diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index 893654c..4a20a4c 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -2,79 +2,62 @@ module serv_decode ( input wire clk, - input wire i_rst, - input wire i_new_irq, + //Input + input wire i_cnt_en, input wire [31:0] i_wb_rdt, input wire i_wb_en, - input wire i_rf_ready, - output wire o_init, - output wire o_run, - output wire o_cnt_en, - output reg [4:0] o_cnt, - output reg [3:0] o_cnt_r, - output wire o_cnt_done, - output reg o_bufreg_hold, + input wire i_alu_cmp, + //To state + output wire o_take_branch, + output wire o_e_op, + output wire o_ebreak, + output wire o_branch_op, + output wire o_mem_op, + output wire o_shift_op, + output wire o_slt_op, + //To bufreg + output wire o_bufreg_loop, output wire o_bufreg_rs1_en, output wire o_bufreg_imm_en, - output wire o_bufreg_loop, - output wire o_ctrl_pc_en, - output reg o_ctrl_jump, + //To ctrl output wire o_ctrl_jalr, output wire o_ctrl_jal_or_jalr, output wire o_ctrl_utype, output wire o_ctrl_pc_rel, - output wire o_ctrl_trap, output reg o_ctrl_mret, - input wire i_ctrl_misalign, - output wire o_rf_rs_en, + //To alu + output wire o_alu_sub, + output wire [1:0] o_alu_bool_op, + output wire o_alu_cmp_eq, + output wire o_alu_cmp_uns, + output wire o_alu_sh_signed, + output wire o_alu_sh_right, + output reg [1:0] o_alu_rd_sel, + //To RF output wire o_rf_rd_en, output reg [4:0] o_rf_rd_addr, output reg [4:0] o_rf_rs1_addr, output reg [4:0] o_rf_rs2_addr, - output wire o_alu_sub, - output wire [1:0] o_alu_bool_op, - output wire o_alu_cmp_eq, - output wire o_alu_cmp_uns, - input wire i_alu_cmp, - output wire o_alu_shamt_en, - output wire o_alu_sh_signed, - output wire o_alu_sh_right, - input wire i_alu_sh_done, - output reg [1:0] o_alu_rd_sel, - output wire o_dbus_cyc, - output wire o_mem_op, + //To mem IF + output reg [2:0] o_funct3, output wire o_mem_cmd, - output wire [1:0] o_mem_bytecnt, - input wire i_mem_misalign, - output wire o_rd_csr_en, + //To CSR output wire o_csr_en, output reg [1:0] o_csr_addr, output wire o_csr_mstatus_en, output wire o_csr_mie_en, output wire o_csr_mcause_en, output wire [1:0] o_csr_source, - output reg [3:0] o_csr_mcause, - output wire o_csr_imm, output wire o_csr_d_sel, - output reg [2:0] o_funct3, + //To top output wire o_imm, output wire o_op_b_source, + output wire o_rd_csr_en, output wire o_rd_alu_en, output wire o_rd_mem_en); `include "serv_params.vh" - localparam [1:0] - IDLE = 2'd0, - INIT = 2'd1, - RUN = 2'd2, - TRAP = 2'd3; - - reg [1:0] state; - - reg cnt_done; - wire cnt_en; - reg [4:0] opcode; reg [31:0] imm; reg op20; @@ -82,28 +65,20 @@ module serv_decode reg op22; reg op26; - wire running; - wire mem_op; - wire shift_op; - wire slt_op; - wire branch_op; - wire e_op; - reg imm30; - assign o_cnt_done = cnt_done; - - assign mem_op = !opcode[4] & !opcode[2] & !opcode[0]; - assign o_mem_op = mem_op; - wire op_or_opimm = (!opcode[4] & opcode[2] & !opcode[0]); - assign shift_op = op_or_opimm & (o_funct3[1:0] == 2'b01); - assign slt_op = op_or_opimm & (o_funct3[2:1] == 2'b01); + assign o_mem_op = !opcode[4] & !opcode[2] & !opcode[0]; + assign o_shift_op = op_or_opimm & (o_funct3[1:0] == 2'b01); + assign o_slt_op = op_or_opimm & (o_funct3[2:1] == 2'b01); + assign o_branch_op = opcode[4] & !opcode[2]; //Matches system opcodes except CSR accesses (o_funct3 == 0) //No idea anymore why the !op21 condition is needed here - assign e_op = opcode[4] & opcode[2] & !op21 & !(|o_funct3); + assign o_e_op = opcode[4] & opcode[2] & !op21 & !(|o_funct3); + + assign o_ebreak = op20; //jal,branch = imm //jalr = rs1+imm @@ -112,21 +87,19 @@ module serv_decode assign o_bufreg_rs1_en = !opcode[4] | (!opcode[1] & opcode[0]); assign o_bufreg_imm_en = !opcode[2]; - //Set loop mode for shift operations + //Loop bufreg contents for shift operations assign o_bufreg_loop = op_or_opimm; - assign o_ctrl_pc_en = running | o_ctrl_trap; - - //Take branch for jump or branch instructions (opcode == 1x0xx) if //a) It's an unconditional branch (opcode[0] == 1) //b) It's a conditional branch (opcode[0] == 0) of type beq,blt,bltu (o_funct3[0] == 0) and ALU compare is true //c) It's a conditional branch (opcode[0] == 0) of type bne,bge,bgeu (o_funct3[0] == 1) and ALU compare is false - wire take_branch = (opcode[4] & !opcode[2]) & (opcode[0] | (i_alu_cmp^o_funct3[0])); + //Only valid during the last cycle of INIT, when the branch condition has + //been calculated. + wire o_take_branch = opcode[4] & !opcode[2] & (opcode[0] | (i_alu_cmp^o_funct3[0])); - assign o_ctrl_jalr = opcode[4] & (opcode[1:0] == 2'b01); - - assign o_ctrl_utype = !opcode[4] & opcode[2] & opcode[0]; + assign o_ctrl_utype = !opcode[4] & opcode[2] & opcode[0]; + assign o_ctrl_jalr = opcode[4] & (opcode[1:0] == 2'b01); assign o_ctrl_jal_or_jalr = opcode[4] & opcode[0]; //True for jal, b* auipc @@ -141,11 +114,7 @@ module serv_decode (!opcode[2] & opcode[4] & opcode[0]) | (!opcode[2] & !opcode[3] & !opcode[0])); - reg alu_sub_r; - assign o_alu_sub = alu_sub_r; - - always @(posedge clk) - alu_sub_r <= opcode[3] & imm30; + assign o_alu_sub = opcode[3] & imm30/*alu_sub_r*/; /* 300 0_000 mstatus RWSC @@ -174,19 +143,14 @@ module serv_decode assign o_csr_source = o_funct3[1:0]; assign o_csr_d_sel = o_funct3[2]; - assign o_csr_imm = (o_cnt < 5) ? o_rf_rs1_addr[o_cnt[2:0]] : 1'b0; - assign o_alu_cmp_eq = o_funct3[2:1] == 2'b00; assign o_alu_cmp_uns = (o_funct3[0] & o_funct3[1]) | (o_funct3[1] & o_funct3[2]); - assign o_alu_shamt_en = (o_cnt < 5) & (state == INIT); assign o_alu_sh_signed = imm30; assign o_alu_sh_right = o_funct3[2]; assign o_mem_cmd = opcode[3]; - assign o_mem_bytecnt = o_cnt[4:3]; - assign o_alu_bool_op = o_funct3[1:0]; wire sign_bit = i_wb_rdt[31]; @@ -246,7 +210,7 @@ module serv_decode stype ? i_wb_rdt[7] : 1'b0; end - if (cnt_en) + if (i_cnt_en) imm <= {imm[0], imm[31:1]}; end @@ -260,100 +224,5 @@ module serv_decode assign o_rd_alu_en = !opcode[0] & opcode[2] & !opcode[4]; assign o_rd_mem_en = !opcode[2] & !opcode[4]; - assign cnt_en = (state != IDLE); - assign o_cnt_en = cnt_en; - assign o_init = (state == INIT); - - assign running = (state == RUN); - assign o_run = running; - - assign o_ctrl_trap = (state == TRAP); - - wire mem_misalign = mem_op & i_mem_misalign; - - always @(posedge clk) begin - o_csr_mcause[3:0] <= 4'd0; - if (mem_misalign) - o_csr_mcause[3:0] <= {2'b01, o_mem_cmd, 1'b0}; - if (e_op) - o_csr_mcause <= {!op20,3'b011}; - end - - - //slt*, branch/jump, shift, load/store - wire two_stage_op = - slt_op | (opcode[4:2] == 3'b110) | (opcode[2:1] == 2'b00) | - shift_op; - reg stage_one_done; - - reg pending_irq; - - assign o_rf_rs_en = two_stage_op ? (state == INIT) : o_ctrl_pc_en; - - assign o_dbus_cyc = (state == IDLE) & stage_one_done & mem_op & !mem_misalign; - - always @(posedge clk) begin - if (state == INIT) - o_ctrl_jump <= take_branch; - if (state == IDLE) - o_ctrl_jump <= 1'b0; - - if (i_new_irq) - pending_irq <= 1'b1; - - cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2]; - - o_bufreg_hold <= 1'b0; - - case (state) - IDLE : begin - if (i_rf_ready) begin - state <= RUN; - if (two_stage_op & !stage_one_done) - state <= INIT; - if (e_op | pending_irq) - state <= TRAP; - end else if (i_alu_sh_done & shift_op & stage_one_done) - state <= RUN; - end - INIT : begin - stage_one_done <= 1'b1; - - if (cnt_done) - if (mem_misalign | (take_branch & i_ctrl_misalign)) - state <= TRAP; - else if (mem_op | shift_op ) begin - state <= IDLE; - o_bufreg_hold <= 1'b1; - end - else - state <= RUN; - end - RUN : begin - stage_one_done <= 1'b0; - if (cnt_done) - state <= IDLE; - end - TRAP : begin - pending_irq <= 1'b0; - if (cnt_done) - state <= IDLE; - end - default : state <= IDLE; - endcase - - o_cnt <= o_cnt + {4'd0,cnt_en}; - if (cnt_en) - o_cnt_r <= {o_cnt_r[2:0],o_cnt_r[3]}; - - if (i_rst) begin - state <= IDLE; - o_cnt <= 5'd0; - pending_irq <= 1'b0; - stage_one_done <= 1'b0; - o_ctrl_jump <= 1'b0; - o_cnt_r <= 4'b0001; - end - end endmodule diff --git a/rtl/serv_state.v b/rtl/serv_state.v new file mode 100644 index 0000000..974129c --- /dev/null +++ b/rtl/serv_state.v @@ -0,0 +1,153 @@ +module serv_state + ( + input wire i_clk, + input wire i_rst, + input wire i_new_irq, + input wire i_rf_ready, + input wire i_take_branch, + input wire i_branch_op, + input wire i_mem_op, + input wire i_shift_op, + input wire i_slt_op, + input wire i_mem_cmd, + input wire i_e_op, + input wire i_ebreak, + input wire [4:0] i_rs1_addr, + output wire o_init, + output wire o_run, + output wire o_cnt_en, + output reg [4:0] o_cnt, + output reg [3:0] o_cnt_r, + output wire o_ctrl_pc_en, + output reg o_ctrl_jump, + output wire o_ctrl_trap, + input wire i_ctrl_misalign, + output wire o_rf_rs_en, + output wire o_alu_shamt_en, + input wire i_alu_sh_done, + output wire o_dbus_cyc, + output wire [1:0] o_mem_bytecnt, + input wire i_mem_misalign, + output reg [3:0] o_csr_mcause, + output wire o_cnt_done, + output reg o_bufreg_hold, + output wire o_csr_imm); + + localparam [1:0] + IDLE = 2'd0, + INIT = 2'd1, + RUN = 2'd2, + TRAP = 2'd3; + + reg [1:0] state; + + reg cnt_done; + wire cnt_en; + wire running; + + assign o_cnt_done = cnt_done; + + //Update PC in RUN or TRAP states + assign o_ctrl_pc_en = running | o_ctrl_trap; + + assign o_csr_imm = (o_cnt < 5) ? i_rs1_addr[o_cnt[2:0]] : 1'b0; + assign o_alu_shamt_en = (o_cnt < 5) & (state == INIT); + + assign o_mem_bytecnt = o_cnt[4:3]; + + assign cnt_en = (state != IDLE); + assign o_cnt_en = cnt_en; + + assign o_init = (state == INIT); + + assign running = (state == RUN); + assign o_run = running; + + assign o_ctrl_trap = (state == TRAP); + + //slt*, branch/jump, shift, load/store + wire two_stage_op = i_slt_op | i_mem_op | i_branch_op | i_shift_op; + + wire mem_misalign = i_mem_op & i_mem_misalign; + + always @(posedge i_clk) begin + o_csr_mcause[3:0] <= 4'd0; + if (mem_misalign) + o_csr_mcause[3:0] <= {2'b01, i_mem_cmd, 1'b0}; + if (i_e_op) + o_csr_mcause <= {!i_ebreak,3'b011}; + end + + reg stage_one_done; + + reg pending_irq; + + assign o_rf_rs_en = two_stage_op ? (state == INIT) : o_ctrl_pc_en; + + assign o_dbus_cyc = (state == IDLE) & stage_one_done & i_mem_op & !mem_misalign; + + always @(posedge i_clk) begin + if (state == INIT) + o_ctrl_jump <= i_take_branch; + if (state == IDLE) + o_ctrl_jump <= 1'b0; + + if (i_new_irq) + pending_irq <= 1'b1; + + cnt_done <= (o_cnt[4:2] == 3'b111) & o_cnt_r[2]; + + o_bufreg_hold <= 1'b0; + + case (state) + IDLE : begin + if (i_rf_ready) begin + state <= RUN; + if (two_stage_op & !stage_one_done) + state <= INIT; + if (i_e_op | pending_irq) + state <= TRAP; + end else if (i_alu_sh_done & i_shift_op & stage_one_done) + state <= RUN; + end + INIT : begin + stage_one_done <= 1'b1; + + if (cnt_done) + if (mem_misalign | (i_take_branch & i_ctrl_misalign)) + state <= TRAP; + else if (i_mem_op | i_shift_op ) begin + state <= IDLE; + o_bufreg_hold <= 1'b1; + end + else + state <= RUN; + end + RUN : begin + stage_one_done <= 1'b0; + if (cnt_done) + state <= IDLE; + end + TRAP : begin + pending_irq <= 1'b0; + if (cnt_done) + state <= IDLE; + end + default : state <= IDLE; + endcase + + o_cnt <= o_cnt + {4'd0,cnt_en}; + if (cnt_en) + o_cnt_r <= {o_cnt_r[2:0],o_cnt_r[3]}; + + if (i_rst) begin + state <= IDLE; + o_cnt <= 5'd0; + pending_irq <= 1'b0; + stage_one_done <= 1'b0; + o_ctrl_jump <= 1'b0; + o_cnt_r <= 4'b0001; + end + end + +endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 5d01aaa..84a14df 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -46,6 +46,14 @@ module serv_top wire [4:0] rs1_addr; wire [4:0] rs2_addr; + wire take_branch; + wire e_op; + wire ebreak; + wire branch_op; + wire mem_op; + wire shift_op; + wire slt_op; + wire rd_alu_en; wire rd_mem_en; wire rd_csr_en; @@ -100,7 +108,6 @@ module serv_top wire op_b_source; wire op_b; - wire mem_op; wire mem_cmd; wire [1:0] mem_bytecnt; @@ -126,15 +133,21 @@ module serv_top wire new_irq; - serv_decode decode + serv_state state ( - .clk (clk), + .i_clk (clk), .i_rst (i_rst), - .o_mem_op (mem_op), .i_new_irq (new_irq), - .i_wb_rdt (i_ibus_rdt), - .i_wb_en (o_ibus_cyc & i_ibus_ack), .i_rf_ready (rf_ready | i_dbus_ack), + .i_take_branch (take_branch), + .i_branch_op (branch_op), + .i_mem_op (mem_op), + .i_shift_op (shift_op), + .i_slt_op (slt_op), + .i_mem_cmd (mem_cmd), + .i_e_op (e_op), + .i_ebreak (ebreak), + .i_rs1_addr (rs1_addr), .o_init (init), .o_run (run), .o_cnt_en (cnt_en), @@ -142,52 +155,75 @@ module serv_top .o_cnt_r (cnt_r), .o_cnt_done (cnt_done), .o_bufreg_hold (bufreg_hold), - .o_bufreg_rs1_en (bufreg_rs1_en), - .o_bufreg_imm_en (bufreg_imm_en), - .o_bufreg_loop (bufreg_loop), .o_ctrl_pc_en (ctrl_pc_en), .o_ctrl_jump (jump), - .o_ctrl_jalr (jalr), - .o_ctrl_jal_or_jalr (jal_or_jalr), - .o_ctrl_utype (utype), - .o_ctrl_pc_rel (pc_rel), .o_ctrl_trap (trap), - .o_ctrl_mret (mret), .i_ctrl_misalign(lsb[1]), - .o_funct3 (funct3), - .o_alu_sub (alu_sub), - .o_alu_bool_op (alu_bool_op), - .o_alu_cmp_eq (alu_cmp_eq), - .o_alu_cmp_uns (alu_cmp_uns), - .i_alu_cmp (alu_cmp), .o_alu_shamt_en (alu_shamt_en), - .o_alu_sh_signed (alu_sh_signed), - .o_alu_sh_right (alu_sh_right), .i_alu_sh_done (alu_sh_done), - .o_alu_rd_sel (alu_rd_sel), .o_rf_rs_en (rs_en), - .o_rf_rd_en (rd_en), - .o_rf_rd_addr (rd_addr), - .o_rf_rs1_addr (rs1_addr), - .o_rf_rs2_addr (rs2_addr), .o_dbus_cyc (o_dbus_cyc), - .o_mem_cmd (mem_cmd), .o_mem_bytecnt (mem_bytecnt), .i_mem_misalign (mem_misalign), - .o_rd_csr_en (rd_csr_en), - .o_csr_en (csr_en), - .o_csr_addr (csr_addr), - .o_csr_mstatus_en (csr_mstatus_en), - .o_csr_mie_en (csr_mie_en), - .o_csr_mcause_en (csr_mcause_en), - .o_csr_source (csr_source), - .o_csr_mcause (mcause), .o_csr_imm (csr_imm), - .o_csr_d_sel (csr_d_sel), - .o_imm (imm), - .o_op_b_source (op_b_source), - .o_rd_alu_en (rd_alu_en), - .o_rd_mem_en (rd_mem_en)); + .o_csr_mcause (mcause)); + + serv_decode decode + ( + .clk (clk), + //Input + .i_cnt_en (cnt_en), + .i_wb_rdt (i_ibus_rdt), + .i_wb_en (o_ibus_cyc & i_ibus_ack), + .i_alu_cmp (alu_cmp), + //To state + .o_take_branch (take_branch), + .o_e_op (e_op), + .o_ebreak (ebreak), + .o_branch_op (branch_op), + .o_mem_op (mem_op), + .o_shift_op (shift_op), + .o_slt_op (slt_op), + //To bufreg + .o_bufreg_loop (bufreg_loop), + .o_bufreg_rs1_en (bufreg_rs1_en), + .o_bufreg_imm_en (bufreg_imm_en), + //To ctrl + .o_ctrl_jalr (jalr), + .o_ctrl_jal_or_jalr (jal_or_jalr), + .o_ctrl_utype (utype), + .o_ctrl_pc_rel (pc_rel), + .o_ctrl_mret (mret), + //To alu + .o_alu_sub (alu_sub), + .o_alu_bool_op (alu_bool_op), + .o_alu_cmp_eq (alu_cmp_eq), + .o_alu_cmp_uns (alu_cmp_uns), + .o_alu_sh_signed (alu_sh_signed), + .o_alu_sh_right (alu_sh_right), + .o_alu_rd_sel (alu_rd_sel), + //To RF + .o_rf_rd_en (rd_en), + .o_rf_rd_addr (rd_addr), + .o_rf_rs1_addr (rs1_addr), + .o_rf_rs2_addr (rs2_addr), + //To mem IF + .o_funct3 (funct3), + .o_mem_cmd (mem_cmd), + //To CSR + .o_csr_en (csr_en), + .o_csr_addr (csr_addr), + .o_csr_mstatus_en (csr_mstatus_en), + .o_csr_mie_en (csr_mie_en), + .o_csr_mcause_en (csr_mcause_en), + .o_csr_source (csr_source), + .o_csr_d_sel (csr_d_sel), + //To top + .o_imm (imm), + .o_op_b_source (op_b_source), + .o_rd_csr_en (rd_csr_en), + .o_rd_alu_en (rd_alu_en), + .o_rd_mem_en (rd_mem_en)); wire [1:0] lsb; wire [31:0] bufreg_out; diff --git a/serv.core b/serv.core index de9b5a9..f37b934 100644 --- a/serv.core +++ b/serv.core @@ -18,6 +18,7 @@ filesets: - rtl/serv_mem_if.v - rtl/serv_regfile.v - rtl/serv_mpram.v + - rtl/serv_state.v - rtl/serv_top.v file_type : verilogSource