From bebc87535394c983b5b45f778f88ccb38f542c3e Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Tue, 19 Mar 2024 09:42:32 +0100 Subject: [PATCH] Make serv_state more simulator-friendly Refactor the counter generation code to avoid using combinatorial always statements that rely on an event happening at time 0. This make serv work with Icarus again. --- rtl/serv_state.v | 55 +++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 012a85e4..02cd02bc 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -12,7 +12,7 @@ module serv_state input wire i_new_irq, input wire i_alu_cmp, output wire o_init, - output reg o_cnt_en, + output wire o_cnt_en, output wire o_cnt0to3, output wire o_cnt12to31, output wire o_cnt0, @@ -62,7 +62,7 @@ module serv_state wire misalign_trap_sync; reg [4:2] o_cnt; - reg [3:0] cnt_r; + wire [3:0] cnt_r; reg ibus_cyc; //Update PC in RUN or TRAP states @@ -153,7 +153,7 @@ module serv_state end end - always @(posedge i_clk) begin + generate /* Because SERV is 32-bit bit-serial we need a counter than can count 0-31 to keep track of which bit we are currently processing. o_cnt and cnt_r @@ -176,30 +176,33 @@ module serv_state just need to check if cnt_r is not zero to see if the counter is currently running */ - if (W == 4) begin - if (i_rf_ready) o_cnt_en <= 1; else - if (o_cnt_done) o_cnt_en <= 0; - o_cnt <= o_cnt + { 2'b0, o_cnt_en }; - end else if (W == 1) begin - o_cnt <= o_cnt + {2'd0,cnt_r[3]}; - cnt_r <= {cnt_r[2:0],(cnt_r[3] & !o_cnt_done) | (i_rf_ready & !o_cnt_en)}; - end - if (i_rst) begin - if (RESET_STRATEGY != "NONE") begin - o_cnt <= 3'd0; - if (W == 1) - cnt_r <= 4'b0000; - else if (W == 4) - o_cnt_en <= 1'b0; - end + if (W == 1) begin : gen_cnt_w_eq_1 + reg [3:0] cnt_lsb; + always @(posedge i_clk) begin + o_cnt <= o_cnt + {2'd0,cnt_r[3]}; + cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | (i_rf_ready & !o_cnt_en)}; + if (i_rst & (RESET_STRATEGY != "NONE")) begin + o_cnt <= 3'd0; + cnt_lsb <= 4'b0000; + end + end + assign cnt_r = cnt_lsb; + assign o_cnt_en = |cnt_lsb; + end else if (W == 4) begin : gen_cnt_w_eq_4 + reg cnt_en; + always @(posedge i_clk) begin + if (i_rf_ready) cnt_en <= 1; else + if (o_cnt_done) cnt_en <= 0; + o_cnt <= o_cnt + { 2'd0, cnt_en }; + if (i_rst & (RESET_STRATEGY != "NONE")) begin + o_cnt <= 3'd0; + cnt_en <= 1'b0; + end + end + assign cnt_r = 4'b1111; + assign o_cnt_en = cnt_en; end - end - - always @(*) - if (W == 1) - o_cnt_en = |cnt_r; - else if (W == 4) - cnt_r = 4'b1111; + endgenerate assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync);