aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlavian Kaufmann <flavian@flaviankaufmann.ch>2024-05-06 10:40:26 +0200
committerFlavian Kaufmann <flavian@flaviankaufmann.ch>2024-05-06 10:40:26 +0200
commitf2e07b4ae7f4410efaf100e830a51d7dcb0d1b28 (patch)
tree1b67950581c67e492215e195a4b8f798fba7860e
parent3fcb15193438661bd975c7b624f76fa9d130f14b (diff)
downloadriscv_cpu-f2e07b4ae7f4410efaf100e830a51d7dcb0d1b28.tar.gz
riscv_cpu-f2e07b4ae7f4410efaf100e830a51d7dcb0d1b28.zip
added cpu
-rw-r--r--src/cpu.v142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/cpu.v b/src/cpu.v
new file mode 100644
index 0000000..e420252
--- /dev/null
+++ b/src/cpu.v
@@ -0,0 +1,142 @@
+module cpu #(
+ parameter N = 32,
+ parameter XLEN = 32
+)(
+ input clk,
+ input rst
+);
+
+
+wire pc_we;
+wire mem_addr_src;
+wire mem_we;
+wire instr_we;
+wire rf_we;
+wire [1:0] imm_src;
+wire [1:0] alu_src0_src;
+wire [1:0] alu_src1_src;
+wire [3:0] alu_op;
+wire alu_zero;
+wire [1:0] result_src;
+
+reg [N-1:0] result;
+
+
+// Fetch
+reg [N-1:0] pc, pc_old, instr;
+
+
+always @ (posedge clk or posedge rst) begin
+ if (rst) pc <= 32'h0001_0000;
+ else if (pc_we) pc <= result;
+end
+
+always @ (posedge clk) begin
+ if (instr_we) begin
+ pc_old <= pc;
+ instr <= mem_data_read;
+ end
+end
+
+// Memory
+wire [N-1:0] mem_addr;
+assign mem_addr = mem_addr_src ? pc : result;
+
+wire [N-1:0] mem_data_write;
+wire [N-1:0] mem_data_read;
+reg [N-1:0] data;
+
+memory_unit #(.N(N)) mu (
+ .clk(clk),
+ .rst(rst),
+ .we(mem_we),
+ .addr(mem_addr),
+ .data_read(mem_data_read),
+ .data_write(mem_data_write)
+);
+
+always @ (posedge clk) begin
+ data <= mem_data_read;
+end
+
+// Register file
+
+reg [N-1:0] rf_data0_old, rf_data1_old;
+wire [N-1:0] rf_data0, rf_data1;
+
+register_file #(.N(N), .XLEN(XLEN)) rf(
+ .clk(clk),
+ .rst(rst),
+ .we(rf_we),
+ .addr_read0(instr[19:15]),
+ .addr_read1(instr[24:20]),
+ .addr_write2(instr[11:7]),
+ .data_read0(rf_data0),
+ .data_read1(rf_data1),
+ .data_write2(result)
+);
+
+always @ (posedge clk) begin
+ rf_data0_old <= rf_data0;
+ rf_data1_old <= rf_data1;
+end
+
+assign mem_data_write = rf_data1_old;
+
+reg [N-1:0] imm;
+
+always @ (*) begin
+ case (imm_src)
+ 2'b00: imm <= {{20{instr[31]}}, instr[31:20]};
+ 2'b01: imm <= {{20{instr[31]}}, instr[31:25], instr[11:7]};
+ 2'b10: imm <= {{20{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
+ endcase
+end
+
+reg [N-1:0] alu_src0, alu_src1;
+
+always @ (*) begin
+ case(alu_src0_src)
+ 2'b00: alu_src0 <= pc;
+ 2'b01: alu_src0 <= pc_old;
+ 2'b10: alu_src0 <= rf_data0_old;
+ endcase
+end
+
+always @ (*) begin
+ case(alu_src1_src)
+ 2'b00: alu_src1 <= rf_data1_old;
+ 2'b01: alu_src1 <= imm;
+ 2'b10: alu_src1 <= {{(N-3){1'b0}}, 3'h4};
+ endcase
+end
+
+// Execute
+
+wire [N-1:0] alu_result;
+
+alu #(.N(N)) alu (
+ .src0(alu_src0),
+ .src1(alu_src1),
+ .op(alu_op),
+ .result(alu_result),
+ .zero(alu_zero)
+);
+
+reg [N-1:0] alu_out;
+
+always @ (posedge clk) begin
+ alu_out <= alu_result;
+end
+
+always @ (*) begin
+ case (result_src)
+ 2'b00: result <= alu_out;
+ 2'b01: result <= data;
+ 2'b10: result <= alu_result;
+ endcase
+end
+
+
+
+endmodule