diff options
| author | Ataberk <olgunataberk@gmail.com> | 2022-09-25 17:22:03 +0200 |
|---|---|---|
| committer | Ataberk <olgunataberk@gmail.com> | 2022-09-25 17:22:03 +0200 |
| commit | dc0b3db1b4f1895a07e5fe280ee3790e87f97b9f (patch) | |
| tree | b47203aa281bdd959def4451c84d310cd9cf2e12 /sources/hdl/verilog/exe_pipeline.v | |
| download | dram-bender-dc0b3db1b4f1895a07e5fe280ee3790e87f97b9f.tar.gz | |
Initial commit
Diffstat (limited to 'sources/hdl/verilog/exe_pipeline.v')
| -rw-r--r-- | sources/hdl/verilog/exe_pipeline.v | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/sources/hdl/verilog/exe_pipeline.v b/sources/hdl/verilog/exe_pipeline.v new file mode 100644 index 0000000..e2111a3 --- /dev/null +++ b/sources/hdl/verilog/exe_pipeline.v @@ -0,0 +1,191 @@ +`include "parameters.vh" +`include "encoding.vh" + +module exe_pipeline( + // common signals + input clk, + input rst, + + // exe_pipeline <-> execution stage if + input exe_valid, + input [`EXE_UOP_WIDTH-1:0] exe_uop, + input [`IMEM_ADDR_WIDTH-1:0] exe_pc, + + // branch unit if + output br_resolve, + output [`IMEM_ADDR_WIDTH-1:0] br_target, + + // exe_pipeline <-> register file if + output wide_wen, + output [31:0] rf_wdata, + output rf_wen, + output [7:0] rf_raddr, + output [3:0] rf_waddr, + input [2*32-1:0] rf_rdata, + input [32*7-1:0] ddr_stat, + + // exe_pipeline <-> scratchpad + output mem_wen, + output mem_ren, + output [9:0] mem_addr, + output [31:0] mem_wdata, + input [31:0] mem_rdata + ); + + // calculated at stage one, registers + reg s2_valid; + reg [`EXE_UOP_WIDTH-1:0] s2_uop; + reg [`IMEM_ADDR_WIDTH-1:0] s2_pc; + reg [3:0] s2_rs1; + reg [3:0] s2_rs2; + reg [3:0] s2_rt; + reg s2_wen; + reg s2_mem_ren; + reg s2_mem_wen; + reg s3_wen; // for loads + reg [3:0] s3_rt; // for loads + reg s2_wide_wen; + reg [31:0] s2_imd_r, s2_imd_ns; + + // delayed branch resolution signals + // calculated at stage two, registers + reg s3_br_resolve; + reg [`IMEM_ADDR_WIDTH-1:0] s3_br_target; + + // combinational elements + reg [31:0] s2_wdata; + wire [31:0] s2_rs1_data, s2_rs2_data; + reg [31:0] s2_mem_wdata; + reg [`IMEM_ADDR_WIDTH-1:0] fetch_pc; + + assign wide_wen = s2_wide_wen; + assign rf_wdata = s3_wen ? mem_rdata : s2_wdata; + assign rf_wen = s2_wen || s3_wen; + assign rf_raddr[0+:4] = s2_rs1; + assign rf_raddr[4+:4] = s2_rs2; + assign rf_waddr = s3_wen ? s3_rt : s2_rt; + + assign s2_rs1_data = rf_rdata[0+:32]; + assign s2_rs2_data = rf_rdata[32+:32]; + assign br_resolve = s3_br_resolve; + assign br_target = s3_br_target; + + assign mem_addr = s2_rs1_data + s2_imd_r; + assign mem_wen = s2_mem_wen; + assign mem_ren = s2_mem_ren; + assign mem_wdata = s2_mem_wdata; + + always @* begin + // stage one, decode immediate value + s2_mem_wen = `LOW; + s2_imd_ns = s2_imd_r; + fetch_pc = {`IMEM_ADDR_WIDTH{1'bX}}; + s2_wdata = 32'bX; + s2_mem_wen = `LOW; + s2_mem_ren = `LOW; + if(exe_uop[`HAS_IMD]) begin + s2_imd_ns[15:0] = exe_uop[`IMD +: 16]; + s2_imd_ns[31:16] = {16{`LOW}}; + end + if(exe_uop[`IS_LI]) begin + s2_imd_ns[31:16] = exe_uop[`IMD2 +: 16]; + end + if(exe_uop[`IS_BL] | exe_uop[`IS_BEQ]) begin + s2_imd_ns[31:0] = exe_uop[`IMD +: 19]; + end + if(exe_uop[`IS_JUMP]) begin + s2_imd_ns[31:0] = exe_uop[`IMD +: 27]; + end + // stage two, actual computation + if(s2_uop[`IS_ADD]) begin + if(s2_uop[`HAS_IMD]) + s2_wdata = s2_rs1_data + s2_imd_r; + else + s2_wdata = s2_rs1_data + s2_rs2_data; + end + if(s2_uop[`IS_SUB]) begin + if(s2_uop[`HAS_IMD]) + s2_wdata = s2_rs1_data - s2_imd_r; + else + s2_wdata = s2_rs1_data - s2_rs2_data; + end + if(s2_uop[`IS_MOV] || s2_uop[`IS_LDWD]) begin + s2_wdata = s2_rs1_data; + end + if(s2_uop[`IS_LI]) begin + s2_wdata = s2_imd_r; + end + if(s2_uop[`IS_LDPC]) begin + s2_wdata = ddr_stat[s2_rs1*32 +: 32]; + end + if(s2_uop[`IS_SRC]) begin + s2_wdata[30:0] = s2_rs1_data[31:1]; + s2_wdata[31] = s2_rs1_data[0]; + end + // Bitwise ops + if(s2_uop[`IS_AND]) begin + s2_wdata = s2_rs1_data & s2_rs2_data; + end + if(s2_uop[`IS_OR]) begin + s2_wdata = s2_rs1_data | s2_rs2_data; + end + if(s2_uop[`IS_XOR]) begin + s2_wdata = s2_rs1_data ^ s2_rs2_data; + end + // mem unit + if(s2_uop[`IS_LD]) begin + s2_mem_ren = `HIGH; + end + if(s2_uop[`IS_ST]) begin + s2_mem_wdata = s2_rs2_data; + s2_mem_wen = `HIGH; + end + + // branch unit + if(s2_uop[`IS_BL]) begin + if(s2_rs1_data < s2_rs2_data) + fetch_pc = s2_imd_r; + else // not taken + fetch_pc = s2_pc + 1; + end + if(s2_uop[`IS_BEQ]) begin + if(s2_rs1_data == s2_rs2_data) + fetch_pc = s2_imd_r; + else // not taken + fetch_pc = s2_pc + 1; + end + if(s2_uop[`IS_JUMP]) begin + fetch_pc = s2_imd_r; + end + if(s2_uop[`IS_SLEEP]) begin + // not implemented + // frontent/fetch handles api sleeps + end + + end + + always @(posedge clk) begin + // stage one, further decode + s2_valid <= exe_valid; + s2_uop <= exe_uop; + s2_pc <= exe_pc; + s2_rs1 <= exe_uop[`RS1 +: 4]; + s2_rs2 <= exe_uop[`RS2 +: 4]; + s2_rt <= exe_uop[`RT +: 4]; + s2_imd_r <= s2_imd_ns; + s2_wen <= exe_uop[`IS_ADD] || exe_uop[`IS_SUB] || + exe_uop[`IS_MOV] || exe_uop[`IS_LI] || + exe_uop[`IS_LDWD] || exe_uop[`IS_SRC] || + exe_uop[`IS_AND] || exe_uop[`IS_OR] || + exe_uop[`IS_XOR] || exe_uop[`IS_LDPC]; + s2_wide_wen <= exe_uop[`IS_LDWD]; + // stage two, delayed branch signals + s3_br_resolve <= s2_valid && (s2_uop[`IS_BL] || + s2_uop[`IS_BEQ] || + s2_uop[`IS_JUMP]); + s3_br_target <= fetch_pc; + s3_wen <= s2_uop[`IS_LD]; // write path for loads + s3_rt <= s2_uop[`RT +: 4]; + end + +endmodule |
