diff --git a/rtl/ibex_alu.sv b/rtl/ibex_alu.sv index cdcce5ef..0e40fef1 100644 --- a/rtl/ibex_alu.sv +++ b/rtl/ibex_alu.sv @@ -20,42 +20,35 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Arithmetic logic unit */ -module ibex_alu -( - input logic [ALU_OP_WIDTH-1:0] operator_i, - input logic [31:0] operand_a_i, - input logic [31:0] operand_b_i, +module ibex_alu ( + input logic [ibex_defines::ALU_OP_WIDTH-1:0] operator_i, + input logic [31:0] operand_a_i, + input logic [31:0] operand_b_i, - input logic [32:0] multdiv_operand_a_i, - input logic [32:0] multdiv_operand_b_i, + input logic [32:0] multdiv_operand_a_i, + input logic [32:0] multdiv_operand_b_i, - input logic multdiv_en_i, + input logic multdiv_en_i, - output logic [31:0] adder_result_o, - output logic [33:0] adder_result_ext_o, + output logic [31:0] adder_result_o, + output logic [33:0] adder_result_ext_o, - output logic [31:0] result_o, - output logic comparison_result_o, - output logic is_equal_result_o + output logic [31:0] result_o, + output logic comparison_result_o, + output logic is_equal_result_o ); + import ibex_defines::*; logic [31:0] operand_a_rev; logic [32:0] operand_b_neg; // bit reverse operand_a for left shifts and bit counting - generate - genvar k; - for(k = 0; k < 32; k++) - begin : g_revloop - assign operand_a_rev[k] = operand_a_i[31-k]; - end - endgenerate - + for (genvar k = 0; k < 32; k++) begin : gen_revloop + assign operand_a_rev[k] = operand_a_i[31-k]; + end ///////////////////////////////////// // _ _ _ // @@ -70,8 +63,7 @@ module ibex_alu logic [32:0] adder_in_a, adder_in_b; logic [31:0] adder_result; - always_comb - begin + always_comb begin adder_op_b_negate = 1'b0; unique case (operator_i) @@ -117,15 +109,13 @@ module ibex_alu logic shift_left; // should we shift left logic shift_arithmetic; - logic [31:0] shift_amt; // amount of shift, to the right + logic [4:0] shift_amt; // amount of shift, to the right logic [31:0] shift_op_a; // input of the shifter logic [31:0] shift_result; logic [31:0] shift_right_result; logic [31:0] shift_left_result; - - assign shift_amt = operand_b_i; - + assign shift_amt = operand_b_i[4:0]; assign shift_left = (operator_i == ALU_SLL); @@ -137,22 +127,17 @@ module ibex_alu // right shifts, we let the synthesizer optimize this logic [32:0] shift_op_a_32; - assign shift_op_a_32 = { shift_arithmetic & shift_op_a[31], shift_op_a}; + assign shift_op_a_32 = {shift_arithmetic & shift_op_a[31], shift_op_a}; - assign shift_right_result = $signed(shift_op_a_32) >>> shift_amt[4:0]; + assign shift_right_result = $unsigned($signed(shift_op_a_32) >>> shift_amt[4:0]); // bit reverse the shift_right_result for left shifts - genvar j; - generate - for(j = 0; j < 32; j++) - begin : g_resrevloop - assign shift_left_result[j] = shift_right_result[31-j]; - end - endgenerate + for (genvar j = 0; j < 32; j++) begin : gen_resrevloop + assign shift_left_result[j] = shift_right_result[31-j]; + end assign shift_result = shift_left ? shift_left_result : shift_right_result; - ////////////////////////////////////////////////////////////////// // ____ ___ __ __ ____ _ ____ ___ ____ ___ _ _ // // / ___/ _ \| \/ | _ \ / \ | _ \|_ _/ ___| / _ \| \ | | // @@ -166,8 +151,7 @@ module ibex_alu logic is_greater_equal; // handles both signed and unsigned forms logic cmp_signed; - always_comb - begin + always_comb begin cmp_signed = 1'b0; unique case (operator_i) @@ -189,12 +173,12 @@ module ibex_alu // Is greater equal - always_comb - begin - if ((operand_a_i[31] ^ operand_b_i[31]) == 0) - is_greater_equal = (adder_result[31] == 0); - else + always_comb begin + if ((operand_a_i[31] ^ operand_b_i[31]) == 1'b0) begin + is_greater_equal = (adder_result[31] == 1'b0); + end else begin is_greater_equal = operand_a_i[31] ^ (cmp_signed); + end end // GTE unsigned: @@ -214,20 +198,19 @@ module ibex_alu // generate comparison result logic cmp_result; - always_comb - begin + always_comb begin cmp_result = is_equal; unique case (operator_i) - ALU_EQ: cmp_result = is_equal; - ALU_NE: cmp_result = (~is_equal); - ALU_GTS, ALU_GTU: cmp_result = is_greater_equal && (~is_equal); + ALU_EQ: cmp_result = is_equal; + ALU_NE: cmp_result = ~is_equal; + ALU_GTS, ALU_GTU: cmp_result = is_greater_equal & ~is_equal; ALU_GES, ALU_GEU: cmp_result = is_greater_equal; ALU_LTS, ALU_SLTS, - ALU_LTU, ALU_SLTU: cmp_result = (~is_greater_equal); + ALU_LTU, ALU_SLTU: cmp_result = ~is_greater_equal; ALU_SLETS, ALU_SLETU, - ALU_LES, ALU_LEU: cmp_result = (~is_greater_equal) || is_equal; + ALU_LES, ALU_LEU: cmp_result = ~is_greater_equal | is_equal; default: ; endcase @@ -246,8 +229,7 @@ module ibex_alu // // //////////////////////////////////////////////////////// - always_comb - begin + always_comb begin result_o = '0; unique case (operator_i) @@ -270,7 +252,7 @@ module ibex_alu ALU_GTS, ALU_GES, ALU_LTS, ALU_LES, ALU_SLTS, ALU_SLTU, - ALU_SLETS, ALU_SLETU: result_o = cmp_result; + ALU_SLETS, ALU_SLETU: result_o = {31'h0,cmp_result}; default: ; // default case to suppress unique warning endcase diff --git a/rtl/ibex_compressed_decoder.sv b/rtl/ibex_compressed_decoder.sv index 90fe9cbf..84cedd60 100644 --- a/rtl/ibex_compressed_decoder.sv +++ b/rtl/ibex_compressed_decoder.sv @@ -16,33 +16,30 @@ // // //////////////////////////////////////////////////////////////////////////////// -import ibex_defines::*; - /** * Compressed instruction decoder * * Decodes RISC-V compressed instructions into their RV32 equivalent. * This module is fully combinatorial. */ -module ibex_compressed_decoder -( - input logic [31:0] instr_i, - output logic [31:0] instr_o, - output logic is_compressed_o, - output logic illegal_instr_o +module ibex_compressed_decoder ( + input logic [31:0] instr_i, + output logic [31:0] instr_o, + output logic is_compressed_o, + output logic illegal_instr_o ); + import ibex_defines::*; - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // ____ _ ____ _ // - // / ___|___ _ __ ___ _ __ _ __ ___ ___ ___ ___ __| | | _ \ ___ ___ ___ __| | ___ _ __ // - // | | / _ \| '_ ` _ \| '_ \| '__/ _ \/ __/ __|/ _ \/ _` | | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| // - // | |__| (_) | | | | | | |_) | | | __/\__ \__ \ __/ (_| | | |_| | __/ (_| (_) | (_| | __/ | // - // \____\___/|_| |_| |_| .__/|_| \___||___/___/\___|\__,_| |____/ \___|\___\___/ \__,_|\___|_| // - // |_| // - ////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////// + // ____ __ _ ____ _ // + // / ___|___ _ __ ___ _ __ _ __ /_/ ___ __| | | _ \ ___ ___ ___ __| | ___ _ __ // + // | | / _ \| '_ ` _ \| '_ \| '__/// / __|/ _` | | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| // + // | |__| (_) | | | | | | |_) | | \__ \ (_| | | |_| | __/ (_| (_) | (_| | __/ | // + // \____\___/|_| |_| |_| .__/|_| |___/\__,_| |____/ \___|\___\___/ \__,_|\___|_| // + // |_| // + ///////////////////////////////////////////////////////////////////////////////////////////// - always_comb - begin + always_comb begin illegal_instr_o = 1'b0; instr_o = '0; @@ -52,18 +49,22 @@ module ibex_compressed_decoder unique case (instr_i[15:13]) 3'b000: begin // c.addi4spn -> addi rd', x2, imm - instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], OPCODE_OPIMM}; + instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], + instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], OPCODE_OPIMM}; if (instr_i[12:5] == 8'b0) illegal_instr_o = 1'b1; end 3'b010: begin // c.lw -> lw rd', imm(rs1') - instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], OPCODE_LOAD}; + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], + 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], OPCODE_LOAD}; end 3'b110: begin // c.sw -> sw rs2', imm(rs1') - instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, OPCODE_STORE}; + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], + 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], + 2'b00, OPCODE_STORE}; end default: begin @@ -78,18 +79,22 @@ module ibex_compressed_decoder 3'b000: begin // c.addi -> addi rd, rd, nzimm // c.nop - instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OPIMM}; + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], + instr_i[11:7], 3'b0, instr_i[11:7], OPCODE_OPIMM}; end 3'b001, 3'b101: begin // 001: c.jal -> jal x1, imm // 101: c.j -> jal x0, imm - instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], OPCODE_JAL}; + instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], + instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], + {9 {instr_i[12]}}, 4'b0, ~instr_i[15], OPCODE_JAL}; end 3'b010: begin // c.li -> addi rd, x0, nzimm - instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], OPCODE_OPIMM}; + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, + 3'b0, instr_i[11:7], OPCODE_OPIMM}; if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; end @@ -99,7 +104,8 @@ module ibex_compressed_decoder if (instr_i[11:7] == 5'h02) begin // c.addi16sp -> addi x2, x2, nzimm - instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, OPCODE_OPIMM}; + instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], + instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, OPCODE_OPIMM}; end else if (instr_i[11:7] == 5'b0) begin illegal_instr_o = 1'b1; end @@ -113,36 +119,42 @@ module ibex_compressed_decoder 2'b01: begin // 00: c.srli -> srli rd, rd, shamt // 01: c.srai -> srai rd, rd, shamt - instr_o = {1'b0, instr_i[10], 5'b0, instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], OPCODE_OPIMM}; + instr_o = {1'b0, instr_i[10], 5'b0, instr_i[6:2], 2'b01, instr_i[9:7], + 3'b101, 2'b01, instr_i[9:7], OPCODE_OPIMM}; if (instr_i[12] == 1'b1) illegal_instr_o = 1'b1; if (instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; end 2'b10: begin // c.andi -> andi rd, rd, imm - instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OPIMM}; + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], + 3'b111, 2'b01, instr_i[9:7], OPCODE_OPIMM}; end 2'b11: begin unique case ({instr_i[12], instr_i[6:5]}) 3'b000: begin // c.sub -> sub rd', rd', rs2' - instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], OPCODE_OP}; + instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], + 3'b000, 2'b01, instr_i[9:7], OPCODE_OP}; end 3'b001: begin // c.xor -> xor rd', rd', rs2' - instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, 2'b01, instr_i[9:7], OPCODE_OP}; + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b100, + 2'b01, instr_i[9:7], OPCODE_OP}; end 3'b010: begin // c.or -> or rd', rd', rs2' - instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, 2'b01, instr_i[9:7], OPCODE_OP}; + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b110, + 2'b01, instr_i[9:7], OPCODE_OP}; end 3'b011: begin // c.and -> and rd', rd', rs2' - instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], OPCODE_OP}; + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b111, + 2'b01, instr_i[9:7], OPCODE_OP}; end 3'b100, @@ -161,11 +173,13 @@ module ibex_compressed_decoder 3'b110, 3'b111: begin // 0: c.beqz -> beq rs1', x0, imm // 1: c.bnez -> bne rs1', x0, imm - instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], OPCODE_BRANCH}; + instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, + instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], + instr_i[12], OPCODE_BRANCH}; end default: begin - illegal_instr_o = 1'b1; + // illegal_instr_o = 1'b1; // not reachable, dead code, commenting out end endcase end @@ -182,7 +196,8 @@ module ibex_compressed_decoder 3'b010: begin // c.lwsp -> lw rd, imm(x2) - instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], OPCODE_LOAD}; + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, + 3'b010, instr_i[11:7], OPCODE_LOAD}; if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; end @@ -202,8 +217,7 @@ module ibex_compressed_decoder if (instr_i[11:7] == 5'b0) begin // c.ebreak -> ebreak instr_o = {32'h00_10_00_73}; - if (instr_i[6:2] != 5'b0) - illegal_instr_o = 1'b1; + if (instr_i[6:2] != 5'b0) illegal_instr_o = 1'b1; end else if (instr_i[6:2] == 5'b0) begin // c.jalr -> jalr x1, rs1, 0 instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, OPCODE_JALR}; @@ -213,7 +227,8 @@ module ibex_compressed_decoder 3'b110: begin // c.swsp -> sw rs2, imm(x2) - instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, OPCODE_STORE}; + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, + instr_i[11:9], 2'b00, OPCODE_STORE}; end default: begin diff --git a/rtl/ibex_controller.sv b/rtl/ibex_controller.sv index 03b1a223..c407be34 100644 --- a/rtl/ibex_controller.sv +++ b/rtl/ibex_controller.sv @@ -22,104 +22,105 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Main CPU controller of the processor */ -module ibex_controller -#( - parameter REG_ADDR_WIDTH = 5 -) -( - input logic clk, - input logic rst_n, +module ibex_controller ( + input logic clk, + input logic rst_n, - input logic fetch_enable_i, // Start the decoding - output logic ctrl_busy_o, // Core is busy processing instructions - output logic first_fetch_o, // Core is at the FIRST FETCH stage - output logic is_decoding_o, // Core is in decoding state + input logic fetch_enable_i, // Start the decoding + output logic ctrl_busy_o, // Core is busy processing instructions + output logic first_fetch_o, // Core is at the FIRST FETCH stage + output logic is_decoding_o, // Core is in decoding state - // decoder related signals - output logic deassert_we_o, // deassert write enable for next instruction + // decoder related signals + output logic deassert_we_o, // deassert write enable for next instruction - input logic illegal_insn_i, // decoder encountered an invalid instruction - input logic ecall_insn_i, // ecall encountered an mret instruction - input logic mret_insn_i, // decoder encountered an mret instruction - input logic pipe_flush_i, // decoder wants to do a pipe flush - input logic ebrk_insn_i, // decoder encountered an ebreak instruction - input logic csr_status_i, // decoder encountered an csr status instruction + input logic illegal_insn_i, // decoder encountered an invalid instruction + input logic ecall_insn_i, // ecall encountered an mret instruction + input logic mret_insn_i, // decoder encountered an mret instruction + input logic pipe_flush_i, // decoder wants to do a pipe flush + input logic ebrk_insn_i, // decoder encountered an ebreak instruction + input logic csr_status_i, // decoder encountered an csr status instruction - // from IF/ID pipeline - input logic instr_valid_i, // instruction coming from IF/ID pipeline is valid + // from IF/ID pipeline + input logic instr_valid_i, // instruction coming from IF/ID pipeline is + // valid - // from prefetcher - output logic instr_req_o, // Start fetching instructions + // from prefetcher + output logic instr_req_o, // Start fetching instructions - // to prefetcher - output logic pc_set_o, // jump to address set by pc_mux - output logic [2:0] pc_mux_o, // Selector in the Fetch stage to select the rigth PC (normal, jump ...) - output logic [1:0] exc_pc_mux_o, // Selects target PC for exception + // to prefetcher + output logic pc_set_o, // jump to address set by pc_mux + output logic [2:0] pc_mux_o, // Selector in the Fetch stage to select the + // right PC (normal, jump ...) + output logic [1:0] exc_pc_mux_o, // Selects target PC for exception - // LSU - input logic data_misaligned_i, + // LSU + input logic data_misaligned_i, - // jump/branch signals - input logic branch_in_id_i, // branch in id - input logic branch_taken_ex_i, // branch taken signal - input logic branch_set_i, // branch taken set signal - input logic jump_set_i, // jump taken set signal + // jump/branch signals + input logic branch_in_id_i, // branch in id + input logic branch_taken_ex_i, // branch taken signal + input logic branch_set_i, // branch taken set signal + input logic jump_set_i, // jump taken set signal - input logic instr_multicyle_i, // multicycle instructions active + input logic instr_multicyle_i, // multicycle instructions active - // External Interrupt Req Signals, used to wake up from wfi even if the interrupt is not taken - input logic irq_i, - // Interrupt Controller Signals - input logic irq_req_ctrl_i, - input logic [4:0] irq_id_ctrl_i, - input logic m_IE_i, // interrupt enable bit from CSR (M mode) + // External Interrupt Req Signals, used to wake up from wfi even if the interrupt is not taken + input logic irq_i, + // Interrupt Controller Signals + input logic irq_req_ctrl_i, + input logic [4:0] irq_id_ctrl_i, + input logic m_IE_i, // interrupt enable bit from CSR (M mode) - output logic irq_ack_o, - output logic [4:0] irq_id_o, + output logic irq_ack_o, + output logic [4:0] irq_id_o, - output logic [5:0] exc_cause_o, - output logic exc_ack_o, - output logic exc_kill_o, + output logic [5:0] exc_cause_o, + output logic exc_ack_o, + output logic exc_kill_o, - output logic csr_save_if_o, - output logic csr_save_id_o, - output logic [5:0] csr_cause_o, - output logic csr_restore_mret_id_o, - output logic csr_save_cause_o, + output logic csr_save_if_o, + output logic csr_save_id_o, + output logic [5:0] csr_cause_o, + output logic csr_restore_mret_id_o, + output logic csr_save_cause_o, - // Debug Signals - input logic dbg_req_i, // a trap was hit, so we have to flush EX and WB - output logic dbg_ack_o, // we stopped and give control to debug now + // Debug Signals + input logic dbg_req_i, // a trap was hit, so we have to flush EX and WB + output logic dbg_ack_o, // we stopped and give control to debug now - input logic dbg_stall_i, // Pipeline stall is requested - input logic dbg_jump_req_i, // Change PC to value from debug unit + input logic dbg_stall_i, // Pipeline stall is requested + input logic dbg_jump_req_i, // Change PC to value from debug unit - input logic [DBG_SETS_W-1:0] dbg_settings_i, - output logic dbg_trap_o, + input logic [DBG_SETS_W-1:0] dbg_settings_i, + output logic dbg_trap_o, - // forwarding signals - output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage + // forwarding signals + output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage - // stall signals - output logic halt_if_o, - output logic halt_id_o, + // stall signals + output logic halt_if_o, + output logic halt_id_o, - input logic id_ready_i, // ID stage is ready + input logic id_ready_i, // ID stage is ready - // Performance Counters - output logic perf_jump_o, // we are executing a jump instruction (j, jr, jal, jalr) - output logic perf_tbranch_o // we are executing a taken branch instruction + // Performance Counters + output logic perf_jump_o, // we are executing a jump instruction + // (j, jr, jal, jalr) + output logic perf_tbranch_o // we are executing a taken branch instruction ); + import ibex_defines::*; // FSM state encoding - enum logic [3:0] { RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, - DECODE, FLUSH, IRQ_TAKEN, - DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH } ctrl_fsm_cs, ctrl_fsm_ns; + typedef enum logic [3:0] { + RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH, DECODE, FLUSH, + IRQ_TAKEN, DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH + } ctrl_fsm_e; + + ctrl_fsm_e ctrl_fsm_cs, ctrl_fsm_ns; logic irq_enable_int; @@ -127,8 +128,7 @@ module ibex_controller // synopsys translate_off // make sure we are called later so that we do not generate messages for // glitches - always_ff @(negedge clk) - begin + always_ff @(negedge clk) begin // print warning in case of decoding errors if (is_decoding_o && illegal_insn_i) begin $display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, ibex_core.core_id_i, @@ -149,8 +149,7 @@ module ibex_controller //////////////////////////////////////////////////////////////////////////////////////////// - always_comb - begin + always_comb begin // Default values instr_req_o = 1'b1; @@ -197,13 +196,12 @@ module ibex_controller unique case (ctrl_fsm_cs) // We were just reset, wait for fetch_enable - RESET: - begin + RESET: begin instr_req_o = 1'b0; - if (fetch_enable_i == 1'b1) + if (fetch_enable_i) begin ctrl_fsm_ns = BOOT_SET; - else if (dbg_req_i) begin + end else if (dbg_req_i) begin // just go to debug even when we did not yet get a fetch enable // this means that the NPC will not be set yet ctrl_fsm_ns = DBG_SIGNAL; @@ -211,8 +209,7 @@ module ibex_controller end // copy boot address to instr fetch address - BOOT_SET: - begin + BOOT_SET: begin instr_req_o = 1'b1; pc_mux_o = PC_BOOT; pc_set_o = 1'b1; @@ -220,8 +217,7 @@ module ibex_controller ctrl_fsm_ns = FIRST_FETCH; end - WAIT_SLEEP: - begin + WAIT_SLEEP: begin ctrl_busy_o = 1'b0; instr_req_o = 1'b0; halt_if_o = 1'b1; @@ -230,8 +226,7 @@ module ibex_controller end // instruction in if_stage is already valid - SLEEP: - begin + SLEEP: begin // we begin execution when an // interrupt has arrived ctrl_busy_o = 1'b0; @@ -243,28 +238,25 @@ module ibex_controller if (dbg_req_i) begin // debug request, now we need to check if we should stay sleeping or // go to normal processing later - ctrl_fsm_ns = DBG_SIGNAL_SLEEP; + ctrl_fsm_ns = DBG_SIGNAL_SLEEP; end else begin // no debug request incoming, normal execution flow // here transparent interrupts are checked to wake up from wfi - if (irq_i) - begin + if (irq_i) begin ctrl_fsm_ns = FIRST_FETCH; end end end - FIRST_FETCH: - begin + FIRST_FETCH: begin first_fetch_o = 1'b1; // Stall because of IF miss - if ((id_ready_i == 1'b1) && (dbg_stall_i == 1'b0)) - begin + if (id_ready_i && !dbg_stall_i) begin ctrl_fsm_ns = DECODE; end - if (irq_req_ctrl_i & irq_enable_int) begin + if (irq_req_ctrl_i && irq_enable_int) begin // This assumes that the pipeline is always flushed before // going to sleep. ctrl_fsm_ns = IRQ_TAKEN; @@ -273,82 +265,76 @@ module ibex_controller end end - DECODE: - begin + DECODE: begin is_decoding_o = 1'b0; - // decode and execute instructions only if the current conditional - // branch in the EX stage is either not taken, or there is no - // conditional branch in the EX stage - if (instr_valid_i) - begin // now analyze the current instruction in the ID stage - is_decoding_o = 1'b1; + // decode and execute instructions only if the current conditional + // branch in the EX stage is either not taken, or there is no + // conditional branch in the EX stage + if (instr_valid_i) begin // now analyze the current instruction in the ID stage + is_decoding_o = 1'b1; - if (branch_set_i & ~jump_set_i & ~(mret_insn_i | ecall_insn_i | pipe_flush_i | ebrk_insn_i | illegal_insn_i | csr_status_i)) - begin - pc_mux_o = PC_JUMP; - pc_set_o = 1'b1; - perf_tbranch_o = 1'b1; - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; - if (dbg_req_i) - ctrl_fsm_ns = DBG_SIGNAL; - end - else if (~branch_set_i & jump_set_i & ~(mret_insn_i | ecall_insn_i | pipe_flush_i | ebrk_insn_i | illegal_insn_i | csr_status_i)) - begin - pc_mux_o = PC_JUMP; - pc_set_o = 1'b1; - perf_jump_o = 1'b1; - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; - end - else if (~branch_set_i & ~jump_set_i & (mret_insn_i | ecall_insn_i | pipe_flush_i | ebrk_insn_i | illegal_insn_i | csr_status_i)) - begin - ctrl_fsm_ns = FLUSH; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - end - else - begin - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + if (branch_set_i && !jump_set_i && + !(mret_insn_i || ecall_insn_i || pipe_flush_i || ebrk_insn_i || + illegal_insn_i || csr_status_i)) begin + pc_mux_o = PC_JUMP; + pc_set_o = 1'b1; + perf_tbranch_o = 1'b1; + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + if (dbg_req_i) begin + ctrl_fsm_ns = DBG_SIGNAL; + end + end else if (!branch_set_i && jump_set_i && + !(mret_insn_i || ecall_insn_i || pipe_flush_i || + ebrk_insn_i || illegal_insn_i || csr_status_i)) begin + pc_mux_o = PC_JUMP; + pc_set_o = 1'b1; + perf_jump_o = 1'b1; + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + end else if (!branch_set_i && !jump_set_i && + (mret_insn_i || ecall_insn_i || pipe_flush_i || + ebrk_insn_i || illegal_insn_i || csr_status_i)) begin + ctrl_fsm_ns = FLUSH; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + end else begin + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; - if ((irq_req_ctrl_i & irq_enable_int & ~instr_multicyle_i & ~branch_in_id_i) & ~(dbg_req_i & ~branch_taken_ex_i)) - begin - ctrl_fsm_ns = IRQ_TAKEN; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - end - else if (~(irq_req_ctrl_i & irq_enable_int & ~instr_multicyle_i & ~branch_in_id_i) & (dbg_req_i & ~branch_taken_ex_i)) - begin - halt_if_o = 1'b1; - if (id_ready_i) begin - ctrl_fsm_ns = DBG_SIGNAL; - end - end - else - exc_kill_o = irq_req_ctrl_i & ~instr_multicyle_i & ~branch_in_id_i ? 1'b1 : 1'b0; + if (irq_req_ctrl_i && irq_enable_int && !instr_multicyle_i && !branch_in_id_i && + !(dbg_req_i && !branch_taken_ex_i)) begin + ctrl_fsm_ns = IRQ_TAKEN; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + end else if (!(irq_req_ctrl_i && irq_enable_int && + !instr_multicyle_i && !branch_in_id_i) && + (dbg_req_i && !branch_taken_ex_i)) begin + halt_if_o = 1'b1; + if (id_ready_i) begin + ctrl_fsm_ns = DBG_SIGNAL; end + end else begin + exc_kill_o = irq_req_ctrl_i & ~instr_multicyle_i & ~branch_in_id_i; + end end - else //~instr_valid_i - begin - if (irq_req_ctrl_i & irq_enable_int) begin - ctrl_fsm_ns = IRQ_TAKEN; - halt_if_o = 1'b1; - halt_id_o = 1'b1; - end + end else begin // !instr_valid_i + if (irq_req_ctrl_i && irq_enable_int) begin + ctrl_fsm_ns = IRQ_TAKEN; + halt_if_o = 1'b1; + halt_id_o = 1'b1; end + end end // now we can signal to the debugger that our pipeline is empty and it // can examine our current state - DBG_SIGNAL: - begin + DBG_SIGNAL: begin dbg_ack_o = 1'b1; halt_if_o = 1'b1; ctrl_fsm_ns = DBG_WAIT; end - DBG_SIGNAL_SLEEP: - begin + DBG_SIGNAL_SLEEP: begin dbg_ack_o = 1'b1; halt_if_o = 1'b1; @@ -357,8 +343,7 @@ module ibex_controller // The Debugger is active in this state // we wait until it is done and go back to DECODE - DBG_WAIT: - begin + DBG_WAIT: begin halt_if_o = 1'b1; if (dbg_jump_req_i) begin @@ -367,13 +352,12 @@ module ibex_controller ctrl_fsm_ns = DBG_WAIT; end - if (dbg_stall_i == 1'b0) begin + if (!dbg_stall_i) begin ctrl_fsm_ns = DECODE; end end - IRQ_TAKEN: - begin + IRQ_TAKEN: begin pc_mux_o = PC_EXCEPTION; pc_set_o = 1'b1; @@ -392,8 +376,7 @@ module ibex_controller end // flush the pipeline, insert NOP - FLUSH: - begin + FLUSH: begin halt_if_o = 1'b1; halt_id_o = 1'b1; @@ -402,57 +385,62 @@ module ibex_controller unique case(1'b1) ecall_insn_i: begin - //ecall - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - csr_save_id_o = 1'b1; - csr_save_cause_o = 1'b1; - exc_pc_mux_o = EXC_PC_ECALL; - exc_cause_o = EXC_CAUSE_ECALL_MMODE; - csr_cause_o = EXC_CAUSE_ECALL_MMODE; - dbg_trap_o = dbg_settings_i[DBG_SETS_ECALL] | dbg_settings_i[DBG_SETS_SSTE]; + //ecall + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + csr_save_id_o = 1'b1; + csr_save_cause_o = 1'b1; + exc_pc_mux_o = EXC_PC_ECALL; + exc_cause_o = EXC_CAUSE_ECALL_MMODE; + csr_cause_o = EXC_CAUSE_ECALL_MMODE; + dbg_trap_o = dbg_settings_i[DBG_SETS_ECALL] | + dbg_settings_i[DBG_SETS_SSTE]; end illegal_insn_i: begin - //exceptions - pc_mux_o = PC_EXCEPTION; - pc_set_o = 1'b1; - csr_save_id_o = 1'b1; - csr_save_cause_o = 1'b1; - exc_pc_mux_o = EXC_PC_ILLINSN; - exc_cause_o = EXC_CAUSE_ILLEGAL_INSN; - csr_cause_o = EXC_CAUSE_ILLEGAL_INSN; - dbg_trap_o = dbg_settings_i[DBG_SETS_EILL] | dbg_settings_i[DBG_SETS_SSTE]; + //exceptions + pc_mux_o = PC_EXCEPTION; + pc_set_o = 1'b1; + csr_save_id_o = 1'b1; + csr_save_cause_o = 1'b1; + exc_pc_mux_o = EXC_PC_ILLINSN; + exc_cause_o = EXC_CAUSE_ILLEGAL_INSN; + csr_cause_o = EXC_CAUSE_ILLEGAL_INSN; + dbg_trap_o = dbg_settings_i[DBG_SETS_EILL] | + dbg_settings_i[DBG_SETS_SSTE]; end mret_insn_i: begin - //mret - pc_mux_o = PC_ERET; - pc_set_o = 1'b1; - csr_restore_mret_id_o = 1'b1; - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + //mret + pc_mux_o = PC_ERET; + pc_set_o = 1'b1; + csr_restore_mret_id_o = 1'b1; + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; end ebrk_insn_i: begin - dbg_trap_o = 1'b1;//dbg_settings_i[DBG_SETS_EBRK] | dbg_settings_i[DBG_SETS_SSTE];; - exc_cause_o = EXC_CAUSE_BREAKPOINT; + dbg_trap_o = 1'b1; // dbg_settings_i[DBG_SETS_EBRK] | + // dbg_settings_i[DBG_SETS_SSTE]; + exc_cause_o = EXC_CAUSE_BREAKPOINT; end csr_status_i: begin - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; end pipe_flush_i: begin - dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; + dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE]; end default:; endcase - if(~pipe_flush_i) begin - if(dbg_req_i) + if (!pipe_flush_i) begin + if (dbg_req_i) begin ctrl_fsm_ns = DBG_SIGNAL; - else + end else begin ctrl_fsm_ns = DECODE; + end end else begin - if(dbg_req_i) + if (dbg_req_i) begin ctrl_fsm_ns = DBG_SIGNAL_SLEEP; - else + end else begin ctrl_fsm_ns = WAIT_SLEEP; + end end end @@ -471,33 +459,20 @@ module ibex_controller // |____/ \__\__,_|_|_| \____\___/|_| |_|\__|_| \___/|_| // // // ///////////////////////////////////////////////////////////// - always_comb - begin - deassert_we_o = 1'b0; - - // deassert WE when the core is not decoding instructions - if (~is_decoding_o) - deassert_we_o = 1'b1; - - // deassert WE in case of illegal instruction - if (illegal_insn_i) - deassert_we_o = 1'b1; - end + // deassert WE when the core is not decoding instructions + // or in case of illegal instruction + assign deassert_we_o = ~is_decoding_o | illegal_insn_i; // Forwarding control unit assign operand_a_fw_mux_sel_o = data_misaligned_i ? SEL_MISALIGNED : SEL_REGFILE; // update registers - always_ff @(posedge clk , negedge rst_n) - begin : UPDATE_REGS - if ( rst_n == 1'b0 ) - begin + always_ff @(posedge clk, negedge rst_n) begin : UPDATE_REGS + if (!rst_n) begin ctrl_fsm_cs <= RESET; //jump_done_q <= 1'b0; - end - else - begin + end else begin ctrl_fsm_cs <= ctrl_fsm_ns; // clear when id is valid (no instruction incoming) //jump_done_q <= jump_done & (~id_ready_i); @@ -510,6 +485,7 @@ module ibex_controller //---------------------------------------------------------------------------- `ifndef VERILATOR assert property ( - @(posedge clk) (~(dbg_req_i & irq_req_ctrl_i)) ) else $warning("Both dbg_req_i and irq_req_ctrl_i are active"); + @(posedge clk) (!(dbg_req_i && irq_req_ctrl_i)) ) else + $warning("Both dbg_req_i and irq_req_ctrl_i are active"); `endif endmodule // controller diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 6a471971..10b86a08 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -23,74 +23,69 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Top level module of the ibex RISC-V core */ -module ibex_core -#( - parameter N_EXT_PERF_COUNTERS = 0, - parameter RV32E = 0, - parameter RV32M = 1 -) -( - // Clock and Reset - input logic clk_i, - input logic rst_ni, +module ibex_core #( + parameter N_EXT_PERF_COUNTERS = 1, + parameter RV32E = 0, + parameter RV32M = 1 +) ( + // Clock and Reset + input logic clk_i, + input logic rst_ni, - input logic clock_en_i, // enable clock, otherwise it is gated - input logic test_en_i, // enable all clock gates for testing + input logic clock_en_i, // enable clock, otherwise it is gated + input logic test_en_i, // enable all clock gates for testing - // Core ID, Cluster ID and boot address are considered more or less static - input logic [ 3:0] core_id_i, - input logic [ 5:0] cluster_id_i, - input logic [31:0] boot_addr_i, + // Core ID, Cluster ID and boot address are considered more or less static + input logic [ 3:0] core_id_i, + input logic [ 5:0] cluster_id_i, + input logic [31:0] boot_addr_i, - // Instruction memory interface - output logic instr_req_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - output logic [31:0] instr_addr_o, - input logic [31:0] instr_rdata_i, + // Instruction memory interface + output logic instr_req_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, - // Data memory interface - output logic data_req_o, - input logic data_gnt_i, - input logic data_rvalid_i, - output logic data_we_o, - output logic [3:0] data_be_o, - output logic [31:0] data_addr_o, - output logic [31:0] data_wdata_o, - input logic [31:0] data_rdata_i, - input logic data_err_i, + // Data memory interface + output logic data_req_o, + input logic data_gnt_i, + input logic data_rvalid_i, + output logic data_we_o, + output logic [3:0] data_be_o, + output logic [31:0] data_addr_o, + output logic [31:0] data_wdata_o, + input logic [31:0] data_rdata_i, + input logic data_err_i, - // Interrupt inputs - input logic irq_i, // level sensitive IR lines - input logic [4:0] irq_id_i, - output logic irq_ack_o, // irq ack - output logic [4:0] irq_id_o, + // Interrupt inputs + input logic irq_i, // level sensitive IR lines + input logic [4:0] irq_id_i, + output logic irq_ack_o, // irq ack + output logic [4:0] irq_id_o, - // Debug Interface - input logic debug_req_i, - output logic debug_gnt_o, - output logic debug_rvalid_o, - input logic [14:0] debug_addr_i, - input logic debug_we_i, - input logic [31:0] debug_wdata_i, - output logic [31:0] debug_rdata_o, - output logic debug_halted_o, - input logic debug_halt_i, - input logic debug_resume_i, + // Debug Interface + input logic debug_req_i, + output logic debug_gnt_o, + output logic debug_rvalid_o, + input logic [14:0] debug_addr_i, + input logic debug_we_i, + input logic [31:0] debug_wdata_i, + output logic [31:0] debug_rdata_o, + output logic debug_halted_o, + input logic debug_halt_i, + input logic debug_resume_i, - // CPU Control Signals - input logic fetch_enable_i, + // CPU Control Signals + input logic fetch_enable_i, - input logic [N_EXT_PERF_COUNTERS-1:0] ext_perf_counters_i + input logic [N_EXT_PERF_COUNTERS-1:0] ext_perf_counters_i ); - localparam N_HWLP = 2; - localparam N_HWLP_BITS = $clog2(N_HWLP); + import ibex_defines::*; // IF/ID signals logic instr_valid_id; @@ -117,7 +112,6 @@ module ibex_core // Jump and branch target and decision (EX->IF) logic [31:0] jump_target_ex; - logic branch_in_ex; logic branch_decision; logic ctrl_busy; @@ -161,7 +155,6 @@ module ibex_core logic [1:0] data_reg_offset_ex; logic data_req_ex; logic [31:0] data_wdata_ex; - logic data_misaligned_ex; logic [31:0] regfile_wdata_lsu; // stall control @@ -171,9 +164,7 @@ module ibex_core logic if_valid; logic id_valid; - logic wb_valid; - logic lsu_ready_ex; logic data_valid_lsu; // Signals between instruction core interface and pipe (if and id stages) @@ -188,7 +179,6 @@ module ibex_core logic csr_save_id; logic [5:0] csr_cause; logic csr_restore_mret_id; - logic csr_restore_uret_id; // Debug Unit logic [DBG_SETS_W-1:0] dbg_settings; @@ -243,9 +233,8 @@ module ibex_core // interface to finish loading instructions assign core_busy_int = if_busy | ctrl_busy | lsu_busy; - always_ff @(posedge clk_i, negedge rst_ni) - begin - if (rst_ni == 1'b0) begin + always_ff @(posedge clk_i, negedge rst_ni) begin + if (!rst_ni) begin core_busy_q <= 1'b0; end else begin core_busy_q <= core_busy_int; @@ -264,12 +253,11 @@ module ibex_core // main clock gate of the core // generates all clocks except the one for the debug unit which is // independent - clock_gating core_clock_gate_i - ( - .clk_i ( clk_i ), - .en_i ( clock_en ), - .test_en_i ( test_en_i ), - .clk_o ( clk ) + prim_clock_gating core_clock_gate_i ( + .clk_i ( clk_i ), + .en_i ( clock_en ), + .test_en_i ( test_en_i ), + .clk_o ( clk ) ); ////////////////////////////////////////////////// @@ -280,54 +268,53 @@ module ibex_core // |___|_| |____/ |_/_/ \_\____|_____| // // // ////////////////////////////////////////////////// - ibex_if_stage if_stage_i - ( - .clk ( clk ), - .rst_n ( rst_ni ), + ibex_if_stage if_stage_i ( + .clk ( clk ), + .rst_n ( rst_ni ), - // boot address (trap vector location) - .boot_addr_i ( boot_addr_i ), + // boot address (trap vector location) + .boot_addr_i ( boot_addr_i ), - // instruction request control - .req_i ( instr_req_int ), + // instruction request control + .req_i ( instr_req_int ), - // instruction cache interface - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), + // instruction cache interface + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), - // outputs to ID stage - .instr_valid_id_o ( instr_valid_id ), - .instr_rdata_id_o ( instr_rdata_id ), - .is_compressed_id_o ( is_compressed_id ), - .illegal_c_insn_id_o ( illegal_c_insn_id ), - .pc_if_o ( pc_if ), - .pc_id_o ( pc_id ), + // outputs to ID stage + .instr_valid_id_o ( instr_valid_id ), + .instr_rdata_id_o ( instr_rdata_id ), + .is_compressed_id_o ( is_compressed_id ), + .illegal_c_insn_id_o ( illegal_c_insn_id ), + .pc_if_o ( pc_if ), + .pc_id_o ( pc_id ), - // control signals - .clear_instr_valid_i ( clear_instr_valid ), - .pc_set_i ( pc_set ), - .exception_pc_reg_i ( mepc ), // exception return address - .pc_mux_i ( pc_mux_id ), // sel for pc multiplexer - .exc_pc_mux_i ( exc_pc_mux_id ), - .exc_vec_pc_mux_i ( exc_cause[4:0] ), + // control signals + .clear_instr_valid_i ( clear_instr_valid ), + .pc_set_i ( pc_set ), + .exception_pc_reg_i ( mepc ), // exception return address + .pc_mux_i ( pc_mux_id ), // sel for pc multiplexer + .exc_pc_mux_i ( exc_pc_mux_id ), + .exc_vec_pc_mux_i ( exc_cause[4:0] ), - // from debug unit - .dbg_jump_addr_i ( dbg_jump_addr ), + // from debug unit + .dbg_jump_addr_i ( dbg_jump_addr ), - // Jump targets - .jump_target_ex_i ( jump_target_ex ), + // Jump targets + .jump_target_ex_i ( jump_target_ex ), - // pipeline stalls - .halt_if_i ( halt_if ), - .id_ready_i ( id_ready ), - .if_valid_o ( if_valid ), + // pipeline stalls + .halt_if_i ( halt_if ), + .id_ready_i ( id_ready ), + .if_valid_o ( if_valid ), - .if_busy_o ( if_busy ), - .perf_imiss_o ( perf_imiss ) + .if_busy_o ( if_busy ), + .perf_imiss_o ( perf_imiss ) ); @@ -339,157 +326,150 @@ module ibex_core // |___|____/ |____/ |_/_/ \_\____|_____| // // // ///////////////////////////////////////////////// - ibex_id_stage - #( - .RV32E(RV32E), - .RV32M(RV32M) - ) - id_stage_i - ( - .clk ( clk ), - .rst_n ( rst_ni ), + ibex_id_stage #( + .RV32E(RV32E), + .RV32M(RV32M) + ) id_stage_i ( + .clk ( clk ), + .rst_n ( rst_ni ), - .test_en_i ( test_en_i ), + .test_en_i ( test_en_i ), - // Processor Enable - .fetch_enable_i ( fetch_enable_i ), - .ctrl_busy_o ( ctrl_busy ), - .core_ctrl_firstfetch_o ( core_ctrl_firstfetch ), - .is_decoding_o ( is_decoding ), + // Processor Enable + .fetch_enable_i ( fetch_enable_i ), + .ctrl_busy_o ( ctrl_busy ), + .core_ctrl_firstfetch_o ( core_ctrl_firstfetch ), + .is_decoding_o ( is_decoding ), - // Interface to instruction memory - .instr_valid_i ( instr_valid_id ), - .instr_rdata_i ( instr_rdata_id ), - .instr_req_o ( instr_req_int ), + // Interface to instruction memory + .instr_valid_i ( instr_valid_id ), + .instr_rdata_i ( instr_rdata_id ), + .instr_req_o ( instr_req_int ), - // Jumps and branches - .branch_in_ex_o ( branch_in_ex ), - .branch_decision_i ( branch_decision ), + // Jumps and branches + .branch_decision_i ( branch_decision ), - // IF and ID control signals - .clear_instr_valid_o ( clear_instr_valid ), - .pc_set_o ( pc_set ), - .pc_mux_o ( pc_mux_id ), - .exc_pc_mux_o ( exc_pc_mux_id ), - .exc_cause_o ( exc_cause ), + // IF and ID control signals + .clear_instr_valid_o ( clear_instr_valid ), + .pc_set_o ( pc_set ), + .pc_mux_o ( pc_mux_id ), + .exc_pc_mux_o ( exc_pc_mux_id ), + .exc_cause_o ( exc_cause ), - .illegal_c_insn_i ( illegal_c_insn_id ), - .is_compressed_i ( is_compressed_id ), + .illegal_c_insn_i ( illegal_c_insn_id ), + .is_compressed_i ( is_compressed_id ), - .pc_id_i ( pc_id ), + .pc_id_i ( pc_id ), - // Stalls - .halt_if_o ( halt_if ), + // Stalls + .halt_if_o ( halt_if ), - .id_ready_o ( id_ready ), - .ex_ready_i ( ex_ready ), + .id_ready_o ( id_ready ), + .ex_ready_i ( ex_ready ), - .id_valid_o ( id_valid ), + .id_valid_o ( id_valid ), - .alu_operator_ex_o ( alu_operator_ex ), - .alu_operand_a_ex_o ( alu_operand_a_ex ), - .alu_operand_b_ex_o ( alu_operand_b_ex ), + .alu_operator_ex_o ( alu_operator_ex ), + .alu_operand_a_ex_o ( alu_operand_a_ex ), + .alu_operand_b_ex_o ( alu_operand_b_ex ), - .mult_en_ex_o ( mult_en_ex ), - .div_en_ex_o ( div_en_ex ), - .multdiv_operator_ex_o ( multdiv_operator_ex ), - .multdiv_signed_mode_ex_o ( multdiv_signed_mode_ex ), - .multdiv_operand_a_ex_o ( multdiv_operand_a_ex ), - .multdiv_operand_b_ex_o ( multdiv_operand_b_ex ), + .mult_en_ex_o ( mult_en_ex ), + .div_en_ex_o ( div_en_ex ), + .multdiv_operator_ex_o ( multdiv_operator_ex ), + .multdiv_signed_mode_ex_o ( multdiv_signed_mode_ex ), + .multdiv_operand_a_ex_o ( multdiv_operand_a_ex ), + .multdiv_operand_b_ex_o ( multdiv_operand_b_ex ), - // CSR ID/EX - .csr_access_ex_o ( csr_access_ex ), - .csr_op_ex_o ( csr_op_ex ), - .csr_cause_o ( csr_cause ), - .csr_save_if_o ( csr_save_if ), // control signal to save pc - .csr_save_id_o ( csr_save_id ), // control signal to save pc - .csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc - .csr_save_cause_o ( csr_save_cause ), + // CSR ID/EX + .csr_access_ex_o ( csr_access_ex ), + .csr_op_ex_o ( csr_op_ex ), + .csr_cause_o ( csr_cause ), + .csr_save_if_o ( csr_save_if ), // control signal to save pc + .csr_save_id_o ( csr_save_id ), // control signal to save pc + .csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc + .csr_save_cause_o ( csr_save_cause ), - // LSU - .data_req_ex_o ( data_req_ex ), // to load store unit - .data_we_ex_o ( data_we_ex ), // to load store unit - .data_type_ex_o ( data_type_ex ), // to load store unit - .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit - .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit - .data_wdata_ex_o ( data_wdata_ex ), // to load store unit + // LSU + .data_req_ex_o ( data_req_ex ), // to load store unit + .data_we_ex_o ( data_we_ex ), // to load store unit + .data_type_ex_o ( data_type_ex ), // to load store unit + .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit + .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit + .data_wdata_ex_o ( data_wdata_ex ), // to load store unit - .data_misaligned_i ( data_misaligned ), - .misaligned_addr_i ( misaligned_addr ), + .data_misaligned_i ( data_misaligned ), + .misaligned_addr_i ( misaligned_addr ), - // Interrupt Signals - .irq_i ( irq_i ), // incoming interrupts - .irq_id_i ( irq_id_i ), - .m_irq_enable_i ( m_irq_enable ), - .irq_ack_o ( irq_ack_o ), - .irq_id_o ( irq_id_o ), + // Interrupt Signals + .irq_i ( irq_i ), // incoming interrupts + .irq_id_i ( irq_id_i ), + .m_irq_enable_i ( m_irq_enable ), + .irq_ack_o ( irq_ack_o ), + .irq_id_o ( irq_id_o ), - .lsu_load_err_i ( lsu_load_err ), - .lsu_store_err_i ( lsu_store_err ), + .lsu_load_err_i ( lsu_load_err ), + .lsu_store_err_i ( lsu_store_err ), - // Debug Unit Signals - .dbg_settings_i ( dbg_settings ), - .dbg_req_i ( dbg_req ), - .dbg_ack_o ( dbg_ack ), - .dbg_stall_i ( dbg_stall ), - .dbg_trap_o ( dbg_trap ), + // Debug Unit Signals + .dbg_settings_i ( dbg_settings ), + .dbg_req_i ( dbg_req ), + .dbg_ack_o ( dbg_ack ), + .dbg_stall_i ( dbg_stall ), + .dbg_trap_o ( dbg_trap ), - .dbg_reg_rreq_i ( dbg_reg_rreq ), - .dbg_reg_raddr_i ( dbg_reg_raddr ), - .dbg_reg_rdata_o ( dbg_reg_rdata ), + .dbg_reg_rreq_i ( dbg_reg_rreq ), + .dbg_reg_raddr_i ( dbg_reg_raddr ), + .dbg_reg_rdata_o ( dbg_reg_rdata ), - .dbg_reg_wreq_i ( dbg_reg_wreq ), - .dbg_reg_waddr_i ( dbg_reg_waddr ), - .dbg_reg_wdata_i ( dbg_reg_wdata ), + .dbg_reg_wreq_i ( dbg_reg_wreq ), + .dbg_reg_waddr_i ( dbg_reg_waddr ), + .dbg_reg_wdata_i ( dbg_reg_wdata ), - .dbg_jump_req_i ( dbg_jump_req ), + .dbg_jump_req_i ( dbg_jump_req ), - // write data to commit in the register file - .regfile_wdata_lsu_i ( regfile_wdata_lsu ), - .regfile_wdata_ex_i ( regfile_wdata_ex ), - .csr_rdata_i ( csr_rdata ), + // write data to commit in the register file + .regfile_wdata_lsu_i ( regfile_wdata_lsu ), + .regfile_wdata_ex_i ( regfile_wdata_ex ), + .csr_rdata_i ( csr_rdata ), - // Performance Counters - .perf_jump_o ( perf_jump ), - .perf_branch_o ( perf_branch ), - .perf_tbranch_o ( perf_tbranch ) + // Performance Counters + .perf_jump_o ( perf_jump ), + .perf_branch_o ( perf_branch ), + .perf_tbranch_o ( perf_tbranch ) ); - ibex_ex_block - #( - //change the localparam MULT_TYPE to 0 or 1 - //if you want a SLOW or FAST multiplier - .RV32M(RV32M) - ) - ex_block_i - ( - .clk ( clk ), - .rst_n ( rst_ni ), - // Alu signals from ID stage - //TODO: hot encoding - .alu_operator_i ( alu_operator_ex ), - .multdiv_operator_i ( multdiv_operator_ex ), - .alu_operand_a_i ( alu_operand_a_ex ), - .alu_operand_b_i ( alu_operand_b_ex ), + ibex_ex_block #( + //change the localparam MULT_TYPE to 0 or 1 + //if you want a SLOW or FAST multiplier + .RV32M(RV32M) + ) ex_block_i ( + .clk ( clk ), + .rst_n ( rst_ni ), + // Alu signals from ID stage + //TODO: hot encoding + .alu_operator_i ( alu_operator_ex ), + .multdiv_operator_i ( multdiv_operator_ex ), + .alu_operand_a_i ( alu_operand_a_ex ), + .alu_operand_b_i ( alu_operand_b_ex ), - // Multipler - .mult_en_i ( mult_en_ex ), - .div_en_i ( div_en_ex ), - .multdiv_signed_mode_i ( multdiv_signed_mode_ex), - .multdiv_operand_a_i ( multdiv_operand_a_ex ), - .multdiv_operand_b_i ( multdiv_operand_b_ex ), - .alu_adder_result_ex_o ( alu_adder_result_ex ), // from ALU to LSU - .regfile_wdata_ex_o ( regfile_wdata_ex ), + // Multipler + .mult_en_i ( mult_en_ex ), + .div_en_i ( div_en_ex ), + .multdiv_signed_mode_i ( multdiv_signed_mode_ex), + .multdiv_operand_a_i ( multdiv_operand_a_ex ), + .multdiv_operand_b_i ( multdiv_operand_b_ex ), + .alu_adder_result_ex_o ( alu_adder_result_ex ), // from ALU to LSU + .regfile_wdata_ex_o ( regfile_wdata_ex ), - // To IF: Jump and branch target and decision - .jump_target_o ( jump_target_ex ), - .branch_decision_o ( branch_decision ), + // To IF: Jump and branch target and decision + .jump_target_o ( jump_target_ex ), + .branch_decision_o ( branch_decision ), - .lsu_en_i ( data_req_ex ), - .lsu_ready_ex_i ( data_valid_lsu ), - .ex_ready_o ( ex_ready ) + .lsu_en_i ( data_req_ex ), + .lsu_ready_ex_i ( data_valid_lsu ), + .ex_ready_o ( ex_ready ) ); //////////////////////////////////////////////////////////////////////////////////////// @@ -501,46 +481,45 @@ module ibex_core // // //////////////////////////////////////////////////////////////////////////////////////// - ibex_load_store_unit load_store_unit_i - ( - .clk ( clk ), - .rst_n ( rst_ni ), + ibex_load_store_unit load_store_unit_i ( + .clk ( clk ), + .rst_n ( rst_ni ), - //output to data memory - .data_req_o ( data_req_o ), - .data_gnt_i ( data_gnt_i ), - .data_rvalid_i ( data_rvalid_i ), - .data_err_i ( data_err_i ), + //output to data memory + .data_req_o ( data_req_o ), + .data_gnt_i ( data_gnt_i ), + .data_rvalid_i ( data_rvalid_i ), + .data_err_i ( data_err_i ), - .data_addr_o ( data_addr_o ), - .data_we_o ( data_we_o ), - .data_be_o ( data_be_o ), - .data_wdata_o ( data_wdata_o ), - .data_rdata_i ( data_rdata_i ), + .data_addr_o ( data_addr_o ), + .data_we_o ( data_we_o ), + .data_be_o ( data_be_o ), + .data_wdata_o ( data_wdata_o ), + .data_rdata_i ( data_rdata_i ), - // signal from ex stage - .data_we_ex_i ( data_we_ex ), - .data_type_ex_i ( data_type_ex ), - .data_wdata_ex_i ( data_wdata_ex ), - .data_reg_offset_ex_i ( data_reg_offset_ex ), - .data_sign_ext_ex_i ( data_sign_ext_ex ), + // signal from ex stage + .data_we_ex_i ( data_we_ex ), + .data_type_ex_i ( data_type_ex ), + .data_wdata_ex_i ( data_wdata_ex ), + .data_reg_offset_ex_i ( data_reg_offset_ex ), + .data_sign_ext_ex_i ( data_sign_ext_ex ), - .data_rdata_ex_o ( regfile_wdata_lsu ), - .data_req_ex_i ( data_req_ex ), + .data_rdata_ex_o ( regfile_wdata_lsu ), + .data_req_ex_i ( data_req_ex ), - .adder_result_ex_i ( alu_adder_result_ex), + .adder_result_ex_i ( alu_adder_result_ex), - .data_misaligned_o ( data_misaligned ), - .misaligned_addr_o ( misaligned_addr ), + .data_misaligned_o ( data_misaligned ), + .misaligned_addr_o ( misaligned_addr ), - // exception signals - .load_err_o ( lsu_load_err ), - .store_err_o ( lsu_store_err ), + // exception signals + .load_err_o ( lsu_load_err ), + .store_err_o ( lsu_store_err ), - // control signals - .data_valid_o ( data_valid_lsu ), - .lsu_update_addr_o ( ), - .busy_o ( lsu_busy ) + // control signals + .data_valid_o ( data_valid_lsu ), + .lsu_update_addr_o ( ), + .busy_o ( lsu_busy ) ); @@ -554,56 +533,53 @@ module ibex_core // Control and Status Registers // ////////////////////////////////////// - ibex_cs_registers - #( - .N_EXT_CNT ( N_EXT_PERF_COUNTERS ) - ) - cs_registers_i - ( - .clk ( clk ), - .rst_n ( rst_ni ), + ibex_cs_registers #( + .N_EXT_CNT ( N_EXT_PERF_COUNTERS ) + ) cs_registers_i ( + .clk ( clk ), + .rst_n ( rst_ni ), - // Core and Cluster ID from outside - .core_id_i ( core_id_i ), - .cluster_id_i ( cluster_id_i ), - // boot address - .boot_addr_i ( boot_addr_i[31:8] ), - // Interface to CSRs (SRAM like) - .csr_access_i ( csr_access ), - .csr_addr_i ( csr_addr ), - .csr_wdata_i ( csr_wdata ), - .csr_op_i ( csr_op ), - .csr_rdata_o ( csr_rdata ), + // Core and Cluster ID from outside + .core_id_i ( core_id_i ), + .cluster_id_i ( cluster_id_i ), + // boot address + .boot_addr_i ( boot_addr_i[31:8] ), + // Interface to CSRs (SRAM like) + .csr_access_i ( csr_access ), + .csr_addr_i ( csr_addr ), + .csr_wdata_i ( csr_wdata ), + .csr_op_i ( csr_op ), + .csr_rdata_o ( csr_rdata ), - // Interrupt related control signals - .m_irq_enable_o ( m_irq_enable ), - .mepc_o ( mepc ), + // Interrupt related control signals + .m_irq_enable_o ( m_irq_enable ), + .mepc_o ( mepc ), - .pc_if_i ( pc_if ), - .pc_id_i ( pc_id ), + .pc_if_i ( pc_if ), + .pc_id_i ( pc_id ), - .csr_save_if_i ( csr_save_if ), - .csr_save_id_i ( csr_save_id ), - .csr_restore_mret_i ( csr_restore_mret_id ), - .csr_cause_i ( csr_cause ), - .csr_save_cause_i ( csr_save_cause ), + .csr_save_if_i ( csr_save_if ), + .csr_save_id_i ( csr_save_id ), + .csr_restore_mret_i ( csr_restore_mret_id ), + .csr_cause_i ( csr_cause ), + .csr_save_cause_i ( csr_save_cause ), - // performance counter related signals - .if_valid_i ( if_valid ), - .id_valid_i ( id_valid ), - .is_compressed_i ( is_compressed_id ), - .is_decoding_i ( is_decoding ), + // performance counter related signals + .if_valid_i ( if_valid ), + .id_valid_i ( id_valid ), + .is_compressed_i ( is_compressed_id ), + .is_decoding_i ( is_decoding ), - .imiss_i ( perf_imiss ), - .pc_set_i ( pc_set ), - .jump_i ( perf_jump ), - .branch_i ( perf_branch ), - .branch_taken_i ( perf_tbranch ), - .mem_load_i ( data_req_o & data_gnt_i & (~data_we_o) ), - .mem_store_i ( data_req_o & data_gnt_i & data_we_o ), + .imiss_i ( perf_imiss ), + .pc_set_i ( pc_set ), + .jump_i ( perf_jump ), + .branch_i ( perf_branch ), + .branch_taken_i ( perf_tbranch ), + .mem_load_i ( data_req_o & data_gnt_i & (~data_we_o) ), + .mem_store_i ( data_req_o & data_gnt_i & data_we_o ), - .ext_counters_i ( ext_perf_counters_i ) + .ext_counters_i ( ext_perf_counters_i ) ); // Mux for CSR access through Debug Unit @@ -625,108 +601,106 @@ module ibex_core // // ///////////////////////////////////////////////////////////// - ibex_debug_unit debug_unit_i - ( - .clk ( clk_i ), // always-running clock for debug - .rst_n ( rst_ni ), + ibex_debug_unit debug_unit_i ( + .clk ( clk_i ), // always-running clock for debug + .rst_n ( rst_ni ), - // Debug Interface - .debug_req_i ( debug_req_i ), - .debug_gnt_o ( debug_gnt_o ), - .debug_rvalid_o ( debug_rvalid_o ), - .debug_addr_i ( debug_addr_i ), - .debug_we_i ( debug_we_i ), - .debug_wdata_i ( debug_wdata_i ), - .debug_rdata_o ( debug_rdata_o ), - .debug_halt_i ( debug_halt_i ), - .debug_resume_i ( debug_resume_i ), - .debug_halted_o ( debug_halted_o ), + // Debug Interface + .debug_req_i ( debug_req_i ), + .debug_gnt_o ( debug_gnt_o ), + .debug_rvalid_o ( debug_rvalid_o ), + .debug_addr_i ( debug_addr_i ), + .debug_we_i ( debug_we_i ), + .debug_wdata_i ( debug_wdata_i ), + .debug_rdata_o ( debug_rdata_o ), + .debug_halt_i ( debug_halt_i ), + .debug_resume_i ( debug_resume_i ), + .debug_halted_o ( debug_halted_o ), - // To/From Core - .settings_o ( dbg_settings ), - .trap_i ( dbg_trap ), - .exc_cause_i ( exc_cause ), - .stall_o ( dbg_stall ), - .dbg_req_o ( dbg_req ), - .dbg_ack_i ( dbg_ack ), + // To/From Core + .settings_o ( dbg_settings ), + .trap_i ( dbg_trap ), + .exc_cause_i ( exc_cause ), + .stall_o ( dbg_stall ), + .dbg_req_o ( dbg_req ), + .dbg_ack_i ( dbg_ack ), - // register file read port - .regfile_rreq_o ( dbg_reg_rreq ), - .regfile_raddr_o ( dbg_reg_raddr ), - .regfile_rdata_i ( dbg_reg_rdata ), + // register file read port + .regfile_rreq_o ( dbg_reg_rreq ), + .regfile_raddr_o ( dbg_reg_raddr ), + .regfile_rdata_i ( dbg_reg_rdata ), - // register file write port - .regfile_wreq_o ( dbg_reg_wreq ), - .regfile_waddr_o ( dbg_reg_waddr ), - .regfile_wdata_o ( dbg_reg_wdata ), + // register file write port + .regfile_wreq_o ( dbg_reg_wreq ), + .regfile_waddr_o ( dbg_reg_waddr ), + .regfile_wdata_o ( dbg_reg_wdata ), - // CSR read/write port - .csr_req_o ( dbg_csr_req ), - .csr_addr_o ( dbg_csr_addr ), - .csr_we_o ( dbg_csr_we ), - .csr_wdata_o ( dbg_csr_wdata ), - .csr_rdata_i ( csr_rdata ), + // CSR read/write port + .csr_req_o ( dbg_csr_req ), + .csr_addr_o ( dbg_csr_addr ), + .csr_we_o ( dbg_csr_we ), + .csr_wdata_o ( dbg_csr_wdata ), + .csr_rdata_i ( csr_rdata ), - // signals for PPC and NPC - .pc_if_i ( pc_if ), // from IF stage - .pc_id_i ( pc_id ), // from ID stage - .instr_valid_id_i ( instr_valid_id ), + // signals for PPC and NPC + .pc_if_i ( pc_if ), // from IF stage + .pc_id_i ( pc_id ), // from ID stage - .sleeping_i ( sleeping ), + .sleeping_i ( sleeping ), - .jump_addr_o ( dbg_jump_addr ), // PC from debug unit - .jump_req_o ( dbg_jump_req ) // set PC to new value + .jump_addr_o ( dbg_jump_addr ), // PC from debug unit + .jump_req_o ( dbg_jump_req ) // set PC to new value ); `ifndef VERILATOR `ifdef TRACE_EXECUTION - ibex_tracer ibex_tracer_i - ( - .clk ( clk_i ), // always-running clock for tracing - .rst_n ( rst_ni ), + ibex_tracer ibex_tracer_i ( + .clk ( clk_i ), // always-running clock for tracing + .rst_n ( rst_ni ), - .fetch_enable ( fetch_enable_i ), - .core_id ( core_id_i ), - .cluster_id ( cluster_id_i ), + .fetch_enable ( fetch_enable_i ), + .core_id ( core_id_i ), + .cluster_id ( cluster_id_i ), - .pc ( id_stage_i.pc_id_i ), - .instr ( id_stage_i.instr ), - .compressed ( id_stage_i.is_compressed_i ), - .id_valid ( id_stage_i.id_valid_o ), - .is_decoding ( id_stage_i.is_decoding_o ), - .is_branch ( id_stage_i.branch_in_id ), - .branch_taken ( id_stage_i.branch_set_q ), - .pipe_flush ( id_stage_i.controller_i.pipe_flush_i ), - .mret_insn ( id_stage_i.controller_i.mret_insn_i ), - .ecall_insn ( id_stage_i.controller_i.ecall_insn_i ), - .ebrk_insn ( id_stage_i.controller_i.ebrk_insn_i ), - .csr_status ( id_stage_i.controller_i.csr_status_i ), - .rs1_value ( id_stage_i.operand_a_fw_id ), - .rs2_value ( id_stage_i.operand_b_fw_id ), + .pc ( id_stage_i.pc_id_i ), + .instr ( id_stage_i.instr ), + .compressed ( id_stage_i.is_compressed_i ), + .id_valid ( id_stage_i.id_valid_o ), + .is_decoding ( id_stage_i.is_decoding_o ), + .is_branch ( id_stage_i.branch_in_id ), + .branch_taken ( id_stage_i.branch_set_q ), + .pipe_flush ( id_stage_i.controller_i.pipe_flush_i ), + .mret_insn ( id_stage_i.controller_i.mret_insn_i ), + .ecall_insn ( id_stage_i.controller_i.ecall_insn_i ), + .ebrk_insn ( id_stage_i.controller_i.ebrk_insn_i ), + .csr_status ( id_stage_i.controller_i.csr_status_i ), + .rs1_value ( id_stage_i.operand_a_fw_id ), + .rs2_value ( id_stage_i.operand_b_fw_id ), - .lsu_value ( data_wdata_ex ), + .lsu_value ( data_wdata_ex ), - .ex_reg_addr ( id_stage_i.regfile_waddr_mux ), - .ex_reg_we ( id_stage_i.regfile_we_mux ), - .ex_reg_wdata ( id_stage_i.regfile_wdata_mux ), - .data_valid_lsu ( data_valid_lsu ), - .ex_data_addr ( data_addr_o ), - .ex_data_req ( data_req_o ), - .ex_data_gnt ( data_gnt_i ), - .ex_data_we ( data_we_o ), + .ex_reg_addr ( id_stage_i.regfile_waddr_mux ), + .ex_reg_we ( id_stage_i.regfile_we_mux ), + .ex_reg_wdata ( id_stage_i.regfile_wdata_mux ), + .data_valid_lsu ( data_valid_lsu ), + .ex_data_addr ( data_addr_o ), + .ex_data_req ( data_req_o ), + .ex_data_gnt ( data_gnt_i ), + .ex_data_we ( data_we_o ), - .ex_data_wdata ( data_wdata_o ), + .ex_data_wdata ( data_wdata_o ), - .lsu_reg_wdata ( regfile_wdata_lsu ), + .lsu_reg_wdata ( regfile_wdata_lsu ), - .imm_u_type ( id_stage_i.imm_u_type ), - .imm_uj_type ( id_stage_i.imm_uj_type ), - .imm_i_type ( id_stage_i.imm_i_type ), - .imm_iz_type ( id_stage_i.imm_iz_type[11:0] ), - .imm_z_type ( id_stage_i.imm_z_type ), - .imm_s_type ( id_stage_i.imm_s_type ), - .imm_sb_type ( id_stage_i.imm_sb_type ) + .imm_u_type ( id_stage_i.imm_u_type ), + .imm_uj_type ( id_stage_i.imm_uj_type ), + .imm_i_type ( id_stage_i.imm_i_type ), + .imm_iz_type ( id_stage_i.imm_iz_type[11:0] ), + .imm_z_type ( id_stage_i.imm_z_type ), + .imm_s_type ( id_stage_i.imm_s_type ), + .imm_sb_type ( id_stage_i.imm_sb_type ) ); `endif `endif + endmodule diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index feca3aef..3f36ffd5 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -21,8 +21,6 @@ `include "ibex_config.sv" -import ibex_defines::*; - `ifndef PULP_FPGA_EMUL `ifdef SYNTHESIS `define ASIC_SYNTHESIS @@ -35,59 +33,55 @@ import ibex_defines::*; * Control and Status Registers (CSRs) loosely following the RiscV draft * priviledged instruction set spec (v1.9) */ -module ibex_cs_registers -#( - parameter N_EXT_CNT = 0 -) -( - // Clock and Reset - input logic clk, - input logic rst_n, +module ibex_cs_registers #(parameter N_EXT_CNT = 0) ( + // Clock and Reset + input logic clk, + input logic rst_n, - // Core and Cluster ID - input logic [3:0] core_id_i, - input logic [5:0] cluster_id_i, + // Core and Cluster ID + input logic [3:0] core_id_i, + input logic [5:0] cluster_id_i, - // Used for boot address - input logic [23:0] boot_addr_i, + input logic [31:0] boot_addr_i, - // Interface to registers (SRAM like) - input logic csr_access_i, - input logic [11:0] csr_addr_i, - input logic [31:0] csr_wdata_i, - input logic [1:0] csr_op_i, - output logic [31:0] csr_rdata_o, + // Interface to registers (SRAM like) + input logic csr_access_i, + input logic [11:0] csr_addr_i, + input logic [31:0] csr_wdata_i, + input logic [1:0] csr_op_i, + output logic [31:0] csr_rdata_o, - // Interrupts - output logic m_irq_enable_o, - output logic [31:0] mepc_o, + // Interrupts + output logic m_irq_enable_o, + output logic [31:0] mepc_o, - input logic [31:0] pc_if_i, - input logic [31:0] pc_id_i, + input logic [31:0] pc_if_i, + input logic [31:0] pc_id_i, - input logic csr_save_if_i, - input logic csr_save_id_i, - input logic csr_restore_mret_i, + input logic csr_save_if_i, + input logic csr_save_id_i, + input logic csr_restore_mret_i, - input logic [5:0] csr_cause_i, - input logic csr_save_cause_i, + input logic [5:0] csr_cause_i, + input logic csr_save_cause_i, - // Performance Counters - input logic if_valid_i, // IF stage gives a new instruction - input logic id_valid_i, // ID stage is done - input logic is_compressed_i, // compressed instruction in ID - input logic is_decoding_i, // controller is in DECODE state + // Performance Counters + input logic if_valid_i, // IF stage gives a new instruction + input logic id_valid_i, // ID stage is done + input logic is_compressed_i, // compressed instruction in ID + input logic is_decoding_i, // controller is in DECODE state - input logic imiss_i, // instruction fetch - input logic pc_set_i, // pc was set to a new value - input logic jump_i, // jump instruction seen (j, jr, jal, jalr) - input logic branch_i, // branch instruction seen (bf, bnf) - input logic branch_taken_i, // branch was taken - input logic mem_load_i, // load from memory in this cycle - input logic mem_store_i, // store to memory in this cycle - input logic [N_EXT_CNT-1:0] ext_counters_i + input logic imiss_i, // instruction fetch + input logic pc_set_i, // pc was set to a new value + input logic jump_i, // jump instruction seen (j, jr, jal, jalr) + input logic branch_i, // branch instruction seen (bf, bnf) + input logic branch_taken_i, // branch was taken + input logic mem_load_i, // load from memory in this cycle + input logic mem_store_i, // store to memory in this cycle + input logic [N_EXT_CNT-1:0] ext_counters_i ); + import ibex_defines::*; localparam N_PERF_COUNTERS = 11 + N_EXT_CNT; @@ -121,12 +115,12 @@ module ibex_cs_registers } Status_t; // Performance Counter Signals - logic id_valid_q; logic [N_PERF_COUNTERS-1:0] PCCR_in; // input signals for each counter category logic [N_PERF_COUNTERS-1:0] PCCR_inc, PCCR_inc_q; // should the counter be increased? logic [N_PERF_REGS-1:0] [31:0] PCCR_q, PCCR_n; // performance counters counter register - logic [1:0] PCMR_n, PCMR_q; // mode register, controls saturation and global enable + logic [1:0] PCMR_n, PCMR_q; // mode register, controls saturation and + // global enable logic [N_PERF_COUNTERS-1:0] PCER_n, PCER_q; // selected counter input logic [31:0] perf_rdata; @@ -156,9 +150,8 @@ module ibex_cs_registers //////////////////////////////////////////// // read logic - always_comb - begin - csr_rdata_int = '0; + always_comb begin + csr_rdata_int = '0; case (csr_addr_i) // mstatus: always M-mode, contains IE bit @@ -172,7 +165,7 @@ module ibex_cs_registers 3'h0 }; // mtvec: machine trap-handler base address - 12'h305: csr_rdata_int = {boot_addr_i, 8'h0}; + 12'h305: csr_rdata_int = {boot_addr_i[31:8], 8'h0}; // mepc: exception program counter 12'h341: csr_rdata_int = mepc_q; // mcause: exception cause @@ -181,14 +174,13 @@ module ibex_cs_registers // mhartid: unique hardware thread id 12'hF14: csr_rdata_int = {21'b0, cluster_id_i[5:0], 1'b0, core_id_i[3:0]}; - default: ; + default: ; endcase end // write logic - always_comb - begin + always_comb begin mepc_n = mepc_q; mstatus_n = mstatus_q; mcause_n = mcause_q; @@ -196,7 +188,7 @@ module ibex_cs_registers case (csr_addr_i) // mstatus: IE bit 12'h300: if (csr_we_int) begin - mstatus_n = '{ + mstatus_n = '{ mie: csr_wdata_int[`MSTATUS_MIE_BITS], mpie: csr_wdata_int[`MSTATUS_MPIE_BITS], mpp: PrivLvl_t'(PRIV_LVL_M) @@ -206,7 +198,7 @@ module ibex_cs_registers 12'h341: if (csr_we_int) mepc_n = csr_wdata_int; // mcause 12'h342: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]}; - default: ; + default: ; endcase // exception controller gets priority over other writes @@ -231,54 +223,37 @@ module ibex_cs_registers end //csr_restore_mret_i default:; - endcase - end // CSR operation logic - always_comb - begin + always_comb begin csr_wdata_int = csr_wdata_i; csr_we_int = 1'b1; unique case (csr_op_i) - CSR_OP_WRITE: csr_wdata_int = csr_wdata_i; - CSR_OP_SET: csr_wdata_int = csr_wdata_i | csr_rdata_o; - CSR_OP_CLEAR: csr_wdata_int = (~csr_wdata_i) & csr_rdata_o; - + CSR_OP_WRITE: csr_wdata_int = csr_wdata_i; + CSR_OP_SET: csr_wdata_int = csr_wdata_i | csr_rdata_o; + CSR_OP_CLEAR: csr_wdata_int = ~csr_wdata_i & csr_rdata_o; CSR_OP_NONE: begin csr_wdata_int = csr_wdata_i; csr_we_int = 1'b0; end - default:; endcase end - - // output mux - always_comb - begin - csr_rdata_o = csr_rdata_int; - - // performance counters - if (is_pccr || is_pcer || is_pcmr) - csr_rdata_o = perf_rdata; - end - + // output mux, possibly choose performance counters + assign csr_rdata_o = (is_pccr || is_pcer || is_pcmr) ? perf_rdata : csr_rdata_int; // directly output some registers assign m_irq_enable_o = mstatus_q.mie; assign mepc_o = mepc_q; - // actual registers - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) - begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin mstatus_q <= '{ mie: 1'b0, mpie: 1'b0, @@ -286,11 +261,9 @@ module ibex_cs_registers }; mepc_q <= '0; mcause_q <= '0; - end - else - begin + end else begin // update CSRs - mstatus_q <= '{ + mstatus_q <= '{ mie: mstatus_n.mie, mpie: mstatus_n.mpie, mpp: PRIV_LVL_M @@ -313,26 +286,22 @@ module ibex_cs_registers assign PCCR_in[1] = if_valid_i; // instruction counter assign PCCR_in[2] = 1'b0; // Reserved assign PCCR_in[3] = 1'b0; // Reserved - assign PCCR_in[4] = imiss_i & (~pc_set_i); // cycles waiting for instruction fetches, excluding jumps and branches + assign PCCR_in[4] = imiss_i & (~pc_set_i); // cycles waiting for instruction fetches, + // excluding jumps and branches assign PCCR_in[5] = mem_load_i; // nr of loads assign PCCR_in[6] = mem_store_i; // nr of stores assign PCCR_in[7] = jump_i; // nr of jumps (unconditional) assign PCCR_in[8] = branch_i; // nr of branches (conditional) assign PCCR_in[9] = branch_taken_i; // nr of taken branches (conditional) - assign PCCR_in[10] = id_valid_i & is_decoding_i & is_compressed_i; // compressed instruction counter + assign PCCR_in[10] = id_valid_i & is_decoding_i & is_compressed_i; // compressed intr ctr // assign external performance counters - generate - genvar i; - for (i = 0; i < N_EXT_CNT; i++) - begin : g_extcounters - assign PCCR_in[N_PERF_COUNTERS - N_EXT_CNT + i] = ext_counters_i[i]; - end - endgenerate + for (genvar i = 0; i < N_EXT_CNT; i++) begin : gen_extcounters + assign PCCR_in[N_PERF_COUNTERS - N_EXT_CNT + i] = ext_counters_i[i]; + end // address decoder for performance counter registers - always_comb - begin + always_comb begin is_pccr = 1'b0; is_pcmr = 1'b0; is_pcer = 1'b0; @@ -345,7 +314,7 @@ module ibex_cs_registers unique case (csr_addr_i) 12'h7A0: begin is_pcer = 1'b1; - perf_rdata[15:0] = PCER_q; + perf_rdata[N_PERF_COUNTERS-1:0] = PCER_q; end 12'h7A1: begin is_pcmr = 1'b1; @@ -378,14 +347,14 @@ module ibex_cs_registers // for synthesis we just have one performance counter register assign PCCR_inc[0] = (|(PCCR_in & PCER_q)) & PCMR_q[0]; - always_comb - begin + always_comb begin PCCR_n[0] = PCCR_q[0]; - if ((PCCR_inc_q[0] == 1'b1) && ((PCCR_q[0] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) - PCCR_n[0] = PCCR_q[0] + 1; + if ((PCCR_inc_q[0] == 1'b1) && ((PCCR_q[0] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) begin + PCCR_n[0] = PCCR_q[0] + 32'h1; + end - if (is_pccr == 1'b1) begin + if (is_pccr) begin unique case (csr_op_i) CSR_OP_NONE: ; CSR_OP_WRITE: PCCR_n[0] = csr_wdata_i; @@ -395,23 +364,22 @@ module ibex_cs_registers end end `else - always_comb - begin - for(int i = 0; i < N_PERF_COUNTERS; i++) - begin : PERF_CNT_INC - PCCR_inc[i] = PCCR_in[i] & PCER_q[i] & PCMR_q[0]; + always_comb begin + for (int c = 0; c < N_PERF_COUNTERS; c++) begin : PERF_CNT_INC + PCCR_inc[c] = PCCR_in[c] & PCER_q[c] & PCMR_q[0]; - PCCR_n[i] = PCCR_q[i]; + PCCR_n[c] = PCCR_q[c]; - if ((PCCR_inc_q[i] == 1'b1) && ((PCCR_q[i] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) - PCCR_n[i] = PCCR_q[i] + 1; + if ((PCCR_inc_q[c] == 1'b1) && ((PCCR_q[c] != 32'hFFFFFFFF) || (PCMR_q[1] == 1'b0))) begin + PCCR_n[c] = PCCR_q[c] + 32'h1; + end - if (is_pccr == 1'b1 && (pccr_all_sel == 1'b1 || pccr_index == i)) begin + if (is_pccr && (pccr_all_sel || pccr_index == c)) begin unique case (csr_op_i) CSR_OP_NONE: ; - CSR_OP_WRITE: PCCR_n[i] = csr_wdata_i; - CSR_OP_SET: PCCR_n[i] = csr_wdata_i | PCCR_q[i]; - CSR_OP_CLEAR: PCCR_n[i] = csr_wdata_i & ~(PCCR_q[i]); + CSR_OP_WRITE: PCCR_n[c] = csr_wdata_i; + CSR_OP_SET: PCCR_n[c] = csr_wdata_i | PCCR_q[c]; + CSR_OP_CLEAR: PCCR_n[c] = csr_wdata_i & ~(PCCR_q[c]); endcase end end @@ -419,8 +387,7 @@ module ibex_cs_registers `endif // update PCMR and PCER - always_comb - begin + always_comb begin PCMR_n = PCMR_q; PCER_n = PCER_q; @@ -444,34 +411,23 @@ module ibex_cs_registers end // Performance Counter Registers - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) - begin - id_valid_q <= 1'b0; - + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin PCER_q <= '0; PCMR_q <= 2'h3; - for(int i = 0; i < N_PERF_REGS; i++) - begin - PCCR_q[i] <= '0; - PCCR_inc_q[i] <= '0; + for (int r = 0; r < N_PERF_REGS; r++) begin + PCCR_q[r] <= '0; + PCCR_inc_q[r] <= '0; end - end - else - begin - id_valid_q <= id_valid_i; - + end else begin PCER_q <= PCER_n; PCMR_q <= PCMR_n; - for(int i = 0; i < N_PERF_REGS; i++) - begin - PCCR_q[i] <= PCCR_n[i]; - PCCR_inc_q[i] <= PCCR_inc[i]; + for (int r = 0; r < N_PERF_REGS; r++) begin + PCCR_q[r] <= PCCR_n[r]; + PCCR_inc_q[r] <= PCCR_inc[r]; end - end end diff --git a/rtl/ibex_debug_unit.sv b/rtl/ibex_debug_unit.sv index 12e2e1a9..fd1413b3 100644 --- a/rtl/ibex_debug_unit.sv +++ b/rtl/ibex_debug_unit.sv @@ -19,70 +19,68 @@ `include "ibex_config.sv" -import ibex_defines::*; +module ibex_debug_unit #(parameter REG_ADDR_WIDTH = 5) ( + input logic clk, + input logic rst_n, -module ibex_debug_unit -#( - parameter REG_ADDR_WIDTH = 5 -) -( - input logic clk, - input logic rst_n, + // Debug Interface + input logic debug_req_i, + output logic debug_gnt_o, + output logic debug_rvalid_o, + input logic [14:0] debug_addr_i, + input logic debug_we_i, + input logic [31:0] debug_wdata_i, + output logic [31:0] debug_rdata_o, - // Debug Interface - input logic debug_req_i, - output logic debug_gnt_o, - output logic debug_rvalid_o, - input logic [14:0] debug_addr_i, - input logic debug_we_i, - input logic [31:0] debug_wdata_i, - output logic [31:0] debug_rdata_o, + output logic debug_halted_o, + input logic debug_halt_i, + input logic debug_resume_i, - output logic debug_halted_o, - input logic debug_halt_i, - input logic debug_resume_i, + // signals to core + output logic [DBG_SETS_W-1:0] settings_o, - // signals to core - output logic [DBG_SETS_W-1:0] settings_o, + input logic trap_i, // trap found, need to stop the core now + input logic [5:0] exc_cause_i, // if it was a trap, then the exception controller knows more + output logic stall_o, // after we got control, we control the stall signal + output logic dbg_req_o, + input logic dbg_ack_i, - input logic trap_i, // trap found, need to stop the core now - input logic [5:0] exc_cause_i, // if it was a trap, then the exception controller knows more - output logic stall_o, // after we got control, we control the stall signal - output logic dbg_req_o, - input logic dbg_ack_i, + // register file read port + output logic regfile_rreq_o, + output logic [REG_ADDR_WIDTH-1:0] regfile_raddr_o, + input logic [31:0] regfile_rdata_i, - // register file read port - output logic regfile_rreq_o, - output logic [(REG_ADDR_WIDTH-1):0] regfile_raddr_o, - input logic [31:0] regfile_rdata_i, + // register file write port + output logic regfile_wreq_o, + output logic [REG_ADDR_WIDTH-1:0] regfile_waddr_o, + output logic [31:0] regfile_wdata_o, - // register file write port - output logic regfile_wreq_o, - output logic [(REG_ADDR_WIDTH-1):0] regfile_waddr_o, - output logic [31:0] regfile_wdata_o, + // CSR read/write port + output logic csr_req_o, + output logic [11:0] csr_addr_o, + output logic csr_we_o, + output logic [31:0] csr_wdata_o, + input logic [31:0] csr_rdata_i, - // CSR read/write port - output logic csr_req_o, - output logic [11:0] csr_addr_o, - output logic csr_we_o, - output logic [31:0] csr_wdata_o, - input logic [31:0] csr_rdata_i, + // Signals for PPC & NPC register + input logic [31:0] pc_if_i, + input logic [31:0] pc_id_i, - // Signals for PPC & NPC register - input logic [31:0] pc_if_i, - input logic [31:0] pc_id_i, + input logic sleeping_i, - input logic instr_valid_id_i, - - input logic sleeping_i, - - output logic jump_req_o, - output logic [31:0] jump_addr_o + output logic jump_req_o, + output logic [31:0] jump_addr_o ); - enum logic [2:0] {RD_NONE, RD_CSR, RD_GPR, RD_DBGA, RD_DBGS} rdata_sel_q, rdata_sel_n; + import ibex_defines::*; - enum logic [0:0] {FIRST, SECOND} state_q, state_n; + typedef enum logic [2:0] {RD_NONE, RD_CSR, RD_GPR, RD_DBGA, RD_DBGS} rdata_sel_e; + + rdata_sel_e rdata_sel_q, rdata_sel_n; + + typedef enum logic [0:0] {FIRST, SECOND} dbg_fsm_e; + + dbg_fsm_e state_q, state_n; logic [DBG_SETS_W-1:0] settings_q, settings_n; @@ -96,8 +94,10 @@ module ibex_debug_unit logic csr_req_q, csr_req_n; logic regfile_wreq; + typedef enum logic [1:0] {RUNNING, HALT_REQ, HALT} stall_fsm_e; + + stall_fsm_e stall_cs, stall_ns; - enum logic [1:0] {RUNNING, HALT_REQ, HALT} stall_cs, stall_ns; logic [31:0] dbg_rdata; logic dbg_resume; logic dbg_halt; @@ -112,8 +112,7 @@ module ibex_debug_unit // address decoding, write and read controller - always_comb - begin + always_comb begin rdata_sel_n = RD_NONE; state_n = FIRST; @@ -162,15 +161,13 @@ module ibex_debug_unit 5'b0_0000: begin // DBG_CTRL if (debug_wdata_i[16]) begin // HALT set - if (~debug_halted_o) begin + if (!debug_halted_o) begin // not halt, so STOP dbg_halt = 1'b1; end - end else begin + end else if (debug_halted_o) begin // RESUME set - if (debug_halted_o) begin - dbg_resume = 1'b1; - end + dbg_resume = 1'b1; end settings_n[DBG_SETS_SSTE] = debug_wdata_i[0]; @@ -192,10 +189,9 @@ module ibex_debug_unit debug_gnt_o = 1'b1; // grant it even when invalid access to not block if (debug_halted_o) begin - unique case (debug_addr_i[6:2]) - 5'b0_0000: jump_req_n = 1'b1; // DNPC - default:; - endcase + if (debug_addr_i[6:2] == 5'b0_0000) begin + jump_req_n = 1'b1; // DNPC + end end end @@ -260,14 +256,14 @@ module ibex_debug_unit // Since those are combinational, we can do it in the cycle where we set // rvalid. The address has been latched into addr_q //---------------------------------------------------------------------------- - always_comb - begin + always_comb begin dbg_rdata = '0; case (rdata_sel_q) RD_DBGA: begin unique case (addr_q[6:2]) - 5'h00: dbg_rdata[31:0] = {15'b0, debug_halted_o, 15'b0, settings_q[DBG_SETS_SSTE]}; // DBG_CTRL + // DBG_CTRL + 5'h00: dbg_rdata[31:0] = {15'b0, debug_halted_o, 15'b0, settings_q[DBG_SETS_SSTE]}; 5'h01: dbg_rdata[31:0] = {15'b0, sleeping_i, 15'b0, dbg_ssth_q}; // DBG_HIT 5'h02: begin // DBG_IE dbg_rdata[31:16] = '0; @@ -310,8 +306,7 @@ module ibex_debug_unit //---------------------------------------------------------------------------- // read data mux //---------------------------------------------------------------------------- - always_comb - begin + always_comb begin debug_rdata_o = '0; case (rdata_sel_q) @@ -319,16 +314,15 @@ module ibex_debug_unit RD_GPR: debug_rdata_o = regfile_rdata_i; RD_DBGA: debug_rdata_o = dbg_rdata; RD_DBGS: debug_rdata_o = dbg_rdata; - default: ; + default: ; endcase end //---------------------------------------------------------------------------- // rvalid generation //---------------------------------------------------------------------------- - always_ff @(posedge clk, negedge rst_n) - begin - if (~rst_n) begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin debug_rvalid_o <= 1'b0; end else begin debug_rvalid_o <= debug_gnt_o; // always give the rvalid one cycle after gnt @@ -338,8 +332,7 @@ module ibex_debug_unit //---------------------------------------------------------------------------- // stall control //---------------------------------------------------------------------------- - always_comb - begin + always_comb begin stall_ns = stall_cs; dbg_req_o = 1'b0; stall_o = 1'b0; @@ -347,17 +340,18 @@ module ibex_debug_unit dbg_cause_n = dbg_cause_q; dbg_ssth_n = dbg_ssth_q; - case (stall_cs) + unique case (stall_cs) RUNNING: begin dbg_ssth_n = 1'b0; - if (dbg_halt | debug_halt_i | trap_i) begin + if (dbg_halt || debug_halt_i || trap_i) begin dbg_req_o = 1'b1; stall_ns = HALT_REQ; if (trap_i) begin - if (settings_q[DBG_SETS_SSTE]) + if (settings_q[DBG_SETS_SSTE]) begin dbg_ssth_n = 1'b1; + end dbg_cause_n = exc_cause_i; end else begin @@ -369,31 +363,30 @@ module ibex_debug_unit HALT_REQ: begin dbg_req_o = 1'b1; - if (dbg_ack_i) - stall_ns = HALT; - - if (dbg_resume | debug_resume_i) - stall_ns = RUNNING; + if (dbg_ack_i) stall_ns = HALT; + if (dbg_resume || debug_resume_i) stall_ns = RUNNING; end HALT: begin stall_o = 1'b1; debug_halted_o = 1'b1; - if (dbg_resume | debug_resume_i) begin + if (dbg_resume || debug_resume_i) begin stall_ns = RUNNING; stall_o = 1'b0; end end + + default:; endcase - if (ssth_clear) + if (ssth_clear) begin dbg_ssth_n = 1'b0; + end end - always_ff @(posedge clk, negedge rst_n) - begin - if (~rst_n) begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin stall_cs <= RUNNING; dbg_cause_q <= DBG_CAUSE_HALT; dbg_ssth_q <= 1'b0; @@ -411,10 +404,8 @@ module ibex_debug_unit assign ppc_int = pc_id_i; assign npc_int = pc_if_i; - always_ff @(posedge clk, negedge rst_n) - begin - if (~rst_n) begin - + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin addr_q <= '0; wdata_q <= '0; state_q <= FIRST; @@ -425,7 +416,6 @@ module ibex_debug_unit settings_q <= 1'b0; end else begin - // settings settings_q <= settings_n; @@ -436,7 +426,7 @@ module ibex_debug_unit state_q <= state_n; end - if (debug_req_i | debug_rvalid_o) begin + if (debug_req_i || debug_rvalid_o) begin // wait for either req or rvalid to set those FFs // This makes sure that they are only triggered once when there is // only one request, and the FFs can be properly clock gated otherwise diff --git a/rtl/ibex_decoder.sv b/rtl/ibex_decoder.sv index 4b23fb83..d2fa5255 100644 --- a/rtl/ibex_decoder.sv +++ b/rtl/ibex_decoder.sv @@ -23,64 +23,65 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Instruction decoder */ -module ibex_decoder -#( - parameter RV32M = 1 -) -( - // singals running to/from controller - input logic deassert_we_i, // deassert we, we are stalled or not active - input logic data_misaligned_i, // misaligned data load/store in progress - input logic branch_mux_i, - input logic jump_mux_i, - output logic illegal_insn_o, // illegal instruction encountered - output logic ebrk_insn_o, // trap instruction encountered - output logic mret_insn_o, // return from exception instruction encountered - output logic ecall_insn_o, // environment call (syscall) instruction encountered - output logic pipe_flush_o, // pipeline flush is requested +module ibex_decoder #( + parameter RV32M = 1 +) ( + // singals running to/from controller + input logic deassert_we_i, // deassert we, we are stalled or not active + input logic data_misaligned_i, // misaligned data load/store in progress + input logic branch_mux_i, + input logic jump_mux_i, + output logic illegal_insn_o, // illegal instruction encountered + output logic ebrk_insn_o, // trap instruction encountered + output logic mret_insn_o, // return from exception instruction encountered + output logic ecall_insn_o, // environment call (syscall) + // instruction encountered + output logic pipe_flush_o, // pipeline flush is requested - // from IF/ID pipeline - input logic [31:0] instr_rdata_i, // instruction read from instr memory/cache - input logic illegal_c_insn_i, // compressed instruction decode failed + // from IF/ID pipeline + input logic [31:0] instr_rdata_i, // instruction read from instr memory/cache + input logic illegal_c_insn_i, // compressed instruction decode failed - // ALU signals - output logic [ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection - output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero - output logic [2:0] alu_op_b_mux_sel_o, // oNOperand b selection: reg value or immediate + // ALU signals + output logic [ibex_defines::ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection + output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, + // immediate or zero + output logic [2:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate - output logic [0:0] imm_a_mux_sel_o, // immediate selection for operand a - output logic [3:0] imm_b_mux_sel_o, // immediate selection for operand b + output logic [0:0] imm_a_mux_sel_o, // immediate selection for operand a + output logic [3:0] imm_b_mux_sel_o, // immediate selection for operand b - // MUL, DIV related control signals - output logic mult_int_en_o, // perform integer multiplication - output logic div_int_en_o, // perform integer division or reminder - output logic [1:0] multdiv_operator_o, - output logic [1:0] multdiv_signed_mode_o, - // register file related signals - output logic regfile_we_o, // write enable for regfile + // MUL, DIV related control signals + output logic mult_int_en_o, // perform integer multiplication + output logic div_int_en_o, // perform integer division or reminder + output logic [1:0] multdiv_operator_o, + output logic [1:0] multdiv_signed_mode_o, + // register file related signals + output logic regfile_we_o, // write enable for regfile - // CSR manipulation - output logic csr_access_o, // access to CSR - output logic [1:0] csr_op_o, // operation to perform on CSR - output logic csr_status_o, // access to xstatus CSR + // CSR manipulation + output logic csr_access_o, // access to CSR + output logic [1:0] csr_op_o, // operation to perform on CSR + output logic csr_status_o, // access to xstatus CSR - // LD/ST unit signals - output logic data_req_o, // start transaction to data memory - output logic data_we_o, // data memory write enable - output logic [1:0] data_type_o, // data type on data memory: byte, half word or word - output logic data_sign_extension_o, // sign extension on read data from data memory - output logic [1:0] data_reg_offset_o, // offset in byte inside register for stores + // LD/ST unit signals + output logic data_req_o, // start transaction to data memory + output logic data_we_o, // data memory write enable + output logic [1:0] data_type_o, // data type on data memory: byte, + // half word or word + output logic data_sign_extension_o, // sign extension on read data from data memory + output logic [1:0] data_reg_offset_o, // offset in byte inside register for stores - // jump/branches - output logic jump_in_id_o, // jump is being calculated in ALU - output logic branch_in_id_o + // jump/branches + output logic jump_in_id_o, // jump is being calculated in ALU + output logic branch_in_id_o ); + import ibex_defines::*; + // write enable/request control logic regfile_we; logic data_req; @@ -102,8 +103,7 @@ module ibex_decoder // // ///////////////////////////////////////////// - always_comb - begin + always_comb begin jump_in_id = 1'b0; branch_in_id = 1'b0; alu_operator_o = ALU_SLTU; @@ -150,7 +150,7 @@ module ibex_decoder OPCODE_JAL: begin // Jump and Link jump_in_id = 1'b1; - if(jump_mux_i) begin + if (jump_mux_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -169,7 +169,7 @@ module ibex_decoder OPCODE_JALR: begin // Jump and Link Register jump_in_id = 1'b1; - if(jump_mux_i) begin + if (jump_mux_i) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; alu_op_b_mux_sel_o = OP_B_IMM; @@ -189,28 +189,21 @@ module ibex_decoder regfile_we = 1'b0; illegal_insn_o = 1'b1; end - end OPCODE_BRANCH: begin // Branch - branch_in_id = 1'b1; - - if (branch_mux_i) - begin + if (branch_mux_i) begin unique case (instr_rdata_i[14:12]) - 3'b000: alu_operator_o = ALU_EQ; - 3'b001: alu_operator_o = ALU_NE; - 3'b100: alu_operator_o = ALU_LTS; - 3'b101: alu_operator_o = ALU_GES; - 3'b110: alu_operator_o = ALU_LTU; - 3'b111: alu_operator_o = ALU_GEU; - default: begin - illegal_insn_o = 1'b1; - end + 3'b000: alu_operator_o = ALU_EQ; + 3'b001: alu_operator_o = ALU_NE; + 3'b100: alu_operator_o = ALU_LTS; + 3'b101: alu_operator_o = ALU_GES; + 3'b110: alu_operator_o = ALU_LTU; + 3'b111: alu_operator_o = ALU_GEU; + default: illegal_insn_o = 1'b1; endcase - end - else begin + end else begin // Calculate jump target in EX alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -218,7 +211,6 @@ module ibex_decoder alu_operator_o = ALU_ADD; regfile_we = 1'b0; end - end @@ -236,13 +228,12 @@ module ibex_decoder data_we_o = 1'b1; alu_operator_o = ALU_ADD; - if (instr_rdata_i[14] == 1'b0) begin + if (!instr_rdata_i[14]) begin // offset from immediate imm_b_mux_sel_o = IMMB_S; alu_op_b_mux_sel_o = OP_B_IMM; - end - // Register offset is illegal since no register c available - else begin + end else begin + // Register offset is illegal since no register c available data_req = 1'b0; data_we_o = 1'b0; illegal_insn_o = 1'b1; @@ -271,7 +262,6 @@ module ibex_decoder alu_op_b_mux_sel_o = OP_B_IMM; imm_b_mux_sel_o = IMMB_I; - // sign/zero extension data_sign_extension_o = ~instr_rdata_i[14]; @@ -352,20 +342,21 @@ module ibex_decoder 3'b001: begin alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate - if (instr_rdata_i[31:25] != 7'b0) + if (instr_rdata_i[31:25] != 7'b0) begin illegal_insn_o = 1'b1; + end end 3'b101: begin - if (instr_rdata_i[31:25] == 7'b0) + if (instr_rdata_i[31:25] == 7'b0) begin alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate - else if (instr_rdata_i[31:25] == 7'b010_0000) + end else if (instr_rdata_i[31:25] == 7'b010_0000) begin alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate - else + end else begin illegal_insn_o = 1'b1; + end end - - default: illegal_insn_o = 1'b1; + default:; endcase end @@ -374,12 +365,7 @@ module ibex_decoder if (instr_rdata_i[31]) begin illegal_insn_o = 1'b1; - end - else - begin // non bit-manipulation instructions - - if (~instr_rdata_i[28]) - + end else if (!instr_rdata_i[28]) begin // non bit-manipulation instructions unique case ({instr_rdata_i[30:25], instr_rdata_i[14:12]}) // RV32I ALU operations {6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add @@ -395,32 +381,32 @@ module ibex_decoder // supported RV32M instructions {6'b00_0001, 3'b000}: begin // mul - alu_operator_o = ALU_ADD; - multdiv_operator_o = MD_OP_MULL; - mult_int_en = 1'b1; - multdiv_signed_mode_o = 2'b00; - illegal_insn_o = RV32M ? 1'b0 : 1'b1; + alu_operator_o = ALU_ADD; + multdiv_operator_o = MD_OP_MULL; + mult_int_en = 1'b1; + multdiv_signed_mode_o = 2'b00; + illegal_insn_o = RV32M ? 1'b0 : 1'b1; end {6'b00_0001, 3'b001}: begin // mulh - alu_operator_o = ALU_ADD; - multdiv_operator_o = MD_OP_MULH; - mult_int_en = 1'b1; - multdiv_signed_mode_o = 2'b11; - illegal_insn_o = RV32M ? 1'b0 : 1'b1; + alu_operator_o = ALU_ADD; + multdiv_operator_o = MD_OP_MULH; + mult_int_en = 1'b1; + multdiv_signed_mode_o = 2'b11; + illegal_insn_o = RV32M ? 1'b0 : 1'b1; end {6'b00_0001, 3'b010}: begin // mulhsu - alu_operator_o = ALU_ADD; - multdiv_operator_o = MD_OP_MULH; - mult_int_en = 1'b1; - multdiv_signed_mode_o = 2'b01; - illegal_insn_o = RV32M ? 1'b0 : 1'b1; + alu_operator_o = ALU_ADD; + multdiv_operator_o = MD_OP_MULH; + mult_int_en = 1'b1; + multdiv_signed_mode_o = 2'b01; + illegal_insn_o = RV32M ? 1'b0 : 1'b1; end {6'b00_0001, 3'b011}: begin // mulhu - alu_operator_o = ALU_ADD; - multdiv_operator_o = MD_OP_MULH; - mult_int_en = 1'b1; - multdiv_signed_mode_o = 2'b00; - illegal_insn_o = RV32M ? 1'b0 : 1'b1; + alu_operator_o = ALU_ADD; + multdiv_operator_o = MD_OP_MULH; + mult_int_en = 1'b1; + multdiv_signed_mode_o = 2'b00; + illegal_insn_o = RV32M ? 1'b0 : 1'b1; end {6'b00_0001, 3'b100}: begin // div alu_operator_o = ALU_ADD; @@ -457,9 +443,6 @@ module ibex_decoder end end - - - //////////////////////////////////////////////// // ____ ____ _____ ____ ___ _ _ // // / ___|| _ \| ____/ ___|_ _| / \ | | // @@ -470,41 +453,28 @@ module ibex_decoder //////////////////////////////////////////////// OPCODE_SYSTEM: begin - if (instr_rdata_i[14:12] == 3'b000) - begin + if (instr_rdata_i[14:12] == 3'b000) begin // non CSR related SYSTEM instructions unique case (instr_rdata_i[31:20]) 12'h000: // ECALL - begin // environment (system) call ecall_insn_o = 1'b1; - end 12'h001: // ebreak - begin // debugger trap ebrk_insn_o = 1'b1; - end 12'h302: // mret - begin mret_insn_o = 1'b1; - end 12'h105: // wfi - begin // flush pipeline pipe_flush_o = 1'b1; - end default: - begin illegal_insn_o = 1'b1; - end endcase - end - else - begin + end else begin // instruction to read/modify CSR csr_access_o = 1'b1; regfile_we = 1'b1; @@ -512,7 +482,7 @@ module ibex_decoder imm_a_mux_sel_o = IMMA_Z; imm_b_mux_sel_o = IMMB_I; // CSR address is encoded in I imm - if (instr_rdata_i[14] == 1'b1) begin + if (instr_rdata_i[14]) begin // rs1 field is used as immediate alu_op_a_mux_sel_o = OP_A_IMM; end else begin @@ -526,10 +496,12 @@ module ibex_decoder default: csr_illegal = 1'b1; endcase - if(~csr_illegal) - if (instr_rdata_i[31:20] == 12'h300) + if (!csr_illegal) begin + if (instr_rdata_i[31:20] == 12'h300) begin //access to mstatus csr_status_o = 1'b1; + end + end illegal_insn_o = csr_illegal; @@ -548,8 +520,7 @@ module ibex_decoder // misaligned access was detected by the LSU // TODO: this section should eventually be moved out of the decoder - if (data_misaligned_i == 1'b1) - begin + if (data_misaligned_i) begin // only part of the pipeline is unstalled, make sure that the // correct operands are sent to the AGU alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; @@ -560,15 +531,9 @@ module ibex_decoder // second address since the first calculated address was // the correct one regfile_we = 1'b0; - end end - - - - - // deassert we signals (in case of stalls) assign regfile_we_o = (deassert_we_i) ? 1'b0 : regfile_we; assign mult_int_en_o = RV32M ? ((deassert_we_i) ? 1'b0 : mult_int_en) : 1'b0; diff --git a/rtl/ibex_ex_block.sv b/rtl/ibex_ex_block.sv index d3771081..c559bbe0 100644 --- a/rtl/ibex_ex_block.sv +++ b/rtl/ibex_ex_block.sv @@ -23,49 +23,46 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Execution stage * * Execution block: Hosts ALU and MUL/DIV unit */ -module ibex_ex_block -#( - parameter RV32M = 1 -) -( +module ibex_ex_block #( + parameter RV32M = 1 +) ( + input logic clk, + input logic rst_n, - input logic clk, - input logic rst_n, + // ALU signals from ID stage + input logic [ibex_defines::ALU_OP_WIDTH-1:0] alu_operator_i, + input logic [1:0] multdiv_operator_i, + input logic mult_en_i, + input logic div_en_i, - // ALU signals from ID stage - input logic [ALU_OP_WIDTH-1:0] alu_operator_i, - input logic [1:0] multdiv_operator_i, - input logic mult_en_i, - input logic div_en_i, + input logic [31:0] alu_operand_a_i, + input logic [31:0] alu_operand_b_i, - input logic [31:0] alu_operand_a_i, - input logic [31:0] alu_operand_b_i, + input logic [1:0] multdiv_signed_mode_i, + input logic [31:0] multdiv_operand_a_i, + input logic [31:0] multdiv_operand_b_i, - input logic [1:0] multdiv_signed_mode_i, - input logic [31:0] multdiv_operand_a_i, - input logic [31:0] multdiv_operand_b_i, + output logic [31:0] alu_adder_result_ex_o, + output logic [31:0] regfile_wdata_ex_o, - output logic [31:0] alu_adder_result_ex_o, - output logic [31:0] regfile_wdata_ex_o, + // To IF: Jump and branch target and decision + output logic [31:0] jump_target_o, + output logic branch_decision_o, - // To IF: Jump and branch target and decision - output logic [31:0] jump_target_o, - output logic branch_decision_o, + input logic lsu_en_i, - input logic lsu_en_i, - - // Stall Control - input logic lsu_ready_ex_i, // LSU is done - output logic ex_ready_o // EX stage gets new data + // Stall Control + input logic lsu_ready_ex_i, // LSU is done + output logic ex_ready_o // EX stage gets new data ); + import ibex_defines::*; + localparam MULT_TYPE = 1; //0 is SLOW logic [31:0] alu_result, multdiv_result; @@ -76,20 +73,18 @@ module ibex_ex_block logic multdiv_ready, multdiv_en_sel; logic multdiv_en; -/* - The multdiv_i output is never selected if RV32M=0 - At synthesis time, all the combinational and sequential logic - from the multdiv_i module are eliminated -*/ -generate -if (RV32M) begin - assign multdiv_en_sel = MULT_TYPE == 0 ? mult_en_i | div_en_i : div_en_i; - assign multdiv_en = mult_en_i | div_en_i; -end else begin - assign multdiv_en_sel = 1'b0; - assign multdiv_en = 1'b0; -end -endgenerate + /* + The multdiv_i output is never selected if RV32M=0 + At synthesis time, all the combinational and sequential logic + from the multdiv_i module are eliminated + */ + if (RV32M) begin : gen_multdiv_m + assign multdiv_en_sel = MULT_TYPE ? div_en_i : mult_en_i | div_en_i; + assign multdiv_en = mult_en_i | div_en_i; + end else begin : gen_multdiv_nom + assign multdiv_en_sel = 1'b0; + assign multdiv_en = 1'b0; + end assign regfile_wdata_ex_o = multdiv_en ? multdiv_result : alu_result; @@ -106,19 +101,18 @@ endgenerate // // //////////////////////////// - ibex_alu alu_i - ( - .operator_i ( alu_operator_i ), - .operand_a_i ( alu_operand_a_i ), - .operand_b_i ( alu_operand_b_i ), - .multdiv_operand_a_i ( multdiv_alu_operand_a ), - .multdiv_operand_b_i ( multdiv_alu_operand_b ), - .multdiv_en_i ( multdiv_en_sel ), - .adder_result_o ( alu_adder_result_ex_o ), - .adder_result_ext_o ( alu_adder_result_ext ), - .result_o ( alu_result ), - .comparison_result_o ( alu_cmp_result ), - .is_equal_result_o ( alu_is_equal_result ) + ibex_alu alu_i ( + .operator_i ( alu_operator_i ), + .operand_a_i ( alu_operand_a_i ), + .operand_b_i ( alu_operand_b_i ), + .multdiv_operand_a_i ( multdiv_alu_operand_a ), + .multdiv_operand_b_i ( multdiv_alu_operand_b ), + .multdiv_en_i ( multdiv_en_sel ), + .adder_result_o ( alu_adder_result_ex_o ), + .adder_result_ext_o ( alu_adder_result_ext ), + .result_o ( alu_result ), + .comparison_result_o ( alu_cmp_result ), + .is_equal_result_o ( alu_is_equal_result ) ); //////////////////////////////////////////////////////////////// @@ -130,59 +124,54 @@ endgenerate // // //////////////////////////////////////////////////////////////// - generate - if (MULT_TYPE == 0) begin : multdiv_slow - ibex_multdiv_slow multdiv_i - ( - .clk ( clk ), - .rst_n ( rst_n ), - .mult_en_i ( mult_en_i ), - .div_en_i ( div_en_i ), - .operator_i ( multdiv_operator_i ), - .signed_mode_i ( multdiv_signed_mode_i ), - .op_a_i ( multdiv_operand_a_i ), - .op_b_i ( multdiv_operand_b_i ), - .alu_adder_ext_i ( alu_adder_result_ext ), - .alu_adder_i ( alu_adder_result_ex_o ), - .equal_to_zero ( alu_is_equal_result ), - .ready_o ( multdiv_ready ), - .alu_operand_a_o ( multdiv_alu_operand_a ), - .alu_operand_b_o ( multdiv_alu_operand_b ), - .multdiv_result_o ( multdiv_result ) + if (!MULT_TYPE) begin : gen_multdiv_slow + ibex_multdiv_slow multdiv_i ( + .clk ( clk ), + .rst_n ( rst_n ), + .mult_en_i ( mult_en_i ), + .div_en_i ( div_en_i ), + .operator_i ( multdiv_operator_i ), + .signed_mode_i ( multdiv_signed_mode_i ), + .op_a_i ( multdiv_operand_a_i ), + .op_b_i ( multdiv_operand_b_i ), + .alu_adder_ext_i ( alu_adder_result_ext ), + .alu_adder_i ( alu_adder_result_ex_o ), + .equal_to_zero ( alu_is_equal_result ), + .ready_o ( multdiv_ready ), + .alu_operand_a_o ( multdiv_alu_operand_a ), + .alu_operand_b_o ( multdiv_alu_operand_b ), + .multdiv_result_o ( multdiv_result ) ); - end else begin: multdiv_fast - ibex_multdiv_fast multdiv_i - ( - .clk ( clk ), - .rst_n ( rst_n ), - .mult_en_i ( mult_en_i ), - .div_en_i ( div_en_i ), - .operator_i ( multdiv_operator_i ), - .signed_mode_i ( multdiv_signed_mode_i ), - .op_a_i ( multdiv_operand_a_i ), - .op_b_i ( multdiv_operand_b_i ), - .alu_operand_a_o ( multdiv_alu_operand_a ), - .alu_operand_b_o ( multdiv_alu_operand_b ), - .alu_adder_ext_i ( alu_adder_result_ext ), - .alu_adder_i ( alu_adder_result_ex_o ), - .equal_to_zero ( alu_is_equal_result ), - .ready_o ( multdiv_ready ), - .multdiv_result_o ( multdiv_result ) + end else begin: gen_multdiv_fast + ibex_multdiv_fast multdiv_i ( + .clk ( clk ), + .rst_n ( rst_n ), + .mult_en_i ( mult_en_i ), + .div_en_i ( div_en_i ), + .operator_i ( multdiv_operator_i ), + .signed_mode_i ( multdiv_signed_mode_i ), + .op_a_i ( multdiv_operand_a_i ), + .op_b_i ( multdiv_operand_b_i ), + .alu_operand_a_o ( multdiv_alu_operand_a ), + .alu_operand_b_o ( multdiv_alu_operand_b ), + .alu_adder_ext_i ( alu_adder_result_ext ), + .alu_adder_i ( alu_adder_result_ex_o ), + .equal_to_zero ( alu_is_equal_result ), + .ready_o ( multdiv_ready ), + .multdiv_result_o ( multdiv_result ) ); end - endgenerate - always_comb - begin - unique case (1'b1) - multdiv_en: - ex_ready_o = multdiv_ready; - lsu_en_i: - ex_ready_o = lsu_ready_ex_i; - default: - //1 Cycle case - ex_ready_o = 1'b1; - endcase + always_comb begin + unique case (1'b1) + multdiv_en: + ex_ready_o = multdiv_ready; + lsu_en_i: + ex_ready_o = lsu_ready_ex_i; + default: + //1 Cycle case + ex_ready_o = 1'b1; + endcase end endmodule diff --git a/rtl/ibex_fetch_fifo.sv b/rtl/ibex_fetch_fifo.sv index a77b8ce1..4a0e84b9 100644 --- a/rtl/ibex_fetch_fifo.sv +++ b/rtl/ibex_fetch_fifo.sv @@ -22,8 +22,7 @@ * clear_i clears the FIFO for the following cycle. in_addr_i can be sent in * this cycle already. */ -module ibex_fetch_fifo -( +module ibex_fetch_fifo ( input logic clk, input logic rst_n, @@ -43,8 +42,10 @@ module ibex_fetch_fifo output logic [31:0] out_rdata_o, output logic [31:0] out_addr_o, - output logic out_valid_stored_o // same as out_valid_o, except that if something is incoming now it is not included. This signal is available immediately as it comes directly out of FFs - ); + output logic out_valid_stored_o // same as out_valid_o, except that if something is + // incoming now it is not included. This signal is + // available immediately as it comes directly out of FFs +); localparam DEPTH = 3; // must be 3 or greater @@ -53,36 +54,35 @@ module ibex_fetch_fifo logic [DEPTH-1:0] [31:0] rdata_n, rdata_int, rdata_Q; logic [DEPTH-1:0] valid_n, valid_int, valid_Q; - logic [31:0] addr_next; + logic [31:2] addr_next; logic [31:0] rdata, rdata_unaligned; logic valid, valid_unaligned; logic aligned_is_compressed, unaligned_is_compressed; - logic aligned_is_compressed_st, unaligned_is_compressed_st; + logic unaligned_is_compressed_st; ////////////////////////////////////////////////////////////////////////////// // output port ////////////////////////////////////////////////////////////////////////////// - assign rdata = (valid_Q[0]) ? rdata_Q[0] : in_rdata_i; - assign valid = valid_Q[0] || in_valid_i; + assign rdata = valid_Q[0] ? rdata_Q[0] : in_rdata_i; + assign valid = valid_Q[0] | in_valid_i; - assign rdata_unaligned = (valid_Q[1]) ? {rdata_Q[1][15:0], rdata[31:16]} : {in_rdata_i[15:0], rdata[31:16]}; + assign rdata_unaligned = valid_Q[1] ? {rdata_Q[1][15:0], rdata[31:16]} : + {in_rdata_i[15:0], rdata[31:16]}; // it is implied that rdata_valid_Q[0] is set - assign valid_unaligned = (valid_Q[1] || (valid_Q[0] && in_valid_i)); + assign valid_unaligned = valid_Q[1] | (valid_Q[0] & in_valid_i); assign unaligned_is_compressed = rdata[17:16] != 2'b11; - assign aligned_is_compressed = rdata[1:0] != 2'b11; + assign aligned_is_compressed = rdata[ 1: 0] != 2'b11; assign unaligned_is_compressed_st = rdata_Q[0][17:16] != 2'b11; - assign aligned_is_compressed_st = rdata_Q[0][1:0] != 2'b11; ////////////////////////////////////////////////////////////////////////////// // instruction aligner (if unaligned) ////////////////////////////////////////////////////////////////////////////// - always_comb - begin + always_comb begin // serve the aligned case even though the output address is unaligned when // the next instruction will be from a hardware loop target // in this case the current instruction is already prealigned in element 0 @@ -90,10 +90,11 @@ module ibex_fetch_fifo // unaligned case out_rdata_o = rdata_unaligned; - if (unaligned_is_compressed) + if (unaligned_is_compressed) begin out_valid_o = valid; - else + end else begin out_valid_o = valid_unaligned; + end end else begin // aligned case out_rdata_o = rdata; @@ -101,18 +102,18 @@ module ibex_fetch_fifo end end - assign out_addr_o = (valid_Q[0]) ? addr_Q[0] : in_addr_i; + assign out_addr_o = valid_Q[0] ? addr_Q[0] : in_addr_i; // this valid signal must not depend on signals from outside! - always_comb - begin + always_comb begin out_valid_stored_o = 1'b1; if (out_addr_o[1]) begin - if (unaligned_is_compressed_st) + if (unaligned_is_compressed_st) begin out_valid_stored_o = 1'b1; - else + end else begin out_valid_stored_o = valid_Q[1]; + end end else begin out_valid_stored_o = valid_Q[0]; end @@ -128,67 +129,53 @@ module ibex_fetch_fifo // later anyway assign in_ready_o = ~valid_Q[DEPTH-2]; - ////////////////////////////////////////////////////////////////////////////// // FIFO management ////////////////////////////////////////////////////////////////////////////// - always_comb - begin - int j; - - addr_int = addr_Q; + always_comb begin + addr_int = addr_Q; rdata_int = rdata_Q; valid_int = valid_Q; - - if (in_valid_i) begin - for(j = 0; j < DEPTH; j++) begin - if (~valid_Q[j]) begin + for (int j = 0; j < DEPTH; j++) begin + if (!valid_Q[j]) begin addr_int[j] = in_addr_i; rdata_int[j] = in_rdata_i; valid_int[j] = 1'b1; - break; end end - end end - assign addr_next = {addr_int[0][31:2], 2'b00} + 32'h4; + assign addr_next[31:2] = addr_int[0][31:2] + 30'h1; // move everything by one step - always_comb - begin + always_comb begin addr_n = addr_int; rdata_n = rdata_int; valid_n = valid_int; if (out_ready_i && out_valid_o) begin - begin - if (addr_int[0][1]) begin - // unaligned case - if (unaligned_is_compressed) begin - addr_n[0] = {addr_next[31:2], 2'b00}; - end else begin - addr_n[0] = {addr_next[31:2], 2'b10}; - end - - rdata_n = {32'b0, rdata_int[DEPTH-1:1]}; - valid_n = {1'b0, valid_int[DEPTH-1:1]}; + if (addr_int[0][1]) begin + // unaligned case + if (unaligned_is_compressed) begin + addr_n[0] = {addr_next[31:2], 2'b00}; end else begin - - if (aligned_is_compressed) begin - // just increase address, do not move to next entry in FIFO - addr_n[0] = {addr_int[0][31:2], 2'b10}; - end else begin - // move to next entry in FIFO - addr_n[0] = {addr_next[31:2], 2'b00}; - rdata_n = {32'b0, rdata_int[DEPTH-1:1]}; - valid_n = {1'b0, valid_int[DEPTH-1:1]}; - end + addr_n[0] = {addr_next[31:2], 2'b10}; end + + rdata_n = {32'b0, rdata_int[DEPTH-1:1]}; + valid_n = {1'b0, valid_int[DEPTH-1:1]}; + end else if (aligned_is_compressed) begin + // just increase address, do not move to next entry in FIFO + addr_n[0] = {addr_int[0][31:2], 2'b10}; + end else begin + // move to next entry in FIFO + addr_n[0] = {addr_next[31:2], 2'b00}; + rdata_n = {32'b0, rdata_int[DEPTH-1:1]}; + valid_n = {1'b0, valid_int[DEPTH-1:1]}; end end end @@ -197,20 +184,16 @@ module ibex_fetch_fifo // registers ////////////////////////////////////////////////////////////////////////////// - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin addr_Q <= '{default: '0}; rdata_Q <= '{default: '0}; valid_Q <= '0; - end - else - begin + end else begin // on a clear signal from outside we invalidate the content of the FIFO // completely and start from an empty state if (clear_i) begin - valid_Q <= '0; + valid_Q <= '0; end else begin addr_Q <= addr_n; rdata_Q <= rdata_n; @@ -226,4 +209,4 @@ module ibex_fetch_fifo assert property ( @(posedge clk) (in_valid_i) |-> ((valid_Q[DEPTH-1] == 1'b0) || (clear_i == 1'b1)) ); `endif -endmodule \ No newline at end of file +endmodule diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index 68d03bee..c40ab63a 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -23,9 +23,6 @@ `include "ibex_config.sv" -import ibex_defines::*; - - // Source/Destination register instruction index `define REG_S1 19:15 `define REG_S2 24:20 @@ -37,12 +34,10 @@ import ibex_defines::*; * Decode stage of the core. It decodes the instructions and hosts the register * file. */ -module ibex_id_stage -#( - parameter RV32M = 1, - parameter RV32E = 0 -) -( +module ibex_id_stage #( + parameter RV32M = 1, + parameter RV32E = 0 +) ( input logic clk, input logic rst_n, @@ -59,7 +54,6 @@ module ibex_id_stage output logic instr_req_o, // Jumps and branches - output logic branch_in_ex_o, input logic branch_decision_i, // IF and ID stage signals @@ -80,9 +74,9 @@ module ibex_id_stage output logic id_valid_o, // ID stage is done // ALU - output logic [ALU_OP_WIDTH-1:0] alu_operator_ex_o, - output logic [31:0] alu_operand_a_ex_o, - output logic [31:0] alu_operand_b_ex_o, + output logic [ibex_defines::ALU_OP_WIDTH-1:0] alu_operator_ex_o, + output logic [31:0] alu_operand_a_ex_o, + output logic [31:0] alu_operand_b_ex_o, // MUL, DIV output logic mult_en_ex_o, @@ -151,6 +145,8 @@ module ibex_id_stage output logic perf_tbranch_o // we are executing a taken branch instruction ); + import ibex_defines::*; + logic [31:0] instr; // Decoder/Controller ID stage internal signals @@ -181,7 +177,9 @@ module ibex_id_stage logic halt_id; //FSM signals to write back multi cycles instructions logic regfile_we; - enum logic {RF_LSU, RF_EX} select_data_rf; + + typedef enum logic {RF_LSU, RF_EX} select_e; + select_e select_data_rf; // Immediate decoding and sign extension logic [31:0] imm_i_type; @@ -200,7 +198,6 @@ module ibex_id_stage logic [31:0] imm_a; // contains the immediate for operand b logic [31:0] imm_b; // contains the immediate for operand b - // Signals running between controller and exception controller logic irq_req_ctrl; logic [4:0] irq_id_ctrl; @@ -284,16 +281,18 @@ module ibex_id_stage //--------------------------------------------------------------------------- assign regfile_alu_waddr_id = instr[`REG_D]; -//if(RV32E) -// assign illegal_reg_rv32e = (regfile_addr_ra_id[4] | regfile_addr_rb_id[4] | regfile_alu_waddr_id[4]); -//else + //if (RV32E) + // assign illegal_reg_rv32e = (regfile_addr_ra_id[4] | + // regfile_addr_rb_id[4] | + // regfile_alu_waddr_id[4]); + //else assign illegal_reg_rv32e = 1'b0; // kill instruction in the IF/ID stage by setting the instr_valid_id control // signal to 0 for instructions that are done assign clear_instr_valid_o = id_ready_o | halt_id; - assign branch_taken_ex = branch_in_id & branch_decision_i; + assign branch_taken_ex = branch_in_id & branch_decision_i; //////////////////////////////////////////////////////// // ___ _ _ // @@ -305,34 +304,25 @@ module ibex_id_stage //////////////////////////////////////////////////////// // ALU_Op_a Mux - always_comb - begin : alu_operand_a_mux + always_comb begin : alu_operand_a_mux case (alu_op_a_mux_sel) OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; OP_A_CURRPC: alu_operand_a = pc_id_i; OP_A_IMM: alu_operand_a = imm_a; default: alu_operand_a = operand_a_fw_id; - endcase; // case (alu_op_a_mux_sel) + endcase // case (alu_op_a_mux_sel) end - always_comb - begin : immediate_a_mux - unique case (imm_a_mux_sel) - IMMA_Z: imm_a = imm_z_type; - IMMA_ZERO: imm_a = '0; - default: imm_a = '0; - endcase - end + assign imm_a = (imm_a_mux_sel == IMMA_Z) ? imm_z_type : '0; - // Operand a forwarding mux used with LSU instructions - always_comb - begin : operand_a_fw_mux - case (operand_a_fw_mux_sel) - SEL_MISALIGNED: operand_a_fw_id = misaligned_addr_i; - SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; - default: operand_a_fw_id = regfile_data_ra_id; - endcase; // case (operand_a_fw_mux_sel) - end + // Operand a forwarding mux used with LSU instructions + always_comb begin : operand_a_fw_mux + case (operand_a_fw_mux_sel) + SEL_MISALIGNED: operand_a_fw_id = misaligned_addr_i; + SEL_REGFILE: operand_a_fw_id = regfile_data_ra_id; + default: operand_a_fw_id = regfile_data_ra_id; + endcase // case (operand_a_fw_mux_sel) + end ////////////////////////////////////////////////////// @@ -345,33 +335,31 @@ module ibex_id_stage ////////////////////////////////////////////////////// // Immediate Mux for operand B - always_comb - begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMMB_I: imm_b = imm_i_type; - IMMB_S: imm_b = imm_s_type; - IMMB_U: imm_b = imm_u_type; - IMMB_PCINCR: imm_b = (is_compressed_i && (~data_misaligned_i)) ? 32'h2 : 32'h4; - IMMB_S2: imm_b = imm_s2_type; - IMMB_BI: imm_b = imm_bi_type; - IMMB_S3: imm_b = imm_s3_type; - IMMB_VS: imm_b = imm_vs_type; - IMMB_VU: imm_b = imm_vu_type; - IMMB_UJ: imm_b = imm_uj_type; - IMMB_SB: imm_b = imm_sb_type; - default: imm_b = imm_i_type; - endcase - end + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMMB_I: imm_b = imm_i_type; + IMMB_S: imm_b = imm_s_type; + IMMB_U: imm_b = imm_u_type; + IMMB_PCINCR: imm_b = (is_compressed_i && !data_misaligned_i) ? 32'h2 : 32'h4; + IMMB_S2: imm_b = imm_s2_type; + IMMB_BI: imm_b = imm_bi_type; + IMMB_S3: imm_b = imm_s3_type; + IMMB_VS: imm_b = imm_vs_type; + IMMB_VU: imm_b = imm_vu_type; + IMMB_UJ: imm_b = imm_uj_type; + IMMB_SB: imm_b = imm_sb_type; + default: imm_b = imm_i_type; + endcase + end // ALU_Op_b Mux - always_comb - begin : alu_operand_b_mux - case (alu_op_b_mux_sel) - OP_B_REGB_OR_FWD: operand_b = regfile_data_rb_id; - OP_B_IMM: operand_b = imm_b; - default: operand_b = regfile_data_rb_id; - endcase // case (alu_op_b_mux_sel) - end + always_comb begin : alu_operand_b_mux + case (alu_op_b_mux_sel) + OP_B_REGB_OR_FWD: operand_b = regfile_data_rb_id; + OP_B_IMM: operand_b = imm_b; + default: operand_b = regfile_data_rb_id; + endcase // case (alu_op_b_mux_sel) + end assign alu_operand_b = operand_b; assign operand_b_fw_id = regfile_data_rb_id; @@ -388,48 +376,43 @@ module ibex_id_stage logic [31:0] regfile_wdata_mux; logic regfile_we_mux; logic [4:0] regfile_waddr_mux; + //TODO: add assertion // Register File mux - always_comb - begin - if(dbg_reg_wreq_i) begin + always_comb begin + if (dbg_reg_wreq_i) begin regfile_wdata_mux = dbg_reg_wdata_i; regfile_waddr_mux = dbg_reg_waddr_i; regfile_we_mux = 1'b1; end else begin regfile_we_mux = regfile_we; regfile_waddr_mux = regfile_alu_waddr_id; - if (select_data_rf == RF_LSU) + if (select_data_rf == RF_LSU) begin regfile_wdata_mux = regfile_wdata_lsu_i; - else - if (csr_access) - regfile_wdata_mux = csr_rdata_i; - else - regfile_wdata_mux = regfile_wdata_ex_i; + end else if (csr_access) begin + regfile_wdata_mux = csr_rdata_i; + end else begin + regfile_wdata_mux = regfile_wdata_ex_i; + end end end - ibex_register_file - #( - .RV32E(RV32E) - ) - registers_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + ibex_register_file #( .RV32E(RV32E)) registers_i ( + .clk ( clk ), + .rst_n ( rst_n ), - .test_en_i ( test_en_i ), + .test_en_i ( test_en_i ), - // Read port a - .raddr_a_i ( regfile_addr_ra_id ), - .rdata_a_o ( regfile_data_ra_id ), - // Read port b - .raddr_b_i ( (dbg_reg_rreq_i == 1'b0) ? regfile_addr_rb_id : dbg_reg_raddr_i ), - .rdata_b_o ( regfile_data_rb_id ), - // write port - .waddr_a_i ( regfile_waddr_mux ), - .wdata_a_i ( regfile_wdata_mux ), - .we_a_i ( regfile_we_mux ) + // Read port a + .raddr_a_i ( regfile_addr_ra_id ), + .rdata_a_o ( regfile_data_ra_id ), + // Read port b + .raddr_b_i ( (dbg_reg_rreq_i == 1'b0) ? regfile_addr_rb_id : dbg_reg_raddr_i ), + .rdata_b_o ( regfile_data_rb_id ), + // write port + .waddr_a_i ( regfile_waddr_mux ), + .wdata_a_i ( regfile_wdata_mux ), + .we_a_i ( regfile_we_mux ) ); assign dbg_reg_rdata_o = regfile_data_rb_id; @@ -445,58 +428,53 @@ module ibex_id_stage // // /////////////////////////////////////////////// - ibex_decoder - #( - .RV32M(RV32M) - ) - decoder_i - ( - // controller related signals - .deassert_we_i ( deassert_we ), - .data_misaligned_i ( data_misaligned_i ), - .branch_mux_i ( branch_mux_dec ), - .jump_mux_i ( jump_mux_dec ), + ibex_decoder #( .RV32M(RV32M)) decoder_i ( + // controller related signals + .deassert_we_i ( deassert_we ), + .data_misaligned_i ( data_misaligned_i ), + .branch_mux_i ( branch_mux_dec ), + .jump_mux_i ( jump_mux_dec ), - .illegal_insn_o ( illegal_insn_dec ), - .ebrk_insn_o ( ebrk_insn ), - .mret_insn_o ( mret_insn_dec ), - .ecall_insn_o ( ecall_insn_dec ), - .pipe_flush_o ( pipe_flush_dec ), + .illegal_insn_o ( illegal_insn_dec ), + .ebrk_insn_o ( ebrk_insn ), + .mret_insn_o ( mret_insn_dec ), + .ecall_insn_o ( ecall_insn_dec ), + .pipe_flush_o ( pipe_flush_dec ), - // from IF/ID pipeline - .instr_rdata_i ( instr ), - .illegal_c_insn_i ( illegal_c_insn_i ), + // from IF/ID pipeline + .instr_rdata_i ( instr ), + .illegal_c_insn_i ( illegal_c_insn_i ), - // ALU signals - .alu_operator_o ( alu_operator ), - .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), - .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), + // ALU signals + .alu_operator_o ( alu_operator ), + .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), + .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), - .imm_a_mux_sel_o ( imm_a_mux_sel ), - .imm_b_mux_sel_o ( imm_b_mux_sel ), + .imm_a_mux_sel_o ( imm_a_mux_sel ), + .imm_b_mux_sel_o ( imm_b_mux_sel ), - .mult_int_en_o ( mult_int_en ), - .div_int_en_o ( div_int_en ), - .multdiv_operator_o ( multdiv_operator ), - .multdiv_signed_mode_o ( multdiv_signed_mode ), - // Register file control signals - .regfile_we_o ( regfile_we_id ), + .mult_int_en_o ( mult_int_en ), + .div_int_en_o ( div_int_en ), + .multdiv_operator_o ( multdiv_operator ), + .multdiv_signed_mode_o ( multdiv_signed_mode ), + // Register file control signals + .regfile_we_o ( regfile_we_id ), - // CSR control signals - .csr_access_o ( csr_access ), - .csr_op_o ( csr_op ), - .csr_status_o ( csr_status ), + // CSR control signals + .csr_access_o ( csr_access ), + .csr_op_o ( csr_op ), + .csr_status_o ( csr_status ), - // Data bus interface - .data_req_o ( data_req_id ), - .data_we_o ( data_we_id ), - .data_type_o ( data_type_id ), - .data_sign_extension_o ( data_sign_ext_id ), - .data_reg_offset_o ( data_reg_offset_id ), + // Data bus interface + .data_req_o ( data_req_id ), + .data_we_o ( data_we_id ), + .data_type_o ( data_type_id ), + .data_sign_extension_o ( data_sign_ext_id ), + .data_reg_offset_o ( data_reg_offset_id ), - // jump/branches - .jump_in_id_o ( jump_in_id ), - .branch_in_id_o ( branch_in_id ) + // jump/branches + .jump_in_id_o ( jump_in_id ), + .branch_in_id_o ( branch_in_id ) ); //////////////////////////////////////////////////////////////////// @@ -508,116 +486,114 @@ module ibex_id_stage // // //////////////////////////////////////////////////////////////////// - ibex_controller controller_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + ibex_controller controller_i ( + .clk ( clk ), + .rst_n ( rst_n ), - .fetch_enable_i ( fetch_enable_i ), - .ctrl_busy_o ( ctrl_busy_o ), - .first_fetch_o ( core_ctrl_firstfetch_o ), - .is_decoding_o ( is_decoding_o ), + .fetch_enable_i ( fetch_enable_i ), + .ctrl_busy_o ( ctrl_busy_o ), + .first_fetch_o ( core_ctrl_firstfetch_o ), + .is_decoding_o ( is_decoding_o ), - // decoder related signals - .deassert_we_o ( deassert_we ), - .illegal_insn_i ( illegal_insn_dec | illegal_reg_rv32e ), - .ecall_insn_i ( ecall_insn_dec ), - .mret_insn_i ( mret_insn_dec ), - .pipe_flush_i ( pipe_flush_dec ), - .ebrk_insn_i ( ebrk_insn ), - .csr_status_i ( csr_status ), + // decoder related signals + .deassert_we_o ( deassert_we ), + .illegal_insn_i ( illegal_insn_dec | illegal_reg_rv32e ), + .ecall_insn_i ( ecall_insn_dec ), + .mret_insn_i ( mret_insn_dec ), + .pipe_flush_i ( pipe_flush_dec ), + .ebrk_insn_i ( ebrk_insn ), + .csr_status_i ( csr_status ), - // from IF/ID pipeline - .instr_valid_i ( instr_valid_i ), + // from IF/ID pipeline + .instr_valid_i ( instr_valid_i ), - // from prefetcher - .instr_req_o ( instr_req_o ), + // from prefetcher + .instr_req_o ( instr_req_o ), - // to prefetcher - .pc_set_o ( pc_set_o ), - .pc_mux_o ( pc_mux_o ), - .exc_pc_mux_o ( exc_pc_mux_o ), - .exc_cause_o ( exc_cause_o ), + // to prefetcher + .pc_set_o ( pc_set_o ), + .pc_mux_o ( pc_mux_o ), + .exc_pc_mux_o ( exc_pc_mux_o ), + .exc_cause_o ( exc_cause_o ), - // LSU - .data_misaligned_i ( data_misaligned_i ), + // LSU + .data_misaligned_i ( data_misaligned_i ), - // jump/branch control - .branch_in_id_i ( branch_in_id ), - .branch_taken_ex_i ( branch_taken_ex ), - .branch_set_i ( branch_set_q ), - .jump_set_i ( jump_set ), + // jump/branch control + .branch_in_id_i ( branch_in_id ), + .branch_taken_ex_i ( branch_taken_ex ), + .branch_set_i ( branch_set_q ), + .jump_set_i ( jump_set ), - .instr_multicyle_i ( instr_multicyle ), + .instr_multicyle_i ( instr_multicyle ), - .irq_i ( irq_i ), - // Interrupt Controller Signals - .irq_req_ctrl_i ( irq_req_ctrl ), - .irq_id_ctrl_i ( irq_id_ctrl ), - .m_IE_i ( m_irq_enable_i ), + .irq_i ( irq_i ), + // Interrupt Controller Signals + .irq_req_ctrl_i ( irq_req_ctrl ), + .irq_id_ctrl_i ( irq_id_ctrl ), + .m_IE_i ( m_irq_enable_i ), - .irq_ack_o ( irq_ack_o ), - .irq_id_o ( irq_id_o ), + .irq_ack_o ( irq_ack_o ), + .irq_id_o ( irq_id_o ), - .exc_ack_o ( exc_ack ), - .exc_kill_o ( exc_kill ), + .exc_ack_o ( exc_ack ), + .exc_kill_o ( exc_kill ), - // CSR Controller Signals - .csr_save_cause_o ( csr_save_cause_o ), - .csr_cause_o ( csr_cause_o ), - .csr_save_if_o ( csr_save_if_o ), - .csr_save_id_o ( csr_save_id_o ), - .csr_restore_mret_id_o ( csr_restore_mret_id_o ), + // CSR Controller Signals + .csr_save_cause_o ( csr_save_cause_o ), + .csr_cause_o ( csr_cause_o ), + .csr_save_if_o ( csr_save_if_o ), + .csr_save_id_o ( csr_save_id_o ), + .csr_restore_mret_id_o ( csr_restore_mret_id_o ), - // Debug Unit Signals - .dbg_req_i ( dbg_req_i ), - .dbg_ack_o ( dbg_ack_o ), - .dbg_stall_i ( dbg_stall_i ), - .dbg_jump_req_i ( dbg_jump_req_i ), - .dbg_settings_i ( dbg_settings_i ), - .dbg_trap_o ( dbg_trap_o ), + // Debug Unit Signals + .dbg_req_i ( dbg_req_i ), + .dbg_ack_o ( dbg_ack_o ), + .dbg_stall_i ( dbg_stall_i ), + .dbg_jump_req_i ( dbg_jump_req_i ), + .dbg_settings_i ( dbg_settings_i ), + .dbg_trap_o ( dbg_trap_o ), - // Forwarding signals - .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), + // Forwarding signals + .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), - // Stall signals - .halt_if_o ( halt_if_o ), - .halt_id_o ( halt_id ), + // Stall signals + .halt_if_o ( halt_if_o ), + .halt_id_o ( halt_id ), - .id_ready_i ( id_ready_o ), + .id_ready_i ( id_ready_o ), - // Performance Counters - .perf_jump_o ( perf_jump_o ), - .perf_tbranch_o ( perf_tbranch_o ) + // Performance Counters + .perf_jump_o ( perf_jump_o ), + .perf_tbranch_o ( perf_tbranch_o ) ); -//////////////////////////////////////////////////////////////////////// -// _____ _ _____ _ _ _ // -// |_ _| | | / __ \ | | | | | // -// | | _ __ | |_ | / \/ ___ _ __ | |_ _ __ ___ | | | ___ _ __ // -// | || '_ \| __| | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| // -// _| || | | | |_ _ | \__/\ (_) | | | | |_| | | (_) | | | __/ | // -// \___/_| |_|\__(_) \____/\___/|_| |_|\__|_| \___/|_|_|\___|_| // -// // -//////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// + // _____ _ _____ _ _ _ // + // |_ _| | | / __ \ | | | | | // + // | | _ __ | |_ | / \/ ___ _ __ | |_ _ __ ___ | | | ___ _ __ // + // | || '_ \| __| | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| // + // _| || | | | |_ _ | \__/\ (_) | | | | |_| | | (_) | | | __/ | // + // \___/_| |_|\__(_) \____/\___/|_| |_|\__|_| \___/|_|_|\___|_| // + // // + //////////////////////////////////////////////////////////////////////// - ibex_int_controller int_controller_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + ibex_int_controller int_controller_i ( + .clk ( clk ), + .rst_n ( rst_n ), - // to controller - .irq_req_ctrl_o ( irq_req_ctrl ), - .irq_id_ctrl_o ( irq_id_ctrl ), + // to controller + .irq_req_ctrl_o ( irq_req_ctrl ), + .irq_id_ctrl_o ( irq_id_ctrl ), - .ctrl_ack_i ( exc_ack ), - .ctrl_kill_i ( exc_kill ), + .ctrl_ack_i ( exc_ack ), + .ctrl_kill_i ( exc_kill ), - // Interrupt signals - .irq_i ( irq_i ), - .irq_id_i ( irq_id_i ), + // Interrupt signals + .irq_i ( irq_i ), + .irq_id_i ( irq_id_i ), - .m_IE_i ( m_irq_enable_i ) + .m_IE_i ( m_irq_enable_i ) ); ///////////////////////////////////// @@ -643,8 +619,6 @@ module ibex_id_stage assign csr_access_ex_o = csr_access; assign csr_op_ex_o = csr_op; - assign branch_in_ex_o = branch_in_id; - assign mult_en_ex_o = mult_int_en; assign div_en_ex_o = div_int_en; @@ -653,19 +627,17 @@ module ibex_id_stage assign multdiv_operand_a_ex_o = regfile_data_ra_id; assign multdiv_operand_b_ex_o = regfile_data_rb_id; - enum logic { IDLE, WAIT_MULTICYCLE } id_wb_fsm_cs, id_wb_fsm_ns; + typedef enum logic { IDLE, WAIT_MULTICYCLE } id_fsm_e; + id_fsm_e id_wb_fsm_cs, id_wb_fsm_ns; /////////////////////////////////////// // ID-EX/WB Pipeline Register // /////////////////////////////////////// - always_ff @(posedge clk, negedge rst_n) - begin : EX_WB_Pipeline_Register - if (~rst_n) - begin + always_ff @(posedge clk, negedge rst_n) begin : EX_WB_Pipeline_Register + if (!rst_n) begin id_wb_fsm_cs <= IDLE; branch_set_q <= 1'b0; - end - else begin + end else begin id_wb_fsm_cs <= id_wb_fsm_ns; branch_set_q <= branch_set_n; end @@ -675,8 +647,7 @@ module ibex_id_stage // ID-EX/WB FMS // /////////////////////////////////////// - always_comb - begin + always_comb begin id_wb_fsm_ns = id_wb_fsm_cs; regfile_we = regfile_we_id; load_stall = 1'b0; @@ -693,8 +664,7 @@ module ibex_id_stage unique case (id_wb_fsm_cs) - IDLE: - begin + IDLE: begin jump_mux_dec = 1'b1; branch_mux_dec = 1'b1; unique case (1'b1) @@ -732,9 +702,8 @@ module ibex_id_stage endcase end - WAIT_MULTICYCLE: - begin - if(ex_ready_i) begin + WAIT_MULTICYCLE: begin + if (ex_ready_i) begin regfile_we = regfile_we_id; id_wb_fsm_ns = IDLE; load_stall = 1'b0; @@ -758,9 +727,9 @@ module ibex_id_stage end // stall control - assign id_ready_o = (~load_stall) & (~branch_stall) & (~jump_stall) & (~multdiv_stall); + assign id_ready_o = ~load_stall & ~branch_stall & ~jump_stall & ~multdiv_stall; - assign id_valid_o = (~halt_id) & id_ready_o; + assign id_valid_o = ~halt_id & id_ready_o; //---------------------------------------------------------------------------- @@ -769,7 +738,8 @@ module ibex_id_stage `ifndef VERILATOR // make sure that branch decision is valid when jumping assert property ( - @(posedge clk) (branch_decision_i !== 1'bx || branch_in_id == 1'b0) ) else begin $display("Branch decision is X"); $stop; end + @(posedge clk) (branch_decision_i !== 1'bx || branch_in_id == 1'b0) ) else begin + $display("Branch decision is X"); $stop; end `ifdef CHECK_MISALIGNED assert property ( @@ -778,11 +748,13 @@ module ibex_id_stage // the instruction delivered to the ID stage should always be valid assert property ( - @(posedge clk) (instr_valid_i & (~illegal_c_insn_i)) |-> (!$isunknown(instr_rdata_i)) ) else $display("Instruction is valid, but has at least one X"); + @(posedge clk) (instr_valid_i & (~illegal_c_insn_i)) |-> (!$isunknown(instr_rdata_i)) ) else + $display("Instruction is valid, but has at least one X"); // make sure multicycles enable signals are unique assert property ( - @(posedge clk) ~(data_req_ex_o & multdiv_int_en )) else $display("Multicycles enable signals are not unique"); + @(posedge clk) ~(data_req_ex_o & multdiv_int_en )) else + $display("Multicycles enable signals are not unique"); `endif diff --git a/rtl/ibex_if_stage.sv b/rtl/ibex_if_stage.sv index 51cd9235..e8a76f37 100644 --- a/rtl/ibex_if_stage.sv +++ b/rtl/ibex_if_stage.sv @@ -22,257 +22,227 @@ `include "ibex_config.sv" -import ibex_defines::*; - /** * Instruction Fetch Stage * * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of * the read instruction. */ -module ibex_if_stage -( - input logic clk, - input logic rst_n, - // the boot address is used to calculate the exception offsets - input logic [31:0] boot_addr_i, - // instruction request control - input logic req_i, - // instruction cache interface - output logic instr_req_o, - output logic [31:0] instr_addr_o, - input logic instr_gnt_i, - input logic instr_rvalid_i, - input logic [31:0] instr_rdata_i, - // Output of IF Pipeline stage - output logic instr_valid_id_o, // instruction in IF/ID pipeline is valid - output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding - output logic is_compressed_id_o, // compressed decoder thinks this is a compressed instruction - output logic illegal_c_insn_id_o, // compressed decoder thinks this is an invalid instruction - output logic [31:0] pc_if_o, - output logic [31:0] pc_id_o, - // Forwarding ports - control signals - input logic clear_instr_valid_i, // clear instruction valid bit in IF/ID pipe - input logic pc_set_i, // set the program counter to a new value - input logic [31:0] exception_pc_reg_i, // address used to restore PC when the interrupt/exception is served - input logic [2:0] pc_mux_i, // sel for pc multiplexer - input logic [1:0] exc_pc_mux_i, // selects ISR address - input logic [4:0] exc_vec_pc_mux_i, // selects ISR address for vectorized interrupt lines +module ibex_if_stage ( + input logic clk, + input logic rst_n, + // the boot address is used to calculate the exception offsets + input logic [31:0] boot_addr_i, + // instruction request control + input logic req_i, + // instruction cache interface + output logic instr_req_o, + output logic [31:0] instr_addr_o, + input logic instr_gnt_i, + input logic instr_rvalid_i, + input logic [31:0] instr_rdata_i, + // Output of IF Pipeline stage + output logic instr_valid_id_o, // instruction in IF/ID pipeline is valid + output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent + // to ID stage for decoding + output logic is_compressed_id_o, // compressed decoder thinks this is a + // compressed instruction + output logic illegal_c_insn_id_o, // compressed decoder thinks this is an + // invalid instruction + output logic [31:0] pc_if_o, + output logic [31:0] pc_id_o, + // Forwarding ports - control signals + input logic clear_instr_valid_i, // clear instruction valid bit in IF/ID pipe + input logic pc_set_i, // set the program counter to a new value + input logic [31:0] exception_pc_reg_i, // address used to restore PC when the + // interrupt/exception is served + input logic [2:0] pc_mux_i, // sel for pc multiplexer + input logic [1:0] exc_pc_mux_i, // selects ISR address + input logic [4:0] exc_vec_pc_mux_i, // selects ISR address for vectorized + // interrupt lines - // jump and branch target and decision - input logic [31:0] jump_target_ex_i, // jump target address - // from debug unit - input logic [31:0] dbg_jump_addr_i, - // pipeline stall - input logic halt_if_i, - input logic id_ready_i, - output logic if_valid_o, - // misc signals - output logic if_busy_o, // is the IF stage busy fetching instructions? - output logic perf_imiss_o // Instruction Fetch Miss - ); + // jump and branch target and decision + input logic [31:0] jump_target_ex_i, // jump target address + // from debug unit + input logic [31:0] dbg_jump_addr_i, + // pipeline stall + input logic halt_if_i, + input logic id_ready_i, + output logic if_valid_o, + // misc signals + output logic if_busy_o, // is the IF stage busy fetching instructions? + output logic perf_imiss_o // Instruction Fetch Miss +); - // offset FSM - enum logic[0:0] {WAIT, IDLE } offset_fsm_cs, offset_fsm_ns; + import ibex_defines::*; - logic valid; - logic if_ready; - // prefetch buffer related signals - logic prefetch_busy; - logic branch_req; - logic [31:0] fetch_addr_n; + logic offset_in_init_d, offset_in_init_q; + logic valid; + logic if_ready; + // prefetch buffer related signals + logic prefetch_busy; + logic branch_req; + logic [31:0] fetch_addr_n; - logic fetch_valid; - logic fetch_ready; - logic [31:0] fetch_rdata; - logic [31:0] fetch_addr; + logic fetch_valid; + logic fetch_ready; + logic [31:0] fetch_rdata; + logic [31:0] fetch_addr; - logic [31:0] exc_pc; + logic [31:0] exc_pc; + + // exception PC selection mux + always_comb begin : EXC_PC_MUX + exc_pc = '0; + + unique case (exc_pc_mux_i) + EXC_PC_ILLINSN: exc_pc = { boot_addr_i[31:8], EXC_OFF_ILLINSN }; + EXC_PC_ECALL: exc_pc = { boot_addr_i[31:8], EXC_OFF_ECALL }; + EXC_PC_IRQ: exc_pc = { boot_addr_i[31:8], 1'b0, exc_vec_pc_mux_i[4:0], 2'b0 }; + // TODO: Add case for EXC_PC_STORE and EXC_PC_LOAD as soon as they are supported + default:; + endcase + end + + // fetch address selection + always_comb begin + fetch_addr_n = '0; + + unique case (pc_mux_i) + PC_BOOT: fetch_addr_n = {boot_addr_i[31:8], EXC_OFF_RST}; + PC_JUMP: fetch_addr_n = jump_target_ex_i; + PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler + PC_ERET: fetch_addr_n = exception_pc_reg_i; // PC is restored when returning + // from IRQ/exception + PC_DBG_NPC: fetch_addr_n = dbg_jump_addr_i; // PC is taken from debug unit + + default:; + endcase + end + + // prefetch buffer, caches a fixed number of instructions + ibex_prefetch_buffer prefetch_buffer_i ( + .clk ( clk ), + .rst_n ( rst_n ), + + .req_i ( req_i ), + + .branch_i ( branch_req ), + .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + + // goes to instruction memory / instruction cache + .instr_req_o ( instr_req_o ), + .instr_addr_o ( instr_addr_o ), + .instr_gnt_i ( instr_gnt_i ), + .instr_rvalid_i ( instr_rvalid_i ), + .instr_rdata_i ( instr_rdata_i ), + + // Prefetch Buffer Status + .busy_o ( prefetch_busy ) + ); + // offset initialization state + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + offset_in_init_q <= 1'b1; + end else begin + offset_in_init_q <= offset_in_init_d; + end + end - // exception PC selection mux - always_comb - begin : EXC_PC_MUX - exc_pc = '0; + // offset initialization related transition logic + always_comb begin + offset_in_init_d = offset_in_init_q; - unique case (exc_pc_mux_i) - EXC_PC_ILLINSN: exc_pc = { boot_addr_i[31:8], EXC_OFF_ILLINSN }; - EXC_PC_ECALL: exc_pc = { boot_addr_i[31:8], EXC_OFF_ECALL }; - EXC_PC_IRQ: exc_pc = { boot_addr_i[31:8], 1'b0, exc_vec_pc_mux_i[4:0], 2'b0 }; - // TODO: Add case for EXC_PC_STORE and EXC_PC_LOAD as soon as they are supported - default:; - endcase + fetch_ready = 1'b0; + branch_req = 1'b0; + valid = 1'b0; + + if (offset_in_init_q) begin + // no valid instruction data for ID stage, assume aligned + if (req_i) begin + branch_req = 1'b1; + offset_in_init_d = 1'b0; + end + end else begin + if (fetch_valid) begin + valid = 1'b1; // an instruction is ready for ID stage + + if (req_i && if_valid_o) begin + fetch_ready = 1'b1; + offset_in_init_d = 1'b0; end + end + end - // fetch address selection - always_comb - begin - fetch_addr_n = '0; + // take care of jumps and branches + if (pc_set_i) begin + valid = 1'b0; - unique case (pc_mux_i) - PC_BOOT: fetch_addr_n = {boot_addr_i[31:8], EXC_OFF_RST}; - PC_JUMP: fetch_addr_n = jump_target_ex_i; - PC_EXCEPTION: fetch_addr_n = exc_pc; // set PC to exception handler - PC_ERET: fetch_addr_n = exception_pc_reg_i; // PC is restored when returning from IRQ/exception - PC_DBG_NPC: fetch_addr_n = dbg_jump_addr_i; // PC is taken from debug unit + // switch to new PC from ID stage + branch_req = 1'b1; + offset_in_init_d = 1'b0; + end + end - default:; - endcase - end + assign pc_if_o = fetch_addr; + assign if_busy_o = prefetch_busy; + assign perf_imiss_o = ~fetch_valid | branch_req; - // prefetch buffer, caches a fixed number of instructions - ibex_prefetch_buffer prefetch_buffer_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + // compressed instruction decoding, or more precisely compressed instruction + // expander + // + // since it does not matter where we decompress instructions, we do it here + // to ease timing closure + logic [31:0] instr_decompressed; + logic illegal_c_insn; + logic instr_compressed_int; - .req_i ( req_i ), + ibex_compressed_decoder compressed_decoder_i ( + .instr_i ( fetch_rdata ), + .instr_o ( instr_decompressed ), + .is_compressed_o ( instr_compressed_int ), + .illegal_instr_o ( illegal_c_insn ) + ); - .branch_i ( branch_req ), - .addr_i ( {fetch_addr_n[31:1], 1'b0} ), + // IF-ID pipeline registers, frozen when the ID stage is stalled + always_ff @(posedge clk, negedge rst_n) begin : IF_ID_PIPE_REGISTERS + if (!rst_n) begin + instr_valid_id_o <= 1'b0; + instr_rdata_id_o <= '0; + illegal_c_insn_id_o <= 1'b0; + is_compressed_id_o <= 1'b0; + pc_id_o <= '0; + end else begin + if (if_valid_o) begin + instr_valid_id_o <= 1'b1; + instr_rdata_id_o <= instr_decompressed; + illegal_c_insn_id_o <= illegal_c_insn; + is_compressed_id_o <= instr_compressed_int; + pc_id_o <= pc_if_o; + end else if (clear_instr_valid_i) begin + instr_valid_id_o <= 1'b0; + end + end + end - .ready_i ( fetch_ready ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .addr_o ( fetch_addr ), + assign if_ready = valid & id_ready_i; + assign if_valid_o = ~halt_if_i & if_ready; - // goes to instruction memory / instruction cache - .instr_req_o ( instr_req_o ), - .instr_addr_o ( instr_addr_o ), - .instr_gnt_i ( instr_gnt_i ), - .instr_rvalid_i ( instr_rvalid_i ), - .instr_rdata_i ( instr_rdata_i ), - - // Prefetch Buffer Status - .busy_o ( prefetch_busy ) - ); - - - // offset FSM state - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) begin - offset_fsm_cs <= IDLE; - end else begin - offset_fsm_cs <= offset_fsm_ns; - end - end - - // offset FSM state transition logic - always_comb - begin - offset_fsm_ns = offset_fsm_cs; - - fetch_ready = 1'b0; - branch_req = 1'b0; - valid = 1'b0; - - unique case (offset_fsm_cs) - // no valid instruction data for ID stage - // assume aligned - IDLE: begin - if (req_i) begin - branch_req = 1'b1; - offset_fsm_ns = WAIT; - end - end - - // serving aligned 32 bit or 16 bit instruction, we don't know yet - WAIT: begin - if (fetch_valid) begin - valid = 1'b1; // an instruction is ready for ID stage - - if (req_i && if_valid_o) begin - fetch_ready = 1'b1; - offset_fsm_ns = WAIT; - end - end - end - - default: begin - offset_fsm_ns = IDLE; - end - endcase - - - // take care of jumps and branches - if (pc_set_i) begin - valid = 1'b0; - - // switch to new PC from ID stage - branch_req = 1'b1; - offset_fsm_ns = WAIT; - end - end - - - - - assign pc_if_o = fetch_addr; - - assign if_busy_o = prefetch_busy; - - assign perf_imiss_o = (~fetch_valid) | branch_req; - - - // compressed instruction decoding, or more precisely compressed instruction - // expander - // - // since it does not matter where we decompress instructions, we do it here - // to ease timing closure - logic [31:0] instr_decompressed; - logic illegal_c_insn; - logic instr_compressed_int; - - ibex_compressed_decoder compressed_decoder_i - ( - .instr_i ( fetch_rdata ), - .instr_o ( instr_decompressed ), - .is_compressed_o ( instr_compressed_int ), - .illegal_instr_o ( illegal_c_insn ) - ); - - // IF-ID pipeline registers, frozen when the ID stage is stalled - always_ff @(posedge clk, negedge rst_n) - begin : IF_ID_PIPE_REGISTERS - if (rst_n == 1'b0) - begin - instr_valid_id_o <= 1'b0; - instr_rdata_id_o <= '0; - illegal_c_insn_id_o <= 1'b0; - is_compressed_id_o <= 1'b0; - pc_id_o <= '0; - end - else - begin - - if (if_valid_o) - begin - instr_valid_id_o <= 1'b1; - instr_rdata_id_o <= instr_decompressed; - illegal_c_insn_id_o <= illegal_c_insn; - is_compressed_id_o <= instr_compressed_int; - pc_id_o <= pc_if_o; - end else if (clear_instr_valid_i) begin - instr_valid_id_o <= 1'b0; - end - - end - end - - - assign if_ready = valid & id_ready_i; - assign if_valid_o = (~halt_if_i) & if_ready; - - //---------------------------------------------------------------------------- - // Assertions - //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- `ifndef VERILATOR - // there should never be a grant when there is no request - assert property ( - @(posedge clk) (instr_gnt_i) |-> (instr_req_o) ) - else $warning("There was a grant without a request"); + // there should never be a grant when there is no request + assert property ( + @(posedge clk) (instr_gnt_i) |-> (instr_req_o) ) + else $warning("There was a grant without a request"); `endif - endmodule +endmodule diff --git a/rtl/ibex_int_controller.sv b/rtl/ibex_int_controller.sv index 40376421..f2a755dd 100644 --- a/rtl/ibex_int_controller.sv +++ b/rtl/ibex_int_controller.sv @@ -16,91 +16,76 @@ // // //////////////////////////////////////////////////////////////////////////////// -import ibex_defines::*; - /** * Interrupt Controller */ -module ibex_int_controller -( - input logic clk, - input logic rst_n, +module ibex_int_controller ( + input logic clk, + input logic rst_n, - // irq_req for controller - output logic irq_req_ctrl_o, - output logic [4:0] irq_id_ctrl_o, + // irq_req for controller + output logic irq_req_ctrl_o, + output logic [4:0] irq_id_ctrl_o, - // handshake signals to controller - input logic ctrl_ack_i, - input logic ctrl_kill_i, + // handshake signals to controller + input logic ctrl_ack_i, + input logic ctrl_kill_i, - // external interrupt lines - input logic irq_i, // level-triggered interrupt inputs - input logic [4:0] irq_id_i, // interrupt id [0,1,....31] + // external interrupt lines + input logic irq_i, // level-triggered interrupt inputs + input logic [4:0] irq_id_i, // interrupt id [0,1,....31] - input logic m_IE_i // interrupt enable bit from CSR (M mode) + input logic m_IE_i // interrupt enable bit from CSR (M mode) ); - enum logic [1:0] { IDLE, IRQ_PENDING, IRQ_DONE} exc_ctrl_cs; + import ibex_defines::*; + + typedef enum logic [1:0] { IDLE, IRQ_PENDING, IRQ_DONE} exc_ctrl_e; + exc_ctrl_e exc_ctrl_ns, exc_ctrl_cs; logic irq_enable_ext; - logic [4:0] irq_id_q; + logic [4:0] irq_id_d, irq_id_q; assign irq_enable_ext = m_IE_i; assign irq_req_ctrl_o = exc_ctrl_cs == IRQ_PENDING; assign irq_id_ctrl_o = irq_id_q; - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) begin - + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin irq_id_q <= '0; exc_ctrl_cs <= IDLE; - end else begin - - unique case (exc_ctrl_cs) - - IDLE: - begin - if(irq_enable_ext & irq_i) begin - exc_ctrl_cs <= IRQ_PENDING; - irq_id_q <= irq_id_i; - end - end - - IRQ_PENDING: - begin - unique case(1'b1) - ctrl_ack_i: - exc_ctrl_cs <= IRQ_DONE; - ctrl_kill_i: - exc_ctrl_cs <= IDLE; - default: - exc_ctrl_cs <= IRQ_PENDING; - endcase - end - - IRQ_DONE: - begin - exc_ctrl_cs <= IDLE; - end - - endcase - + irq_id_q <= irq_id_d; + exc_ctrl_cs <= exc_ctrl_ns; end end -`ifndef SYNTHESIS - // synopsys translate_off - // evaluate at falling edge to avoid duplicates during glitches - // Removed this message as it pollutes too much the output and makes tests fail - //always_ff @(negedge clk) - //begin - // if (rst_n && exc_ctrl_cs == IRQ_DONE) - // $display("%t: Entering interrupt service routine. [%m]", $time); - //end - // synopsys translate_on -`endif + always_comb begin + irq_id_d = irq_id_q; + exc_ctrl_ns = exc_ctrl_cs; + unique case (exc_ctrl_cs) + IDLE: begin + if (irq_enable_ext && irq_i) begin + exc_ctrl_ns = IRQ_PENDING; + irq_id_d = irq_id_i; + end + end + + IRQ_PENDING: begin + unique case(1'b1) + ctrl_ack_i: + exc_ctrl_ns = IRQ_DONE; + ctrl_kill_i: + exc_ctrl_ns = IDLE; + default: + exc_ctrl_ns = IRQ_PENDING; + endcase + end + + IRQ_DONE: begin + exc_ctrl_ns = IDLE; + end + endcase + end endmodule diff --git a/rtl/ibex_load_store_unit.sv b/rtl/ibex_load_store_unit.sv index 90cdf0ef..d8f52032 100644 --- a/rtl/ibex_load_store_unit.sv +++ b/rtl/ibex_load_store_unit.sv @@ -28,8 +28,7 @@ * Load Store Unit, used to eliminate multiple access during processor stalls, * and to align bytes and halfwords. */ -module ibex_load_store_unit -( +module ibex_load_store_unit ( input logic clk, input logic rst_n, @@ -84,96 +83,88 @@ module ibex_load_store_unit logic [3:0] data_be; logic [31:0] data_wdata; - logic misaligned_st; // high if we are currently performing the second part of a misaligned store + logic misaligned_st; // high if we are currently performing the second part + // of a misaligned store logic data_misaligned, data_misaligned_q; logic increase_address; - enum logic [2:0] { IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID } CS, NS; + typedef enum logic [2:0] { + IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID + } ls_fsm_e; + + ls_fsm_e CS, NS; logic [31:0] rdata_q; ///////////////////////////////// BE generation //////////////////////////////// - always_comb - begin + always_comb begin case (data_type_ex_i) // Data type 00 Word, 01 Half word, 11,10 byte - 2'b00: - begin // Writing a word - if (misaligned_st == 1'b0) - begin // non-misaligned case - case (data_addr_int[1:0]) + 2'b00: begin // Writing a word + if (!misaligned_st) begin // non-misaligned case + unique case (data_addr_int[1:0]) 2'b00: data_be = 4'b1111; 2'b01: data_be = 4'b1110; 2'b10: data_be = 4'b1100; 2'b11: data_be = 4'b1000; - endcase; // case (data_addr_int[1:0]) - end - else - begin // misaligned case - case (data_addr_int[1:0]) + endcase // case (data_addr_int[1:0]) + end else begin // misaligned case + unique case (data_addr_int[1:0]) 2'b00: data_be = 4'b0000; // this is not used, but included for completeness 2'b01: data_be = 4'b0001; 2'b10: data_be = 4'b0011; 2'b11: data_be = 4'b0111; - endcase; // case (data_addr_int[1:0]) + endcase // case (data_addr_int[1:0]) end end - 2'b01: - begin // Writing a half word - if (misaligned_st == 1'b0) - begin // non-misaligned case - case (data_addr_int[1:0]) + 2'b01: begin // Writing a half word + if (!misaligned_st) begin // non-misaligned case + unique case (data_addr_int[1:0]) 2'b00: data_be = 4'b0011; 2'b01: data_be = 4'b0110; 2'b10: data_be = 4'b1100; 2'b11: data_be = 4'b1000; - endcase; // case (data_addr_int[1:0]) - end - else - begin // misaligned case + endcase // case (data_addr_int[1:0]) + end else begin // misaligned case data_be = 4'b0001; end end 2'b10, 2'b11: begin // Writing a byte - case (data_addr_int[1:0]) + unique case (data_addr_int[1:0]) 2'b00: data_be = 4'b0001; 2'b01: data_be = 4'b0010; 2'b10: data_be = 4'b0100; 2'b11: data_be = 4'b1000; - endcase; // case (data_addr_int[1:0]) + endcase // case (data_addr_int[1:0]) end - endcase; // case (data_type_ex_i) + endcase // case (data_type_ex_i) end // prepare data to be written to the memory // we handle misaligned accesses, half word and byte accesses and // register offsets here assign wdata_offset = data_addr_int[1:0] - data_reg_offset_ex_i[1:0]; - always_comb - begin - case (wdata_offset) + always_comb begin + unique case (wdata_offset) 2'b00: data_wdata = data_wdata_ex_i[31:0]; 2'b01: data_wdata = {data_wdata_ex_i[23:0], data_wdata_ex_i[31:24]}; 2'b10: data_wdata = {data_wdata_ex_i[15:0], data_wdata_ex_i[31:16]}; 2'b11: data_wdata = {data_wdata_ex_i[ 7:0], data_wdata_ex_i[31: 8]}; - endcase; // case (wdata_offset) + endcase // case (wdata_offset) end // FF for rdata alignment and sign-extension - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin - data_type_q <= '0; - rdata_offset_q <= '0; - data_sign_ext_q <= '0; + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + data_type_q <= 2'h0; + rdata_offset_q <= 2'h0; + data_sign_ext_q <= 1'b0; data_we_q <= 1'b0; - end - else if (data_gnt_i == 1'b1) // request was granted, we wait for rvalid and can continue to WB - begin + end else if (data_gnt_i) begin + // request was granted, we wait for rvalid and can continue to WB data_type_q <= data_type_ex_i; rdata_offset_q <= data_addr_int[1:0]; data_sign_ext_q <= data_sign_ext_ex_i; @@ -181,7 +172,6 @@ module ibex_load_store_unit end end - //////////////////////////////////////////////////////////////////////// // ____ _ _____ _ _ // // / ___|(_) __ _ _ __ | ____|_ _| |_ ___ _ __ ___(_) ___ _ __ // @@ -198,8 +188,7 @@ module ibex_load_store_unit logic [31:0] rdata_b_ext; // sign extension for bytes // take care of misaligned words - always_comb - begin + always_comb begin case (rdata_offset_q) 2'b00: rdata_w_ext = data_rdata_i[31:0]; 2'b01: rdata_w_ext = {data_rdata_i[ 7:0], rdata_q[31:8]}; @@ -209,83 +198,81 @@ module ibex_load_store_unit end // sign extension for half words - always_comb - begin + always_comb begin case (rdata_offset_q) - 2'b00: - begin - if (data_sign_ext_q == 1'b0) + 2'b00: begin + if (!data_sign_ext_q) begin rdata_h_ext = {16'h0000, data_rdata_i[15:0]}; - else + end else begin rdata_h_ext = {{16{data_rdata_i[15]}}, data_rdata_i[15:0]}; + end end - 2'b01: - begin - if (data_sign_ext_q == 1'b0) + 2'b01: begin + if (!data_sign_ext_q) begin rdata_h_ext = {16'h0000, data_rdata_i[23:8]}; - else + end else begin rdata_h_ext = {{16{data_rdata_i[23]}}, data_rdata_i[23:8]}; + end end - 2'b10: - begin - if (data_sign_ext_q == 1'b0) + 2'b10: begin + if (!data_sign_ext_q) begin rdata_h_ext = {16'h0000, data_rdata_i[31:16]}; - else + end else begin rdata_h_ext = {{16{data_rdata_i[31]}}, data_rdata_i[31:16]}; + end end - 2'b11: - begin - if (data_sign_ext_q == 1'b0) + 2'b11: begin + if (!data_sign_ext_q) begin rdata_h_ext = {16'h0000, data_rdata_i[7:0], rdata_q[31:24]}; - else + end else begin rdata_h_ext = {{16{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]}; + end end endcase // case (rdata_offset_q) end // sign extension for bytes - always_comb - begin + always_comb begin case (rdata_offset_q) - 2'b00: - begin - if (data_sign_ext_q == 1'b0) + 2'b00: begin + if (!data_sign_ext_q) begin rdata_b_ext = {24'h00_0000, data_rdata_i[7:0]}; - else + end else begin rdata_b_ext = {{24{data_rdata_i[7]}}, data_rdata_i[7:0]}; + end end 2'b01: begin - if (data_sign_ext_q == 1'b0) + if (!data_sign_ext_q) begin rdata_b_ext = {24'h00_0000, data_rdata_i[15:8]}; - else + end else begin rdata_b_ext = {{24{data_rdata_i[15]}}, data_rdata_i[15:8]}; + end end - 2'b10: - begin - if (data_sign_ext_q == 1'b0) + 2'b10: begin + if (!data_sign_ext_q) begin rdata_b_ext = {24'h00_0000, data_rdata_i[23:16]}; - else + end else begin rdata_b_ext = {{24{data_rdata_i[23]}}, data_rdata_i[23:16]}; + end end - 2'b11: - begin - if (data_sign_ext_q == 1'b0) + 2'b11: begin + if (!data_sign_ext_q) begin rdata_b_ext = {24'h00_0000, data_rdata_i[31:24]}; - else + end else begin rdata_b_ext = {{24{data_rdata_i[31]}}, data_rdata_i[31:24]}; + end end endcase // case (rdata_offset_q) end // select word, half word or byte sign extended version - always_comb - begin + always_comb begin case (data_type_q) 2'b00: data_rdata_ext = rdata_w_ext; 2'b01: data_rdata_ext = rdata_h_ext; @@ -295,42 +282,38 @@ module ibex_load_store_unit - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin CS <= IDLE; rdata_q <= '0; data_misaligned_q <= '0; misaligned_addr_o <= 32'b0; - end - else - begin + end else begin CS <= NS; if (lsu_update_addr_o) begin data_misaligned_q <= data_misaligned; - if(increase_address) begin + if (increase_address) begin misaligned_addr_o <= data_addr_int; end end - if (data_rvalid_i && (~data_we_q)) - begin + if (data_rvalid_i && !data_we_q) begin // if we have detected a misaligned access, and we are // currently doing the first part of this access, then // store the data coming from memory in rdata_q. // In all other cases, rdata_q gets the value that we are // writing to the register file - if ((data_misaligned_q == 1'b1) || (data_misaligned == 1'b1)) + if (data_misaligned_q || data_misaligned) begin rdata_q <= data_rdata_i; - else + end else begin rdata_q <= data_rdata_ext; + end end end end // output to register file - assign data_rdata_ex_o = (data_rvalid_i == 1'b1) ? data_rdata_ext : rdata_q; + assign data_rdata_ex_o = data_rvalid_i ? data_rdata_ext : rdata_q; // output to data interface assign data_addr_o = data_addr_int; @@ -344,8 +327,7 @@ module ibex_load_store_unit assign store_err_o = 1'b0; // FSM - always_comb - begin + always_comb begin NS = CS; data_req_o = 1'b0; @@ -358,34 +340,30 @@ module ibex_load_store_unit case(CS) // starts from not active and stays in IDLE until request was granted - IDLE: - begin + IDLE: begin if (data_req_ex_i) begin - data_req_o = data_req_ex_i; - if(data_gnt_i) begin - lsu_update_addr_o = 1'b1; - increase_address = data_misaligned; - NS = data_misaligned ? WAIT_RVALID_MIS : WAIT_RVALID; - end - else begin - NS = data_misaligned ? WAIT_GNT_MIS : WAIT_GNT; - end + data_req_o = data_req_ex_i; + if (data_gnt_i) begin + lsu_update_addr_o = 1'b1; + increase_address = data_misaligned; + NS = data_misaligned ? WAIT_RVALID_MIS : WAIT_RVALID; + end else begin + NS = data_misaligned ? WAIT_GNT_MIS : WAIT_GNT; + end end - end //~ IDLE + end // IDLE - WAIT_GNT_MIS: - begin + WAIT_GNT_MIS: begin data_req_o = 1'b1; - if(data_gnt_i) begin + if (data_gnt_i) begin lsu_update_addr_o = 1'b1; increase_address = data_misaligned; NS = WAIT_RVALID_MIS; end - end //~ WAIT_GNT_MIS + end // WAIT_GNT_MIS // wait for rvalid in WB stage and send a new request if there is any - WAIT_RVALID_MIS: - begin + WAIT_RVALID_MIS: begin //increase_address goes down, we already have the proper address increase_address = 1'b0; //tell the controller to update the address @@ -393,23 +371,21 @@ module ibex_load_store_unit data_req_o = 1'b0; lsu_update_addr_o = data_gnt_i; - if(data_rvalid_i) begin - //if first part rvalid is received - data_req_o = 1'b1; - if(data_gnt_i) begin - //second grant is received - NS = WAIT_RVALID; - //in this stage we already received the first valid but no the second one - //it differes from WAIT_RVALID_MIS because we do not send other requests - end - else begin - //second grant is NOT received, but first rvalid yes - //lsu_update_addr_o is 0 so data_misaligned_q stays high in WAIT_GNT - //increase address stays the same as well - NS = WAIT_GNT; // [1] - end - end - else begin + if (data_rvalid_i) begin + //if first part rvalid is received + data_req_o = 1'b1; + if (data_gnt_i) begin + //second grant is received + NS = WAIT_RVALID; + //in this stage we already received the first valid but no the second one + //it differes from WAIT_RVALID_MIS because we do not send other requests + end else begin + //second grant is NOT received, but first rvalid yes + //lsu_update_addr_o is 0 so data_misaligned_q stays high in WAIT_GNT + //increase address stays the same as well + NS = WAIT_GNT; // [1] + end + end else begin //if first part rvalid is NOT received //the second grand is not received either by protocol. //stay here @@ -417,26 +393,23 @@ module ibex_load_store_unit end end - WAIT_GNT: - begin + WAIT_GNT: begin data_misaligned_o = data_misaligned_q; //useful in case [1] data_req_o = 1'b1; - if(data_gnt_i) begin + if (data_gnt_i) begin lsu_update_addr_o = 1'b1; NS = WAIT_RVALID; end end //~ WAIT_GNT - WAIT_RVALID: - begin + WAIT_RVALID: begin data_req_o = 1'b0; - if(data_rvalid_i) begin + if (data_rvalid_i) begin data_valid_o = 1'b1; NS = IDLE; - end - else begin + end else begin NS = WAIT_RVALID; end end //~ WAIT_RVALID @@ -451,31 +424,29 @@ module ibex_load_store_unit // check for misaligned accesses that need a second memory access // If one is detected, this is signaled with data_misaligned_o to // the controller which selectively stalls the pipeline - always_comb - begin + always_comb begin data_misaligned = 1'b0; - if((data_req_ex_i == 1'b1) && (data_misaligned_q == 1'b0)) - begin + if (data_req_ex_i && !data_misaligned_q) begin case (data_type_ex_i) - 2'b00: // word - begin - if(data_addr_int[1:0] != 2'b00) + 2'b00: begin // word + if (data_addr_int[1:0] != 2'b00) begin data_misaligned = 1'b1; + end end - 2'b01: // half word - begin - if(data_addr_int[1:0] == 2'b11) + 2'b01: begin // half word + if (data_addr_int[1:0] == 2'b11) begin data_misaligned = 1'b1; + end end - default: ; + default: ; endcase // case (data_type_ex_i) end end assign data_addr_int = adder_result_ex_i; - assign busy_o = (CS == WAIT_RVALID) || (data_req_o == 1'b1); + assign busy_o = (CS == WAIT_RVALID) | (data_req_o == 1'b1); ////////////////////////////////////////////////////////////////////////////// // Assertions diff --git a/rtl/ibex_multdiv_fast.sv b/rtl/ibex_multdiv_fast.sv index ec4f84d3..c396ec4e 100644 --- a/rtl/ibex_multdiv_fast.sv +++ b/rtl/ibex_multdiv_fast.sv @@ -15,8 +15,6 @@ // // //////////////////////////////////////////////////////////////////////////////// -import ibex_defines::*; - `define OP_L 15:0 `define OP_H 31:16 @@ -25,30 +23,38 @@ import ibex_defines::*; * * 16x16 kernel multiplier and Long Division */ -module ibex_multdiv_fast -( - input logic clk, - input logic rst_n, - input logic mult_en_i, - input logic div_en_i, - input logic [1:0] operator_i, - input logic [1:0] signed_mode_i, - input logic [31:0] op_a_i, - input logic [31:0] op_b_i, - input logic [33:0] alu_adder_ext_i, - input logic [31:0] alu_adder_i, - input logic equal_to_zero, +module ibex_multdiv_fast ( + input logic clk, + input logic rst_n, + input logic mult_en_i, + input logic div_en_i, + input logic [1:0] operator_i, + input logic [1:0] signed_mode_i, + input logic [31:0] op_a_i, + input logic [31:0] op_b_i, + input logic [33:0] alu_adder_ext_i, + input logic [31:0] alu_adder_i, + input logic equal_to_zero, - output logic [32:0] alu_operand_a_o, - output logic [32:0] alu_operand_b_o, + output logic [32:0] alu_operand_a_o, + output logic [32:0] alu_operand_b_o, - output logic [31:0] multdiv_result_o, - output logic ready_o + output logic [31:0] multdiv_result_o, + output logic ready_o ); + import ibex_defines::*; + logic [ 4:0] div_counter_q, div_counter_n; - enum logic [1:0] {ALBL, ALBH, AHBL, AHBH } mult_state_q, mult_state_n; - enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH } divcurr_state_q, divcurr_state_n; + typedef enum logic [1:0] { + ALBL, ALBH, AHBL, AHBH + } mult_fsm_e; + mult_fsm_e mult_state_q, mult_state_n; + + typedef enum logic [2:0] { + MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH + } div_fsm_e; + div_fsm_e divcurr_state_q, divcurr_state_n; logic [34:0] mac_res_ext; logic [33:0] mac_res_q, mac_res_n, mac_res, op_reminder_n; @@ -67,12 +73,13 @@ module ibex_multdiv_fast logic [31:0] op_denominator_n; logic [31:0] op_numerator_n; logic [31:0] op_quotient_n; - logic [32:0] next_reminder, next_quotient; + logic [31:0] next_reminder; + logic [32:0] next_quotient; logic [32:0] res_adder_h; logic mult_is_ready; always_ff @(posedge clk or negedge rst_n) begin : proc_mult_state_q - if(~rst_n) begin + if (!rst_n) begin mult_state_q <= ALBL; mac_res_q <= '0; div_counter_q <= '0; @@ -82,11 +89,11 @@ module ibex_multdiv_fast op_quotient_q <= '0; end else begin - if(mult_en_i) begin + if (mult_en_i) begin mult_state_q <= mult_state_n; end - if(div_en_i) begin + if (div_en_i) begin div_counter_q <= div_counter_n; op_denominator_q <= op_denominator_n ; op_numerator_q <= op_numerator_n ; @@ -102,7 +109,6 @@ module ibex_multdiv_fast default: mac_res_q <= mac_res_q; endcase - end end @@ -115,8 +121,9 @@ module ibex_multdiv_fast assign res_adder_h = alu_adder_ext_i[33:1]; - assign next_reminder = is_greater_equal ? res_adder_h : mac_res_q[32:0]; - assign next_quotient = is_greater_equal ? op_quotient_q | one_shift : op_quotient_q; + assign next_reminder = is_greater_equal ? res_adder_h[31:0] : mac_res_q[31:0]; + assign next_quotient = is_greater_equal ? {1'b0,op_quotient_q} | {1'b0,one_shift} : + {1'b0,op_quotient_q}; assign one_shift = {31'b0, 1'b1} << div_counter_q; @@ -126,12 +133,12 @@ module ibex_multdiv_fast the next Reminder is Reminder - Divisor contained in res_adder_h and the */ - always_comb - begin - if ((mac_res_q[31] ^ op_denominator_q[31]) == 0) - is_greater_equal = (res_adder_h[31] == 0); - else + always_comb begin + if ((mac_res_q[31] ^ op_denominator_q[31]) == 1'b0) begin + is_greater_equal = (res_adder_h[31] == 1'b0); + end else begin is_greater_equal = mac_res_q[31]; + end end assign div_sign_a = op_a_i[31] & signed_mode_i[0]; @@ -140,199 +147,181 @@ module ibex_multdiv_fast assign rem_change_sign = div_sign_a; - always_comb - begin : div_fsm - div_counter_n = div_counter_q - 1; - op_reminder_n = mac_res_q; - op_quotient_n = op_quotient_q; - divcurr_state_n = divcurr_state_q; - op_numerator_n = op_numerator_q; - op_denominator_n = op_denominator_q; - alu_operand_a_o = {32'h0 , 1'b1}; - alu_operand_b_o = {~op_b_i, 1'b1}; + always_comb begin : div_fsm + div_counter_n = div_counter_q - 5'h1; + op_reminder_n = mac_res_q; + op_quotient_n = op_quotient_q; + divcurr_state_n = divcurr_state_q; + op_numerator_n = op_numerator_q; + op_denominator_n = op_denominator_q; + alu_operand_a_o = {32'h0 , 1'b1}; + alu_operand_b_o = {~op_b_i, 1'b1}; - unique case(divcurr_state_q) - MD_IDLE: begin - unique case(operator_i) - MD_OP_DIV: begin - //Check if the Denominator is 0 - //quotient for division by 0 - op_reminder_n = '1; - divcurr_state_n = equal_to_zero ? MD_FINISH : MD_ABS_A; - end - default: begin - //Check if the Denominator is 0 - //reminder for division by 0 - op_reminder_n = {2'b0, op_a_i}; - divcurr_state_n = equal_to_zero ? MD_FINISH : MD_ABS_A; - end - endcase - //0 - B = 0 iff B == 0 - alu_operand_a_o = {32'h0 , 1'b1}; - alu_operand_b_o = {~op_b_i, 1'b1}; - div_counter_n = 5'd31; - end - - MD_ABS_A: begin - //quotient - op_quotient_n = '0; - //A abs value - op_numerator_n = div_sign_a ? alu_adder_i : op_a_i; - divcurr_state_n = MD_ABS_B; - div_counter_n = 5'd31; - //ABS(A) = 0 - A - alu_operand_a_o = {32'h0 , 1'b1}; - alu_operand_b_o = {~op_a_i, 1'b1}; - end - - MD_ABS_B: begin - //reminder - op_reminder_n = { 33'h0, op_numerator_q[31]}; - //B abs value - op_denominator_n = div_sign_b ? alu_adder_i : op_b_i; - divcurr_state_n = MD_COMP; - div_counter_n = 5'd31; - //ABS(B) = 0 - B - alu_operand_a_o = {32'h0 , 1'b1}; - alu_operand_b_o = {~op_b_i, 1'b1}; - end - - MD_COMP: begin - - op_reminder_n = {1'b0, next_reminder[31:0], op_numerator_q[div_counter_n]}; - op_quotient_n = next_quotient; - if(div_counter_q == 5'd1) - divcurr_state_n = MD_LAST; - else - divcurr_state_n = MD_COMP; - //Division - alu_operand_a_o = {mac_res_q[31:0], 1'b1}; //it contains the reminder - alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; //denominator negated + 1 to do -denominator - end - - MD_LAST: begin - - unique case(operator_i) - MD_OP_DIV: - //this time we save the quotient in op_reminder_n (i.e. mac_res_q) since we do not need anymore the reminder - op_reminder_n = {1'b0, next_quotient}; - default: - //this time we do not save the quotient anymore since we need only the reminder - op_reminder_n = {2'b0, next_reminder[31:0]}; - endcase - //Division - alu_operand_a_o = {mac_res_q[31:0], 1'b1}; //it contains the reminder - alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; //denominator negated + 1 to do -denominator - - divcurr_state_n = MD_CHANGE_SIGN; - end - - MD_CHANGE_SIGN: begin - divcurr_state_n = MD_FINISH; - unique case(operator_i) - MD_OP_DIV: - op_reminder_n = (div_change_sign) ? alu_adder_i : mac_res_q; - default: - op_reminder_n = (rem_change_sign) ? alu_adder_i : mac_res_q; - endcase - //ABS(Quotient) = 0 - Quotient (or Reminder) - alu_operand_a_o = {32'h0 , 1'b1}; - alu_operand_b_o = {~mac_res_q[31:0], 1'b1}; - end - - MD_FINISH: begin - divcurr_state_n = MD_IDLE; + unique case(divcurr_state_q) + MD_IDLE: begin + if (operator_i == MD_OP_DIV) begin + //Check if the Denominator is 0 + //quotient for division by 0 + op_reminder_n = '1; + divcurr_state_n = equal_to_zero ? MD_FINISH : MD_ABS_A; + end else begin + //Check if the Denominator is 0 + //reminder for division by 0 + op_reminder_n = {2'b0, op_a_i}; + divcurr_state_n = equal_to_zero ? MD_FINISH : MD_ABS_A; end + //0 - B = 0 iff B == 0 + alu_operand_a_o = {32'h0 , 1'b1}; + alu_operand_b_o = {~op_b_i, 1'b1}; + div_counter_n = 5'd31; + end - default:; - endcase // divcurr_state_q + MD_ABS_A: begin + //quotient + op_quotient_n = '0; + //A abs value + op_numerator_n = div_sign_a ? alu_adder_i : op_a_i; + divcurr_state_n = MD_ABS_B; + div_counter_n = 5'd31; + //ABS(A) = 0 - A + alu_operand_a_o = {32'h0 , 1'b1}; + alu_operand_b_o = {~op_a_i, 1'b1}; + end + + MD_ABS_B: begin + //reminder + op_reminder_n = { 33'h0, op_numerator_q[31]}; + //B abs value + op_denominator_n = div_sign_b ? alu_adder_i : op_b_i; + divcurr_state_n = MD_COMP; + div_counter_n = 5'd31; + //ABS(B) = 0 - B + alu_operand_a_o = {32'h0 , 1'b1}; + alu_operand_b_o = {~op_b_i, 1'b1}; + end + + MD_COMP: begin + op_reminder_n = {1'b0, next_reminder[31:0], op_numerator_q[div_counter_n]}; + op_quotient_n = next_quotient[31:0]; + divcurr_state_n = (div_counter_q == 5'd1) ? MD_LAST : MD_COMP; + //Division + alu_operand_a_o = {mac_res_q[31:0], 1'b1}; //it contains the reminder + alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; // -denominator two's compliment + end + + MD_LAST: begin + if (operator_i == MD_OP_DIV) begin + // this time we save the quotient in op_reminder_n (i.e. mac_res_q) since + // we do not need anymore the reminder + op_reminder_n = {1'b0, next_quotient}; + end else begin + //this time we do not save the quotient anymore since we need only the reminder + op_reminder_n = {2'b0, next_reminder[31:0]}; + end + //Division + alu_operand_a_o = {mac_res_q[31:0], 1'b1}; // it contains the reminder + alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; // -denominator two's compliment + + divcurr_state_n = MD_CHANGE_SIGN; + end + + MD_CHANGE_SIGN: begin + divcurr_state_n = MD_FINISH; + if (operator_i == MD_OP_DIV) begin + op_reminder_n = (div_change_sign) ? {2'h0,alu_adder_i} : mac_res_q; + end else begin + op_reminder_n = (rem_change_sign) ? {2'h0,alu_adder_i} : mac_res_q; + end + //ABS(Quotient) = 0 - Quotient (or Reminder) + alu_operand_a_o = {32'h0 , 1'b1}; + alu_operand_b_o = {~mac_res_q[31:0], 1'b1}; + end + + MD_FINISH: begin + divcurr_state_n = MD_IDLE; + end + + default:; + endcase // divcurr_state_q end assign ready_o = mult_is_ready | (divcurr_state_q == MD_FINISH); - always_comb - begin : mult_fsm - mult_op_a = op_a_i[`OP_L]; - mult_op_b = op_b_i[`OP_L]; - sign_a = 1'b0; - sign_b = 1'b0; - accum = mac_res_q; - mac_res_n = mac_res; - mult_state_n = mult_state_q; - mult_is_ready = 1'b0; - unique case (mult_state_q) + always_comb begin : mult_fsm + mult_op_a = op_a_i[`OP_L]; + mult_op_b = op_b_i[`OP_L]; + sign_a = 1'b0; + sign_b = 1'b0; + accum = mac_res_q; + mac_res_n = mac_res; + mult_state_n = mult_state_q; + mult_is_ready = 1'b0; - ALBL: begin - //al*bl - mult_op_a = op_a_i[`OP_L]; - mult_op_b = op_b_i[`OP_L]; - sign_a = 1'b0; - sign_b = 1'b0; - accum = '0; + unique case (mult_state_q) + + ALBL: begin + //al*bl + mult_op_a = op_a_i[`OP_L]; + mult_op_b = op_b_i[`OP_L]; + sign_a = 1'b0; + sign_b = 1'b0; + accum = '0; + mac_res_n = mac_res; + mult_state_n = ALBH; + end + + ALBH: begin + //al*bh<<16 + mult_op_a = op_a_i[`OP_L]; + mult_op_b = op_b_i[`OP_H]; + sign_a = 1'b0; + sign_b = signed_mode_i[1] & op_b_i[31]; + //result of AL*BL (in mac_res_q) always unsigned with no carry, so carries_q always 00 + accum = {18'b0,mac_res_q[31:16]}; + if (operator_i == MD_OP_MULL) begin + mac_res_n = {2'b0,mac_res[`OP_L],mac_res_q[`OP_L]}; + end else begin + //MD_OP_MULH mac_res_n = mac_res; - mult_state_n = ALBH; end + mult_state_n = AHBL; + end - ALBH: begin - //al*bh<<16 - mult_op_a = op_a_i[`OP_L]; - mult_op_b = op_b_i[`OP_H]; - sign_a = 1'b0; - sign_b = signed_mode_i[1] & op_b_i[31]; - //result of AL*BL (in mac_res_q) always unsigned with no carry, so carries_q always 00 - accum = {18'b0,mac_res_q[31:16]}; - unique case(operator_i) - MD_OP_MULL: begin - mac_res_n = {2'b0,mac_res[`OP_L],mac_res_q[`OP_L]}; - end - default: begin - //MD_OP_MULH - mac_res_n = mac_res; - end - endcase - - mult_state_n = AHBL; - end - - AHBL: begin - //ah*bl<<16 - mult_op_a = op_a_i[`OP_H]; - mult_op_b = op_b_i[`OP_L]; - sign_a = signed_mode_i[0] & op_a_i[31]; - sign_b = 1'b0; - unique case(operator_i) - MD_OP_MULL: begin - accum = {18'b0,mac_res_q[31:16]}; - mac_res_n = {2'b0,mac_res[15:0],mac_res_q[15:0]}; - mult_is_ready = 1'b1; - mult_state_n = ALBL; - end - default: begin - accum = mac_res_q; - mac_res_n = mac_res; - mult_state_n = AHBH; - end - endcase - end - - AHBH: begin - //only MD_OP_MULH here - //ah*bh - mult_op_a = op_a_i[`OP_H]; - mult_op_b = op_b_i[`OP_H]; - sign_a = signed_mode_i[0] & op_a_i[31]; - sign_b = signed_mode_i[1] & op_b_i[31]; - accum[17:0 ] = mac_res_q[33:16]; - accum[33:18] = {18{signed_mult & mac_res_q[33]}}; - //result of AH*BL is not signed only if signed_mode_i == 2'b00 - mac_res_n = mac_res; - mult_state_n = ALBL; + AHBL: begin + //ah*bl<<16 + mult_op_a = op_a_i[`OP_H]; + mult_op_b = op_b_i[`OP_L]; + sign_a = signed_mode_i[0] & op_a_i[31]; + sign_b = 1'b0; + if (operator_i == MD_OP_MULL) begin + accum = {18'b0,mac_res_q[31:16]}; + mac_res_n = {2'b0,mac_res[15:0],mac_res_q[15:0]}; mult_is_ready = 1'b1; - + mult_state_n = ALBL; + end else begin + accum = mac_res_q; + mac_res_n = mac_res; + mult_state_n = AHBH; end + end - default:; - endcase // mult_state_q + AHBH: begin + //only MD_OP_MULH here + //ah*bh + mult_op_a = op_a_i[`OP_H]; + mult_op_b = op_b_i[`OP_H]; + sign_a = signed_mode_i[0] & op_a_i[31]; + sign_b = signed_mode_i[1] & op_b_i[31]; + accum[17: 0] = mac_res_q[33:16]; + accum[33:18] = {16{signed_mult & mac_res_q[33]}}; + //result of AH*BL is not signed only if signed_mode_i == 2'b00 + mac_res_n = mac_res; + mult_state_n = ALBL; + mult_is_ready = 1'b1; + + end + default:; + endcase // mult_state_q end diff --git a/rtl/ibex_multdiv_slow.sv b/rtl/ibex_multdiv_slow.sv index 17c73fc4..c2516b79 100644 --- a/rtl/ibex_multdiv_slow.sv +++ b/rtl/ibex_multdiv_slow.sv @@ -15,44 +15,46 @@ // // //////////////////////////////////////////////////////////////////////////////// -import ibex_defines::*; - /** * Slow Multiplier and Division * * Baugh-Wooley multiplier and Long Division */ -module ibex_multdiv_slow -( - input logic clk, - input logic rst_n, - input logic mult_en_i, - input logic div_en_i, - input logic [1:0] operator_i, - input logic [1:0] signed_mode_i, - input logic [31:0] op_a_i, - input logic [31:0] op_b_i, - input logic [33:0] alu_adder_ext_i, - input logic [31:0] alu_adder_i, - input logic equal_to_zero, +module ibex_multdiv_slow ( + input logic clk, + input logic rst_n, + input logic mult_en_i, + input logic div_en_i, + input logic [1:0] operator_i, + input logic [1:0] signed_mode_i, + input logic [31:0] op_a_i, + input logic [31:0] op_b_i, + input logic [33:0] alu_adder_ext_i, + input logic [31:0] alu_adder_i, + input logic equal_to_zero, - output logic [32:0] alu_operand_a_o, - output logic [32:0] alu_operand_b_o, - output logic [31:0] multdiv_result_o, + output logic [32:0] alu_operand_a_o, + output logic [32:0] alu_operand_b_o, + output logic [31:0] multdiv_result_o, - output logic ready_o + output logic ready_o ); - logic [ 4:0] multdiv_state_q, multdiv_state_n; - enum logic [2:0] { MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH } curr_state_q; + import ibex_defines::*; - logic [32:0] accum_window_q; + logic [ 4:0] multdiv_state_q, multdiv_state_d, multdiv_state_m1; + typedef enum logic [2:0] { + MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH + } div_fsm_e; + div_fsm_e curr_state_q, curr_state_d; + + logic [32:0] accum_window_q, accum_window_d; logic [32:0] res_adder_l; logic [32:0] res_adder_h; - logic [32:0] op_b_shift_q; - logic [32:0] op_a_shift_q; + logic [32:0] op_b_shift_q, op_b_shift_d; + logic [32:0] op_a_shift_q, op_a_shift_d; logic [32:0] op_a_ext, op_b_ext; logic [32:0] one_shift; logic [32:0] op_a_bw_pp, op_a_bw_last_pp; @@ -60,7 +62,7 @@ module ibex_multdiv_slow logic sign_a, sign_b; logic [32:0] next_reminder, next_quotient; logic [32:0] op_remainder; - logic [31:0] op_numerator_q; + logic [31:0] op_numerator_q, op_numerator_d; logic is_greater_equal; logic div_change_sign, rem_change_sign; @@ -70,9 +72,7 @@ module ibex_multdiv_slow //(accum_window_q + op_a_shift_q)>>1 assign res_adder_h = alu_adder_ext_i[33:1]; - always_comb - begin - + always_comb begin alu_operand_a_o = accum_window_q; multdiv_result_o = div_en_i ? accum_window_q[31:0] : res_adder_l; @@ -83,11 +83,9 @@ module ibex_multdiv_slow end MD_OP_MULH: begin - if(curr_state_q == MD_LAST) - alu_operand_b_o = op_a_bw_last_pp; - else - alu_operand_b_o = op_a_bw_pp; + alu_operand_b_o = (curr_state_q == MD_LAST) ? op_a_bw_last_pp : op_a_bw_pp; end + default: begin unique case(curr_state_q) MD_IDLE: begin @@ -113,13 +111,11 @@ module ibex_multdiv_slow default: begin //Division alu_operand_a_o = {accum_window_q[31:0], 1'b1}; //it contains the reminder - alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1}; //denominator negated + 1 to do -denominator + alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1}; //-denominator two's compliment end endcase end - endcase - end /* @@ -130,13 +126,10 @@ module ibex_multdiv_slow The */ - always_comb - begin - if ((accum_window_q[31] ^ op_b_shift_q[31]) == 0) - is_greater_equal = (res_adder_h[31] == 0); - else - is_greater_equal = accum_window_q[31]; - end + assign is_greater_equal = + ((accum_window_q[31] ^ op_b_shift_q[31]) == 1'b0) ? + (res_adder_h[31] == 1'b0) : + accum_window_q[31]; assign one_shift = {32'b0, 1'b1} << multdiv_state_q; @@ -146,9 +139,8 @@ module ibex_multdiv_slow assign b_0 = {32{op_b_shift_q[0]}}; //build the partial product - assign op_a_bw_pp = { ~(op_a_shift_q[32] & op_b_shift_q[0]), op_a_shift_q[31:0] & b_0 }; - - assign op_a_bw_last_pp = { op_a_shift_q[32] & op_b_shift_q[0], ~(op_a_shift_q[31:0] & b_0) }; + assign op_a_bw_pp = { ~(op_a_shift_q[32] & op_b_shift_q[0]), (op_a_shift_q[31:0] & b_0) }; + assign op_a_bw_last_pp = { (op_a_shift_q[32] & op_b_shift_q[0]), ~(op_a_shift_q[31:0] & b_0) }; assign sign_a = op_a_i[31] & signed_mode_i[0]; assign sign_b = op_b_i[31] & signed_mode_i[1]; @@ -159,141 +151,152 @@ module ibex_multdiv_slow //division assign op_remainder = accum_window_q[32:0]; - assign multdiv_state_n = multdiv_state_q - 1; + assign multdiv_state_m1 = multdiv_state_q - 5'h1; assign div_change_sign = sign_a ^ sign_b; assign rem_change_sign = sign_a; always_ff @(posedge clk or negedge rst_n) begin : proc_multdiv_state_q - if(~rst_n) begin - multdiv_state_q <= '0; - accum_window_q <= '0; - op_b_shift_q <= '0; - op_a_shift_q <= '0; + if (!rst_n) begin + multdiv_state_q <= 5'h0; + accum_window_q <= 33'h0; + op_b_shift_q <= 33'h0; + op_a_shift_q <= 33'h0; + op_numerator_q <= 32'h0; curr_state_q <= MD_IDLE; - op_numerator_q <= '0; end else begin - if(mult_en_i | div_en_i) begin - unique case(curr_state_q) - - MD_IDLE: begin - unique case(operator_i) - MD_OP_MULL: begin - op_a_shift_q <= op_a_ext << 1; - accum_window_q <= { ~(op_a_ext[32] & op_b_i[0]), op_a_ext[31:0] & {32{op_b_i[0]}} }; - op_b_shift_q <= op_b_ext >> 1; - curr_state_q <= MD_COMP; - end - MD_OP_MULH: begin - op_a_shift_q <= op_a_ext; - accum_window_q <= { 1'b1, ~(op_a_ext[32] & op_b_i[0]), op_a_ext[31:1] & {31{op_b_i[0]}} }; - op_b_shift_q <= op_b_ext >> 1; - curr_state_q <= MD_COMP; - end - MD_OP_DIV: begin - //Check if the Denominator is 0 - //quotient for division by 0 - accum_window_q <= '1; - curr_state_q <= equal_to_zero ? MD_FINISH : MD_ABS_A; - end - default: begin - //Check if the Denominator is 0 - //reminder for division by 0 - accum_window_q <= op_a_ext; - curr_state_q <= equal_to_zero ? MD_FINISH : MD_ABS_A; - end - endcase - multdiv_state_q <= 5'd31; - end - - MD_ABS_A: begin - //quotient - op_a_shift_q <= '0; - //A abs value - op_numerator_q <= sign_a ? alu_adder_i : op_a_i; - curr_state_q <= MD_ABS_B; - end - - MD_ABS_B: begin - //reminder - accum_window_q <= { 32'h0, op_numerator_q[31]}; - //B abs value - op_b_shift_q <= sign_b ? alu_adder_i : op_b_i; - curr_state_q <= MD_COMP; - end - - MD_COMP: begin - - multdiv_state_q <= multdiv_state_n; - - unique case(operator_i) - MD_OP_MULL: begin - accum_window_q <= res_adder_l; - op_a_shift_q <= op_a_shift_q << 1; - op_b_shift_q <= op_b_shift_q >> 1; - end - MD_OP_MULH: begin - accum_window_q <= res_adder_h; - op_a_shift_q <= op_a_shift_q; - op_b_shift_q <= op_b_shift_q >> 1; - end - default: begin - accum_window_q <= {next_reminder[31:0], op_numerator_q[multdiv_state_n]}; - op_a_shift_q <= next_quotient; - end - endcase - - if(multdiv_state_q == 5'd1) - curr_state_q <= MD_LAST; - else - curr_state_q <= MD_COMP; - end - - MD_LAST: begin - - unique case(operator_i) - MD_OP_MULL: begin - accum_window_q <= res_adder_l; - curr_state_q <= MD_IDLE; - end - MD_OP_MULH: begin - accum_window_q <= res_adder_l; - curr_state_q <= MD_IDLE; - end - MD_OP_DIV: begin - //this time we save the quotient in accum_window_q since we do not need anymore the reminder - accum_window_q <= next_quotient; - curr_state_q <= MD_CHANGE_SIGN; - end - default: begin - //this time we do not save the quotient anymore since we need only the reminder - accum_window_q <= {1'b0, next_reminder[31:0]}; - curr_state_q <= MD_CHANGE_SIGN; - end - endcase - end - - MD_CHANGE_SIGN: begin - curr_state_q <= MD_FINISH; - unique case(operator_i) - MD_OP_DIV: - accum_window_q <= (div_change_sign) ? alu_adder_i : accum_window_q; - default: - accum_window_q <= (rem_change_sign) ? alu_adder_i : accum_window_q; - endcase - end - - MD_FINISH: begin - curr_state_q <= MD_IDLE; - end - - default:; - endcase // curr_state_q - end + multdiv_state_q <= multdiv_state_d; + accum_window_q <= accum_window_d; + op_b_shift_q <= op_b_shift_d; + op_a_shift_q <= op_a_shift_d; + op_numerator_q <= op_numerator_d; + curr_state_q <= curr_state_d; end end + always_comb begin + multdiv_state_d = multdiv_state_q; + accum_window_d = accum_window_q; + op_b_shift_d = op_b_shift_q; + op_a_shift_d = op_a_shift_q; + op_numerator_d = op_numerator_q; + curr_state_d = curr_state_q; + if (mult_en_i || div_en_i) begin + unique case(curr_state_q) + MD_IDLE: begin + unique case(operator_i) + MD_OP_MULL: begin + op_a_shift_d = op_a_ext << 1; + accum_window_d = { ~(op_a_ext[32] & op_b_i[0]), + op_a_ext[31:0] & {32{op_b_i[0]}} }; + op_b_shift_d = op_b_ext >> 1; + curr_state_d = MD_COMP; + end + MD_OP_MULH: begin + op_a_shift_d = op_a_ext; + accum_window_d = { 1'b1, ~(op_a_ext[32] & op_b_i[0]), + op_a_ext[31:1] & {31{op_b_i[0]}} }; + op_b_shift_d = op_b_ext >> 1; + curr_state_d = MD_COMP; + end + MD_OP_DIV: begin + //Check if the Denominator is 0 + //quotient for division by 0 + accum_window_d = {33{1'b1}}; + curr_state_d = equal_to_zero ? MD_FINISH : MD_ABS_A; + end + default: begin + //Check if the Denominator is 0 + //reminder for division by 0 + accum_window_d = op_a_ext; + curr_state_d = equal_to_zero ? MD_FINISH : MD_ABS_A; + end + endcase + multdiv_state_d = 5'd31; + end - assign ready_o = (curr_state_q == MD_FINISH) | (curr_state_q == MD_LAST & (operator_i == MD_OP_MULL | operator_i == MD_OP_MULH)); + MD_ABS_A: begin + //quotient + op_a_shift_d = '0; + //A abs value + op_numerator_d = sign_a ? alu_adder_i : op_a_i; + curr_state_d = MD_ABS_B; + end + MD_ABS_B: begin + //reminder + accum_window_d = { 32'h0, op_numerator_q[31]}; + //B abs value + op_b_shift_d = sign_b ? alu_adder_i : op_b_i; + curr_state_d = MD_COMP; + end + + MD_COMP: begin + multdiv_state_d = multdiv_state_m1; + unique case(operator_i) + MD_OP_MULL: begin + accum_window_d = res_adder_l; + op_a_shift_d = op_a_shift_q << 1; + op_b_shift_d = op_b_shift_q >> 1; + end + MD_OP_MULH: begin + accum_window_d = res_adder_h; + op_a_shift_d = op_a_shift_q; + op_b_shift_d = op_b_shift_q >> 1; + end + default: begin + accum_window_d = {next_reminder[31:0], op_numerator_q[multdiv_state_m1]}; + op_a_shift_d = next_quotient; + end + endcase + + curr_state_d = (multdiv_state_q == 5'd1) ? MD_LAST : MD_COMP; + end + + MD_LAST: begin + unique case(operator_i) + MD_OP_MULL: begin + accum_window_d = res_adder_l; + curr_state_d = MD_IDLE; + end + MD_OP_MULH: begin + accum_window_d = res_adder_l; + curr_state_d = MD_IDLE; + end + MD_OP_DIV: begin + //this time we save the quotient in accum_window_q since we do not need anymore the reminder + accum_window_d = next_quotient; + curr_state_d = MD_CHANGE_SIGN; + end + default: begin + //this time we do not save the quotient anymore since we need only the reminder + accum_window_d = {1'b0, next_reminder[31:0]}; + curr_state_d = MD_CHANGE_SIGN; + end + endcase + end + + MD_CHANGE_SIGN: begin + curr_state_d = MD_FINISH; + unique case(operator_i) + MD_OP_DIV: + accum_window_d = (div_change_sign) ? alu_adder_i : accum_window_q; + default: + accum_window_d = (rem_change_sign) ? alu_adder_i : accum_window_q; + endcase + end + + MD_FINISH: begin + curr_state_d = MD_IDLE; + end + + default:; + endcase // curr_state_q + end + end + + assign ready_o = (curr_state_q == MD_FINISH) | + (curr_state_q == MD_LAST & + (operator_i == MD_OP_MULL | + operator_i == MD_OP_MULH)); endmodule // ibex_mult diff --git a/rtl/ibex_prefetch_buffer.sv b/rtl/ibex_prefetch_buffer.sv index 75e04af4..d757d48b 100644 --- a/rtl/ibex_prefetch_buffer.sv +++ b/rtl/ibex_prefetch_buffer.sv @@ -14,42 +14,44 @@ // long critical paths to the instruction cache // // // //////////////////////////////////////////////////////////////////////////////// - /** * Prefetcher Buffer for 32 bit memory interface * * Prefetch Buffer that caches instructions. This cuts overly long critical * paths to the instruction cache. */ -module ibex_prefetch_buffer -( - input logic clk, - input logic rst_n, +module ibex_prefetch_buffer ( + input logic clk, + input logic rst_n, - input logic req_i, + input logic req_i, - input logic branch_i, - input logic [31:0] addr_i, + input logic branch_i, + input logic [31:0] addr_i, - input logic ready_i, - output logic valid_o, - output logic [31:0] rdata_o, - output logic [31:0] addr_o, + input logic ready_i, + output logic valid_o, + output logic [31:0] rdata_o, + output logic [31:0] addr_o, - // goes to instruction memory / instruction cache - output logic instr_req_o, - input logic instr_gnt_i, - output logic [31:0] instr_addr_o, - input logic [31:0] instr_rdata_i, - input logic instr_rvalid_i, + // goes to instruction memory / instruction cache + output logic instr_req_o, + input logic instr_gnt_i, + output logic [31:0] instr_addr_o, + input logic [31:0] instr_rdata_i, + input logic instr_rvalid_i, - // Prefetch Buffer Status - output logic busy_o + // Prefetch Buffer Status + output logic busy_o ); - enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED } CS, NS; + typedef enum logic [1:0] { + IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED + } prefetch_fsm_e; + + prefetch_fsm_e CS, NS; logic [31:0] instr_addr_q, fetch_addr; logic addr_valid; @@ -58,39 +60,35 @@ module ibex_prefetch_buffer logic fifo_ready; logic fifo_clear; - logic valid_stored; - - ////////////////////////////////////////////////////////////////////////////// // prefetch buffer status ////////////////////////////////////////////////////////////////////////////// - assign busy_o = (CS != IDLE) || instr_req_o; + assign busy_o = (CS != IDLE) | instr_req_o; ////////////////////////////////////////////////////////////////////////////// // fetch fifo // consumes addresses and rdata ////////////////////////////////////////////////////////////////////////////// - ibex_fetch_fifo fifo_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + ibex_fetch_fifo fifo_i ( + .clk ( clk ), + .rst_n ( rst_n ), - .clear_i ( fifo_clear ), + .clear_i ( fifo_clear ), - .in_addr_i ( instr_addr_q ), - .in_rdata_i ( instr_rdata_i ), - .in_valid_i ( fifo_valid ), - .in_ready_o ( fifo_ready ), + .in_addr_i ( instr_addr_q ), + .in_rdata_i ( instr_rdata_i ), + .in_valid_i ( fifo_valid ), + .in_ready_o ( fifo_ready ), - .out_valid_o ( valid_o ), - .out_ready_i ( ready_i ), - .out_rdata_o ( rdata_o ), - .out_addr_o ( addr_o ), + .out_valid_o ( valid_o ), + .out_ready_i ( ready_i ), + .out_rdata_o ( rdata_o ), + .out_addr_o ( addr_o ), - .out_valid_stored_o ( valid_stored ) + .out_valid_stored_o ( ) ); @@ -99,19 +97,14 @@ module ibex_prefetch_buffer ////////////////////////////////////////////////////////////////////////////// assign fetch_addr = {instr_addr_q[31:2], 2'b00} + 32'd4; - - always_comb - begin - fifo_clear = branch_i; - end + assign fifo_clear = branch_i; ////////////////////////////////////////////////////////////////////////////// // instruction fetch FSM // deals with instruction memory / instruction cache ////////////////////////////////////////////////////////////////////////////// - always_comb - begin + always_comb begin instr_req_o = 1'b0; instr_addr_o = fetch_addr; fifo_valid = 1'b0; @@ -120,30 +113,26 @@ module ibex_prefetch_buffer unique case(CS) // default state, not waiting for requested data - IDLE: - begin + IDLE: begin instr_addr_o = fetch_addr; instr_req_o = 1'b0; - if (branch_i) + if (branch_i) begin instr_addr_o = addr_i; + end - if (req_i & (fifo_ready | branch_i )) begin + if (req_i && (fifo_ready || branch_i )) begin instr_req_o = 1'b1; addr_valid = 1'b1; - if(instr_gnt_i) //~> granted request - NS = WAIT_RVALID; - else begin //~> got a request but no grant - NS = WAIT_GNT; - end + //~> granted request or not + NS = instr_gnt_i ? WAIT_RVALID : WAIT_GNT; end end // case: IDLE // we sent a request but did not yet get a grant - WAIT_GNT: - begin + WAIT_GNT: begin instr_addr_o = instr_addr_q; instr_req_o = 1'b1; @@ -152,21 +141,19 @@ module ibex_prefetch_buffer addr_valid = 1'b1; end - if(instr_gnt_i) - NS = WAIT_RVALID; - else - NS = WAIT_GNT; + //~> granted request or not + NS = instr_gnt_i ? WAIT_RVALID : WAIT_GNT; end // case: WAIT_GNT // we wait for rvalid, after that we are ready to serve a new request WAIT_RVALID: begin instr_addr_o = fetch_addr; - if (branch_i) + if (branch_i) begin instr_addr_o = addr_i; + end - - if (req_i & (fifo_ready | branch_i)) begin + if (req_i && (fifo_ready || branch_i)) begin // prepare for next request if (instr_rvalid_i) begin @@ -174,12 +161,8 @@ module ibex_prefetch_buffer fifo_valid = 1'b1; addr_valid = 1'b1; - - if (instr_gnt_i) begin - NS = WAIT_RVALID; - end else begin - NS = WAIT_GNT; - end + //~> granted request or not + NS = instr_gnt_i ? WAIT_RVALID : WAIT_GNT; end else begin // we are requested to abort our current request // we didn't get an rvalid yet, so wait for it @@ -213,18 +196,14 @@ module ibex_prefetch_buffer instr_req_o = 1'b1; // no need to send address, already done in WAIT_RVALID - if (instr_gnt_i) begin - NS = WAIT_RVALID; - end else begin - NS = WAIT_GNT; - end + //~> granted request or not + NS = instr_gnt_i ? WAIT_RVALID : WAIT_GNT; end end - default: - begin - NS = IDLE; - instr_req_o = 1'b0; + default: begin + // NS = IDLE; // unreachable, removing dead code + // instr_req_o = 1'b0; // unreachable, removing dead code end endcase end @@ -233,15 +212,11 @@ module ibex_prefetch_buffer // registers ////////////////////////////////////////////////////////////////////////////// - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin CS <= IDLE; instr_addr_q <= '0; - end - else - begin + end else begin CS <= NS; if (addr_valid) begin diff --git a/rtl/ibex_register_file.sv b/rtl/ibex_register_file.sv index 3b19d635..25eceac0 100644 --- a/rtl/ibex_register_file.sv +++ b/rtl/ibex_register_file.sv @@ -29,31 +29,28 @@ * This register file is based on latches and is thus smaller than the flip-flop * based RF. */ -module ibex_register_file -#( - parameter RV32E = 0, - parameter DATA_WIDTH = 32 -) -( - // Clock and Reset - input logic clk, - input logic rst_n, +module ibex_register_file #( + parameter RV32E = 0, + parameter DATA_WIDTH = 32 +) ( + // Clock and Reset + input logic clk, + input logic rst_n, - input logic test_en_i, + input logic test_en_i, - //Read port R1 - input logic [4:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + //Read port R1 + input logic [4:0] raddr_a_i, + output logic [DATA_WIDTH-1:0] rdata_a_o, - //Read port R2 - input logic [4:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + //Read port R2 + input logic [4:0] raddr_b_i, + output logic [DATA_WIDTH-1:0] rdata_b_o, - - // Write port W1 - input logic [4:0] waddr_a_i, - input logic [DATA_WIDTH-1:0] wdata_a_i, - input logic we_a_i + // Write port W1 + input logic [4:0] waddr_a_i, + input logic [DATA_WIDTH-1:0] wdata_a_i, + input logic we_a_i ); @@ -76,15 +73,8 @@ module ibex_register_file assign raddr_b_int = raddr_b_i[ADDR_WIDTH-1:0]; assign waddr_a_int = waddr_a_i[ADDR_WIDTH-1:0]; - logic clk_int; - int unsigned i; - int unsigned j; - int unsigned k; - - genvar x; - //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- @@ -95,36 +85,34 @@ module ibex_register_file // WRITE : SAMPLE INPUT DATA //--------------------------------------------------------------------------- - clock_gating CG_WE_GLOBAL - ( - .clk_i ( clk ), - .en_i ( we_a_i ), - .test_en_i ( test_en_i ), - .clk_o ( clk_int ) + prim_clock_gating CG_WE_GLOBAL ( + .clk_i ( clk ), + .en_i ( we_a_i ), + .test_en_i ( test_en_i ), + .clk_o ( clk_int ) ); // use clk_int here, since otherwise we don't want to write anything anyway - always_ff @(posedge clk_int, negedge rst_n) - begin : sample_waddr - if (~rst_n) begin - wdata_a_q <= '0; + always_ff @(posedge clk_int, negedge rst_n) begin : sample_waddr + if (!rst_n) begin + wdata_a_q <= '0; end else begin - if(we_a_i) + if (we_a_i) begin wdata_a_q <= wdata_a_i; + end end end //----------------------------------------------------------------------------- //-- WRITE : Write Address Decoder (WAD), combinatorial process //----------------------------------------------------------------------------- - always_comb - begin : p_WADa - for(i = 1; i < NUM_WORDS; i++) - begin : p_WordItera - if ( (we_a_i == 1'b1 ) && (waddr_a_int == i) ) + always_comb begin : p_WADa + for (int i = 1; i < NUM_WORDS; i++) begin : p_WordItera + if (we_a_i && (waddr_a_int == i)) begin waddr_onehot_a[i] = 1'b1; - else + end else begin waddr_onehot_a[i] = 1'b0; + end end end @@ -132,18 +120,14 @@ module ibex_register_file //----------------------------------------------------------------------------- //-- WRITE : Clock gating (if integrated clock-gating cells are available) //----------------------------------------------------------------------------- - generate - for(x = 1; x < NUM_WORDS; x++) - begin : CG_CELL_WORD_ITER - clock_gating CG_Inst - ( - .clk_i ( clk_int ), - .en_i ( waddr_onehot_a[x] ), - .test_en_i ( test_en_i ), - .clk_o ( mem_clocks[x] ) - ); - end - endgenerate + for (genvar x = 1; x < NUM_WORDS; x++) begin : gen_CG_CELL_WORD_ITER + prim_clock_gating CG_Inst ( + .clk_i ( clk_int ), + .en_i ( waddr_onehot_a[x] ), + .test_en_i ( test_en_i ), + .clk_o ( mem_clocks[x] ) + ); + end //----------------------------------------------------------------------------- //-- WRITE : Write operation @@ -154,17 +138,15 @@ module ibex_register_file //-- Use active low, i.e. transparent on low latches as storage elements //-- Data is sampled on rising clock edge - always_latch - begin : latch_wdata + always_latch begin : latch_wdata // Note: The assignment has to be done inside this process or Modelsim complains about it mem[0] = '0; - for(k = 1; k < NUM_WORDS; k++) - begin : w_WordIter - if(mem_clocks[k] == 1'b1) + for (int k = 1; k < NUM_WORDS; k++) begin : w_WordIter + if (mem_clocks[k]) begin mem[k] = wdata_a_q; + end end end - endmodule diff --git a/rtl/ibex_register_file_ff.sv b/rtl/ibex_register_file_ff.sv index d0909491..e8608702 100644 --- a/rtl/ibex_register_file_ff.sv +++ b/rtl/ibex_register_file_ff.sv @@ -27,31 +27,29 @@ * Register file with 31 or 15x 32 bit wide registers. Register 0 is fixed to 0. * This register file is based on flip flops. */ -module ibex_register_file -#( - parameter RV32E = 0, - parameter DATA_WIDTH = 32 -) -( - // Clock and Reset - input logic clk, - input logic rst_n, +module ibex_register_file #( + parameter RV32E = 0, + parameter DATA_WIDTH = 32 +) ( + // Clock and Reset + input logic clk, + input logic rst_n, - input logic test_en_i, + input logic test_en_i, - //Read port R1 - input logic [4:0] raddr_a_i, - output logic [DATA_WIDTH-1:0] rdata_a_o, + //Read port R1 + input logic [4:0] raddr_a_i, + output logic [DATA_WIDTH-1:0] rdata_a_o, - //Read port R2 - input logic [4:0] raddr_b_i, - output logic [DATA_WIDTH-1:0] rdata_b_o, + //Read port R2 + input logic [4:0] raddr_b_i, + output logic [DATA_WIDTH-1:0] rdata_b_o, - // Write port W1 - input logic [4:0] waddr_a_i, - input logic [DATA_WIDTH-1:0] wdata_a_i, - input logic we_a_i + // Write port W1 + input logic [4:0] waddr_a_i, + input logic [DATA_WIDTH-1:0] wdata_a_i, + input logic we_a_i ); @@ -59,44 +57,29 @@ module ibex_register_file localparam NUM_WORDS = 2**ADDR_WIDTH; logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] rf_reg; - logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] rf_reg_tmp; - logic [NUM_WORDS-1:0] we_a_dec; + logic [NUM_WORDS-1:1][DATA_WIDTH-1:0] rf_reg_tmp; + logic [NUM_WORDS-1:1] we_a_dec; - always_comb - begin : we_a_decoder - for (int i = 0; i < NUM_WORDS; i++) begin - if (waddr_a_i == i) - we_a_dec[i] = we_a_i; - else - we_a_dec[i] = 1'b0; + always_comb begin : we_a_decoder + for (int i = 1; i < NUM_WORDS; i++) begin + we_a_dec[i] = (waddr_a_i == i) ? we_a_i : 1'b0; end end - - genvar i; - generate - - // loop from 1 to NUM_WORDS-1 as R0 is nil - for (i = 1; i < NUM_WORDS; i++) - begin : rf_gen - - always_ff @(posedge clk, negedge rst_n) - begin : register_write_behavioral - if (rst_n==1'b0) begin - rf_reg_tmp[i] <= 'b0; - end else begin - if (we_a_dec[i]) - rf_reg_tmp[i] <= wdata_a_i; - end + // loop from 1 to NUM_WORDS-1 as R0 is nil + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + rf_reg_tmp <= '{default:'0}; + end else begin + for (int r = 1; r < NUM_WORDS; r++) begin + if (we_a_dec[r]) rf_reg_tmp[r] <= wdata_a_i; end - end + end - // R0 is nil - assign rf_reg[0] = '0; - assign rf_reg[NUM_WORDS-1:1] = rf_reg_tmp[NUM_WORDS-1:1]; - - endgenerate + // R0 is nil + assign rf_reg[0] = '0; + assign rf_reg[NUM_WORDS-1:1] = rf_reg_tmp[NUM_WORDS-1:1]; assign rdata_a_o = rf_reg[raddr_a_i]; assign rdata_b_o = rf_reg[raddr_b_i]; diff --git a/rtl/ibex_tracer.sv b/rtl/ibex_tracer.sv index c78fb616..33e23957 100644 --- a/rtl/ibex_tracer.sv +++ b/rtl/ibex_tracer.sv @@ -35,54 +35,52 @@ import ibex_tracer_defines::*; /** * Traces the executed instructions */ -module ibex_tracer -#( +module ibex_tracer #( parameter REG_ADDR_WIDTH = 5 -) -( - // Clock and Reset - input logic clk, - input logic rst_n, +) ( + // Clock and Reset + input logic clk, + input logic rst_n, - input logic fetch_enable, - input logic [3:0] core_id, - input logic [5:0] cluster_id, + input logic fetch_enable, + input logic [3:0] core_id, + input logic [5:0] cluster_id, - input logic [31:0] pc, - input logic [31:0] instr, - input logic compressed, - input logic id_valid, - input logic is_decoding, - input logic is_branch, - input logic branch_taken, - input logic pipe_flush, - input logic mret_insn, - input logic ecall_insn, - input logic ebrk_insn, - input logic csr_status, - input logic [31:0] rs1_value, - input logic [31:0] rs2_value, - input logic [31:0] lsu_value, + input logic [31:0] pc, + input logic [31:0] instr, + input logic compressed, + input logic id_valid, + input logic is_decoding, + input logic is_branch, + input logic branch_taken, + input logic pipe_flush, + input logic mret_insn, + input logic ecall_insn, + input logic ebrk_insn, + input logic csr_status, + input logic [31:0] rs1_value, + input logic [31:0] rs2_value, + input logic [31:0] lsu_value, - input logic [(REG_ADDR_WIDTH-1):0] ex_reg_addr, - input logic ex_reg_we, - input logic [31:0] ex_reg_wdata, - input logic data_valid_lsu, - input logic ex_data_req, - input logic ex_data_gnt, - input logic ex_data_we, - input logic [31:0] ex_data_addr, - input logic [31:0] ex_data_wdata, + input logic [(REG_ADDR_WIDTH-1):0] ex_reg_addr, + input logic ex_reg_we, + input logic [31:0] ex_reg_wdata, + input logic data_valid_lsu, + input logic ex_data_req, + input logic ex_data_gnt, + input logic ex_data_we, + input logic [31:0] ex_data_addr, + input logic [31:0] ex_data_wdata, - input logic [31:0] lsu_reg_wdata, + input logic [31:0] lsu_reg_wdata, - input logic [31:0] imm_u_type, - input logic [31:0] imm_uj_type, - input logic [31:0] imm_i_type, - input logic [11:0] imm_iz_type, - input logic [31:0] imm_z_type, - input logic [31:0] imm_s_type, - input logic [31:0] imm_sb_type + input logic [31:0] imm_u_type, + input logic [31:0] imm_uj_type, + input logic [31:0] imm_i_type, + input logic [11:0] imm_iz_type, + input logic [31:0] imm_z_type, + input logic [31:0] imm_s_type, + input logic [31:0] imm_sb_type ); integer f; @@ -122,10 +120,11 @@ module ibex_tracer function string regAddrToStr(input logic [(REG_ADDR_WIDTH-1):0] addr); begin - if (addr < 10) + if (addr < 10) begin return $sformatf(" x%0d", addr); - else + end else begin return $sformatf("x%0d", addr); + end end endfunction @@ -139,13 +138,15 @@ module ibex_tracer str); foreach(regs_write[i]) begin - if (regs_write[i].addr != 0) + if (regs_write[i].addr != 0) begin $fwrite(f, " %s=%08x", regAddrToStr(regs_write[i].addr), regs_write[i].value); + end end foreach(regs_read[i]) begin - if (regs_read[i].addr != 0) + if (regs_read[i].addr != 0) begin $fwrite(f, " %s:%08x", regAddrToStr(regs_read[i].addr), regs_read[i].value); + end end if (mem_access.size() > 0) begin @@ -218,7 +219,7 @@ module ibex_tracer regs_write.push_back('{rd, 'x}); - if (instr[14] == 1'b0) begin + if (!instr[14]) begin regs_read.push_back('{rs1, rs1_value}); str = $sformatf("%-16s x%0d, x%0d, 0x%h", mnemonic, rd, rs1, csr); end else begin @@ -233,8 +234,9 @@ module ibex_tracer begin // detect reg-reg load and find size size = instr[14:12]; - if (instr[14:12] == 3'b111) + if (instr[14:12] == 3'b111) begin size = instr[30:28]; + end case (size) 3'b000: mnemonic = "lb"; @@ -276,7 +278,7 @@ module ibex_tracer end endcase - if (instr[14] == 1'b0) begin + if (!instr[14]) begin // regular store regs_read.push_back('{rs2, rs2_value}); regs_read.push_back('{rs1, rs1_value}); @@ -293,28 +295,25 @@ module ibex_tracer mailbox #(instr_trace_t) instr_wb = new (); // cycle counter - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin cycles = 0; - else + end else begin cycles = cycles + 1; + end end // open/close output file for writing - initial - begin + initial begin wait(rst_n == 1'b1); wait(fetch_enable == 1'b1); $sformat(fn, "trace_core_%h_%h.log", cluster_id, core_id); $display("[TRACER] Output filename is: %s", fn); f = $fopen(fn, "w"); $fwrite(f, " Time Cycles PC Instr Mnemonic\n"); - end - final - begin + final begin $fclose(f); end @@ -324,13 +323,12 @@ module ibex_tracer assign rs3 = instr[`REG_S3]; // log execution - always @(negedge clk) - begin + always @(negedge clk) begin instr_trace_t trace; mem_acc_t mem_acc; // special case for WFI because we don't wait for unstalling there - if ( (id_valid || mret_insn || ecall_insn || pipe_flush || ebrk_insn || csr_status || ex_data_req) && is_decoding) - begin + if ( (id_valid || mret_insn || ecall_insn || pipe_flush || ebrk_insn || + csr_status || ex_data_req) && is_decoding) begin trace = new (); trace.simtime = $time; @@ -403,13 +401,14 @@ module ibex_tracer // replace register written back foreach(trace.regs_write[i]) begin - if ((trace.regs_write[i].addr == ex_reg_addr) && ex_reg_we) + if ((trace.regs_write[i].addr == ex_reg_addr) && ex_reg_we) begin trace.regs_write[i].value = ex_reg_wdata; + end end // look for data accesses and log them if (ex_data_req) begin - if(~ex_data_gnt) begin + if (!ex_data_gnt) begin //we wait until the the gnt comes do @(negedge clk); while (!ex_data_gnt); @@ -418,22 +417,23 @@ module ibex_tracer mem_acc.addr = ex_data_addr; mem_acc.we = ex_data_we; - if (mem_acc.we) + if (mem_acc.we) begin mem_acc.wdata = ex_data_wdata; - else + end else begin mem_acc.wdata = 'x; + end //we wait until the the data instruction ends do @(negedge clk); - while (!data_valid_lsu); + while (!data_valid_lsu); - if (~mem_acc.we) + if (!mem_acc.we) begin //load operations foreach(trace.regs_write[i]) - trace.regs_write[i].value = lsu_reg_wdata; + trace.regs_write[i].value = lsu_reg_wdata; + end trace.mem_access.push_back(mem_acc); end trace.printInstrTrace(); - end end // always @ (posedge clk) diff --git a/rtl/include/ibex_config.sv b/rtl/include/ibex_config.sv index 925e60f6..af48508e 100644 --- a/rtl/include/ibex_config.sv +++ b/rtl/include/ibex_config.sv @@ -27,4 +27,4 @@ //`define SIMCHECKER `endif -//`define CHECK_MISALIGNED \ No newline at end of file +//`define CHECK_MISALIGNED diff --git a/rtl/include/ibex_defines.sv b/rtl/include/ibex_defines.sv index 0f35322a..9467c32d 100644 --- a/rtl/include/ibex_defines.sv +++ b/rtl/include/ibex_defines.sv @@ -243,8 +243,8 @@ parameter IMMB_VU = 4'b0111; parameter IMMB_SHUF = 4'b1000; parameter IMMB_CLIP = 4'b1001; parameter IMMB_BI = 4'b1011; -parameter IMMB_UJ = 4'b1100; -parameter IMMB_SB = 4'b1101; +parameter IMMB_UJ = 4'b1100; +parameter IMMB_SB = 4'b1101; // bit mask selection parameter BMASK_A_ZERO = 1'b0; diff --git a/rtl/include/ibex_tracer_defines.sv b/rtl/include/ibex_tracer_defines.sv index d8e741d1..5edabd83 100644 --- a/rtl/include/ibex_tracer_defines.sv +++ b/rtl/include/ibex_tracer_defines.sv @@ -66,4 +66,4 @@ parameter INSTR_PMULHSU = { 7'b0000001, 10'b?, 3'b010, 5'b?, OPCODE_OP }; parameter INSTR_PMULHU = { 7'b0000001, 10'b?, 3'b011, 5'b?, OPCODE_OP }; -endpackage \ No newline at end of file +endpackage