diff --git a/rtl/ser_add.v b/rtl/ser_add.v index 798c040..0c9ba57 100644 --- a/rtl/ser_add.v +++ b/rtl/ser_add.v @@ -4,12 +4,15 @@ module ser_add input a, input b, input clr, - output q); + output q, + output o_v); - reg c = 1'b0; + assign o_v = (a&b | a&c_r | b&c_r); - assign q = a ^ b ^ c; + reg c_r = 1'b0; + + assign q = a ^ b ^ c_r; always @(posedge clk) - c <= !clr & (a&b | a&c | b&c); + c_r <= !clr & o_v; endmodule diff --git a/rtl/serv_alu.v b/rtl/serv_alu.v index 3af4e2c..c9b6122 100644 --- a/rtl/serv_alu.v +++ b/rtl/serv_alu.v @@ -3,29 +3,29 @@ module serv_alu ( input clk, input i_en, - input [2:0] i_op, - input [2:0] i_funct3, input i_rs1, input i_op_b, - input i_init, + input i_init, + input i_sub, + input i_cmp_sel, + input i_cmp_neg, output o_cmp, input i_shamt_en, + input [1:0] i_rd_sel, output o_rd); `include "serv_params.vh" - localparam[2:0] - BEQ = 3'b000, - BNE = 3'b001; + wire result_add; + wire result_eq; + reg result_lt = 1'b0; + wire result_sh; - wire result_add; - wire result_eq; - wire result_sh; + wire [4:0] shamt; - wire [4:0] shamt; + reg en_r; + wire v; - reg en_r; - shift_reg #(.LEN (5)) shamt_reg (.clk (clk), .i_en (i_shamt_en), @@ -51,10 +51,10 @@ module serv_alu .a (~i_op_b), .b (plus_1), .clr (!i_en), - .q (b_inv_plus_1)); + .q (b_inv_plus_1), + .o_v ()); - wire add_b = sub ? b_inv_plus_1 : i_op_b; - wire sub = i_op[1]; + wire add_b = i_sub ? b_inv_plus_1 : i_op_b; ser_add ser_add ( @@ -62,7 +62,8 @@ module serv_alu .a (i_rs1), .b (add_b), .clr (!i_en), - .q (result_add)); + .q (result_add), + .o_v (v)); ser_eq ser_eq ( @@ -72,16 +73,17 @@ module serv_alu .clr (!i_init), .o_q (result_eq)); - assign o_cmp = (i_funct3 == BEQ) ? result_eq : - (i_funct3 == BNE) ? ~result_eq : 1'bx; + assign o_cmp = i_cmp_neg^(i_cmp_sel ? result_eq : result_lt); - assign o_rd = (i_op == ALU_OP_ADD) ? result_add : - (i_op == ALU_OP_SUB) ? result_add : - (i_op == ALU_OP_SR) ? result_sh : + assign o_rd = (i_rd_sel == ALU_RESULT_ADD) ? result_add : + (i_rd_sel == ALU_RESULT_SR) ? result_sh : 1'bx; - always @(posedge clk) - en_r <= i_en; - + always @(posedge clk) begin + if (i_init) + result_lt <= /*v^*/result_add; + + en_r <= i_en; + end endmodule diff --git a/rtl/serv_ctrl.v b/rtl/serv_ctrl.v index fcd5b92..0de4af1 100644 --- a/rtl/serv_ctrl.v +++ b/rtl/serv_ctrl.v @@ -5,6 +5,8 @@ module serv_ctrl input i_en, input i_jump, input i_offset, + input i_rs1, + input i_jalr, input i_auipc, output o_rd, output [31:0] o_i_ca_adr, @@ -21,6 +23,8 @@ module serv_ctrl wire pc; wire new_pc; + + wire offset_a; assign plus_4 = en_2r & !en_3r; @@ -32,7 +36,8 @@ module serv_ctrl .a (pc), .b (plus_4), .clr (!i_en), - .q (pc_plus_4)); + .q (pc_plus_4), + .o_v ()); shift_reg #( @@ -49,14 +54,17 @@ module serv_ctrl assign new_pc = i_jump ? pc_plus_offset : pc_plus_4; assign o_rd = i_auipc ? pc_plus_offset : pc_plus_4; + + assign offset_a = i_jalr ? i_rs1 : pc; ser_add ser_add_pc_plus_offset ( .clk (clk), - .a (pc), + .a (offset_a), .b (i_offset), .clr (!i_en), - .q (pc_plus_offset)); + .q (pc_plus_offset), + .o_v ()); reg en_r = 1'b1; reg en_2r = 1'b0; diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index fff8359..4509ece 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -6,6 +6,7 @@ module serv_decode output reg o_i_rd_rdy = 1'b1, output o_ctrl_en, output o_ctrl_jump, + output o_ctrl_jalr, output o_ctrl_auipc, output o_rf_rd_en, output [4:0] o_rf_rd_addr, @@ -13,10 +14,13 @@ module serv_decode output [4:0] o_rf_rs1_addr, output [4:0] o_rf_rs2_addr, output o_alu_en, - output [2:0] o_alu_op, output o_alu_init, + output o_alu_sub, + output o_alu_cmp_sel, + output o_alu_cmp_neg, input i_alu_cmp, output o_alu_shamt_en, + output [1:0] o_alu_rd_sel, output o_mem_en, output o_mem_cmd, output o_mem_init, @@ -46,6 +50,7 @@ module serv_decode OP_OP = 5'b01100, OP_LUI = 5'b01101, OP_BRANCH = 5'b11000, + OP_JALR = 5'b11001, OP_JAL = 5'b11011; reg [2:0] state = 3'd0; @@ -61,8 +66,11 @@ module serv_decode assign o_ctrl_en = running; assign o_ctrl_jump = (opcode == OP_JAL) | + (opcode == OP_JALR) | ((opcode == OP_BRANCH) & i_alu_cmp); + assign o_ctrl_jalr = (opcode == OP_JALR); + assign o_ctrl_auipc = (opcode == OP_AUIPC); assign o_rf_rd_en = running & @@ -72,17 +80,31 @@ module serv_decode assign o_rf_rs_en = cnt_en /*(running & (opcode == OP_OPIMM)) | (state == SH_INIT) | (state == MEM_INIT)*/; - wire sub = (opcode == OP_OP) & i_i_rd_dat[30]; //FIXME: Change for addi? + //FIXME: Change for addi? assign o_alu_en = cnt_en; - assign o_alu_op = (o_funct3 == 3'b000) ? {1'b0, sub, 1'b0} : - (o_funct3 == 3'b101) ? ALU_OP_SR : - 3'bxxx; assign o_alu_init = (state == COMPARE) | (state == SH_INIT); + + assign o_alu_sub = ((opcode == OP_OP) & i_i_rd_dat[30]) ? 1'b1 : + ((opcode == OP_BRANCH) & (o_funct3 == 3'b100)) ? 1'b1 : + ((opcode == OP_OPIMM) & (o_funct3 == 3'b000)) ? 1'b0 : + 1'bx; + + assign o_alu_cmp_sel = (o_funct3[2:1] == 2'b00) ? ALU_CMP_EQ : + (o_funct3[2] == 1'b1) ? ALU_CMP_LT : + (o_funct3[2:1] == 2'b01) ? ALU_CMP_LT : 1'bx; + + assign o_alu_cmp_neg = (opcode == OP_BRANCH) & o_funct3[0]; + assign o_alu_shamt_en = (state == SH_INIT) & (cnt < 5); + assign o_alu_rd_sel = (o_funct3 == 3'b000) ? ALU_RESULT_ADD : + (o_funct3[2:1] == 2'b01) ? ALU_RESULT_LT : + (o_funct3 == 3'b101) ? ALU_RESULT_SR : +2'bxx; + assign o_mem_en = mem_op & cnt_en; assign o_mem_cmd = (opcode == OP_STORE); @@ -92,7 +114,11 @@ module serv_decode assign o_funct3 = i_i_rd_dat[14:12]; assign o_rf_rs1_addr = i_i_rd_dat[19:15]; assign o_rf_rs2_addr = i_i_rd_dat[24:20]; - assign o_offset_source = (opcode == OP_JAL) ? OFFSET_SOURCE_IMM : 1'b0; + assign o_offset_source = (opcode == OP_JAL) ? OFFSET_SOURCE_IMM : + (opcode == OP_AUIPC) ? OFFSET_SOURCE_IMM : + (opcode == OP_BRANCH) ? OFFSET_SOURCE_IMM : + (opcode == OP_JALR) ? OFFSET_SOURCE_IMM : + 1'bx; assign o_op_b_source = (opcode == OP_OPIMM) ? OP_B_SOURCE_IMM : (opcode == OP_BRANCH) ? OP_B_SOURCE_RS2 : @@ -110,6 +136,7 @@ module serv_decode (opcode == OP_OP) ? RD_SOURCE_ALU : (opcode == OP_LUI) ? RD_SOURCE_IMM : (opcode == OP_AUIPC) ? RD_SOURCE_CTRL : + (opcode == OP_JALR) ? RD_SOURCE_CTRL : (opcode == OP_LOAD) ? RD_SOURCE_MEM : 2'bxx; always @(cnt, opcode, i_i_rd_dat) begin @@ -120,7 +147,7 @@ module serv_decode else if (cnt > 10) o_imm = i_i_rd_dat[20]; else if (cnt > 0) o_imm = i_i_rd_dat[cnt+20]; else o_imm = 1'b0; - else if (opcode == OP_OPIMM) + else if ((opcode == OP_OPIMM) | (opcode == OP_JALR)) if (cnt > 10) o_imm = i_i_rd_dat[31]; else o_imm = i_i_rd_dat[cnt+20]; else if ((opcode == OP_LUI) | (opcode == OP_AUIPC)) @@ -179,6 +206,7 @@ module serv_decode if (cnt_done) state <= IDLE; end + default : state <= 3'bxxx; endcase cnt <= cnt + {4'd0,cnt_en}; diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index 8c4483f..972278c 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -41,7 +41,8 @@ module serv_mem_if .a (i_rs1), .b (i_imm), .clr (!i_en), - .q (adr)); + .q (adr), + .o_v ()); shift_reg #(32) shift_reg_adr ( @@ -68,7 +69,7 @@ module serv_mem_if assign o_d_dm_dat = dat; assign o_d_dm_msk = is_word ? 4'b1111 : is_half ? {{2{upper_half}}, ~{2{upper_half}}} : - 1'b1 << bytepos; + 4'd1 << bytepos; always @(posedge i_clk) begin signbit <= dat[0]; diff --git a/rtl/serv_params.vh b/rtl/serv_params.vh index 802aa07..a42bf65 100644 --- a/rtl/serv_params.vh +++ b/rtl/serv_params.vh @@ -6,20 +6,27 @@ localparam [1:0] localparam [0:0] OFFSET_SOURCE_IMM = 1'd0, - OFFSET_SOURCE_RD = 1'd1; + OFFSET_SOURCE_RS1 = 1'd1; localparam [0:0] OP_B_SOURCE_IMM = 1'd0, OP_B_SOURCE_RS2 = 1'd1; -localparam[2:0] - ALU_OP_ADD = 3'd0, - ALU_OP_SL = 3'd1, - ALU_OP_SUB = 3'd2, - ALU_OP_SLT = 3'd3, - ALU_OP_XOR = 3'd4, - ALU_OP_SR = 3'd5, - ALU_OP_OR = 3'd6, - ALU_OP_AND = 3'd7; +localparam[1:0] + ALU_RESULT_ADD = 2'd0, + ALU_RESULT_SR = 2'd1, + ALU_RESULT_LT = 2'd2; - +localparam [0:0] + ALU_CMP_LT = 1'b0, + ALU_CMP_EQ = 1'b1; + +/* + source + ADD, SUB + SL,SR + SLT + XOR, + OR + AND +*/ diff --git a/rtl/serv_top.v b/rtl/serv_top.v index ffbd648..cf8ea08 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -63,6 +63,7 @@ module serv_top wire ctrl_en; wire jump; + wire jalr; wire auipc; wire offset; wire offset_source; @@ -71,10 +72,13 @@ module serv_top wire [2:0] funct3; wire alu_en; - wire [2:0] alu_op; wire alu_init; + wire alu_sub; + wire alu_cmp_sel; + wire alu_cmp_neg; wire alu_cmp; wire alu_shamt_en; + wire [1:0] alu_rd_sel; wire rs1; wire rs2; @@ -102,13 +106,17 @@ module serv_top .o_i_rd_rdy (o_i_rd_rdy), .o_ctrl_en (ctrl_en), .o_ctrl_jump (jump), + .o_ctrl_jalr (jalr), .o_ctrl_auipc (auipc), .o_funct3 (funct3), .o_alu_en (alu_en), - .o_alu_op (alu_op), .o_alu_init (alu_init), + .o_alu_sub (alu_sub), + .o_alu_cmp_sel (alu_cmp_sel), + .o_alu_cmp_neg (alu_cmp_neg), .i_alu_cmp (alu_cmp), .o_alu_shamt_en (alu_shamt_en), + .o_alu_rd_sel (alu_rd_sel), .o_rf_rd_en (rd_en), .o_rf_rd_addr (rd_addr), .o_rf_rs_en (rs_en), @@ -132,13 +140,16 @@ module serv_top .i_en (ctrl_en), .i_jump (jump), .i_offset (offset), + .i_rs1 (rs1), + .i_jalr (jalr), .i_auipc (auipc), .o_rd (ctrl_rd), .o_i_ca_adr (o_i_ca_adr), .o_i_ca_vld (o_i_ca_vld), .i_i_ca_rdy (i_i_ca_rdy)); - assign offset = (offset_source == OFFSET_SOURCE_IMM) ? imm : rs1; + assign offset = (offset_source == OFFSET_SOURCE_IMM) ? imm : + (offset_source == OFFSET_SOURCE_RS1) ? rs1 : 1'bx; assign rd = (rd_source == RD_SOURCE_CTRL) ? ctrl_rd : (rd_source == RD_SOURCE_ALU) ? alu_rd : @@ -154,13 +165,15 @@ module serv_top ( .clk (clk), .i_en (alu_en), - .i_op (alu_op), - .i_funct3 (funct3), - .i_init (alu_init), - .o_cmp (alu_cmp), - .i_shamt_en (alu_shamt_en), .i_rs1 (rs1), .i_op_b (op_b), + .i_init (alu_init), + .i_sub (alu_sub), + .i_cmp_sel (alu_cmp_sel), + .i_cmp_neg (alu_cmp_neg), + .o_cmp (alu_cmp), + .i_shamt_en (alu_shamt_en), + .i_rd_sel (alu_rd_sel), .o_rd (alu_rd)); serv_regfile regfile