diff --git a/src/frontend/sras.sv b/src/frontend/sras.sv index 498fddf2a79d9e7326aeb6b6968e37d8d0428637..71208fd8762e8596dcac0cca216abe6d947e5651 100644 --- a/src/frontend/sras.sv +++ b/src/frontend/sras.sv @@ -38,48 +38,48 @@ module sras #( assign ptr_spec_d = (bad_spec_i) ? ptr_backup_q : (begin_spec_i) ? ptr_spec_q + 1'b1 : ptr_spec_q; assign ptr_backup_d = (valid_spec_i) ? ptr_backup_q + 1'b1 : ptr_backup_q; - always_comb begin - stack_d = stack_q; - tos_d = tos_q; + logic [$clog2(SpecDepth)-1:0] previous_tos_addr; + logic [$clog2(DEPTH)-1:0] previous_tos, prev_plus_one, pp_plus_one, prev_minus_one; - if (!bad_spec_i && begin_spec_i) begin - stack_d[ptr_spec_d] = stack_q[ptr_spec_q]; - tos_d[ptr_spec_d] = tos_q[ptr_spec_q]; - end + assign previous_tos_addr = (!bad_spec_i && begin_spec_i) ? ptr_spec_q : ptr_spec_d; + assign previous_tos = tos_q[previous_tos_addr]; - data_o = stack_d[ptr_spec_d][tos_d[ptr_spec_d]]; + assign prev_plus_one = previous_tos + 1'b1; + assign pp_plus_one = tos_q[ptr_spec_q] + 1'b1; + assign prev_minus_one = previous_tos - 1'b1; - // leave everything untouched and just push the latest value to the - // top of the stack - if (pop_i && push_i) begin - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = data_i; - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b1; - end else begin - // push on the stack - if (push_i) begin - tos_d[ptr_spec_d] = tos_d[ptr_spec_d] + 1'b1; - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = data_i; - // mark the new return address as valid - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b1; - - if (begin_spec_i) begin - tos_d[ptr_spec_q] = tos_d[ptr_spec_q] + 1'b1; - stack_d[ptr_spec_q][tos_d[ptr_spec_q]] = stack_d[ptr_spec_d][tos_d[ptr_spec_d]]; - end - end - - if (pop_i) begin - // we popped the value so invalidate the end of the stack - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].ra = '0; - stack_d[ptr_spec_d][tos_d[ptr_spec_d]].valid = 1'b0; - tos_d[ptr_spec_d] = tos_d[ptr_spec_d] - 1'b1; - end - end + for (genvar i = 0; i < SpecDepth; i++) begin + assign tos_d[i] = (flush_i) ? '0 : + (i == ptr_spec_d && push_i && !pop_i) ? prev_plus_one : + (i == ptr_spec_q && push_i && !pop_i) ? pp_plus_one : + (i == ptr_spec_d && !push_i && pop_i) ? prev_minus_one : + (i == ptr_spec_d && !bad_spec_i && begin_spec_i) ? tos_q[ptr_spec_q] : + tos_q[i]; + end - if (flush_i) begin - stack_d = '0; - tos_d = '0; - end + assign data_o = stack_q[previous_tos_addr][previous_tos]; + + ariane_pkg::ras_t to_push; + assign to_push.ra = (push_i) ? data_i : 0; + assign to_push.valid = push_i; + + ariane_pkg::ras_t [DEPTH-1:0] new_stack, prev_stack; + + for (genvar i = 0; i < DEPTH; i++) begin + assign new_stack[i] = ((i == previous_tos && pop_i) || + (i == prev_plus_one && push_i)) ? to_push : + (!bad_spec_i && begin_spec_i) ? stack_q[ptr_spec_q][i] : + stack_q[ptr_spec_d][i]; + + assign prev_stack[i] = (i == pp_plus_one && push_i) ? to_push : + stack_q[ptr_spec_q][i]; + end + + for (genvar i = 0; i < SpecDepth; i++) begin + assign stack_d[i] = (flush_i) ? '0 : + (i == ptr_spec_d) ? new_stack : + (i == ptr_spec_q) ? prev_stack : + stack_q[i]; end always_ff @(posedge clk_i or negedge rst_ni) begin