diff --git a/compressed_decoder.sv b/compressed_decoder.sv index 048077cb..a9cfc85f 100644 --- a/compressed_decoder.sv +++ b/compressed_decoder.sv @@ -264,7 +264,8 @@ module compressed_decoder endcase end - 2'b11: begin + // 2'b11: + default: begin // 32 bit (or more) instruction instr_o = instr_i; end diff --git a/if_stage.sv b/if_stage.sv index 63603517..bbe773e4 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -89,51 +89,41 @@ module if_stage ); // offset FSM - enum logic[3:0] {WAIT_ALIGNED, VALID_ALIGNED, - UNALIGNED_16, - WAIT_UNALIGNED_32, VALID_UNALIGNED_32, - WAIT_JUMPED_ALIGNED, VALID_JUMPED_ALIGNED, - WAIT_JUMPED_UNALIGNED, VALID_JUMPED_UNALIGNED, + enum logic[3:0] {WAIT_ALIGNED, WAIT_UNALIGNED, IDLE } offset_fsm_cs, offset_fsm_ns; logic [1:0] is_compressed; - logic crossword; logic unaligned; logic unaligned_jump; // instr_core_interface - logic fetch_req; - logic [31:0] fetch_rdata; + logic branch_req; + logic [31:0] fetch_addr_n; + logic fetch_valid; - logic [31:0] fetch_addr_n, fetch_addr_Q, fetch_addr_QQ; + logic fetch_ready; + logic [31:0] fetch_rdata; + logic [31:0] fetch_addr; + + logic fetch_unaligned_valid; + logic [31:0] fetch_unaligned_rdata; + logic [31:0] instr_rdata_int; logic [31:0] exc_pc; - // local cache - logic [15:0] data_arr; - // output data and PC mux always_comb begin // default values for regular aligned access instr_rdata_int = fetch_rdata; - current_pc_if_o = {fetch_addr_Q[31:2], 2'b00}; + current_pc_if_o = {fetch_addr[31:2], 2'b00}; if (unaligned) begin - if (crossword) begin - // cross-word access, regular instruction - instr_rdata_int = {fetch_rdata[15:0], data_arr}; - current_pc_if_o = {fetch_addr_QQ[31:2], 2'b10}; - end else begin - // unaligned compressed instruction - // don't care about upper half-word, insert good value for - // optimization - instr_rdata_int = {fetch_rdata[15:0], fetch_rdata[31:16]}; - current_pc_if_o = {fetch_addr_Q[31:2], 2'b10}; - end + current_pc_if_o = {fetch_addr[31:2], 2'b10}; + instr_rdata_int = fetch_unaligned_rdata; end end @@ -161,7 +151,8 @@ module if_stage `PC_BOOT: fetch_addr_n = {boot_addr_i[31:5], `EXC_OFF_RST}; `PC_JUMP: fetch_addr_n = {jump_target_id_i[31:2], 2'b0}; `PC_BRANCH: fetch_addr_n = {jump_target_ex_i[31:2], 2'b0}; - `PC_INCR: fetch_addr_n = fetch_addr_Q + 32'd4; // incremented PC + // TODO: remove the next entry + `PC_INCR: fetch_addr_n = 'X; // no longer needed, remove! `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_HWLOOP: fetch_addr_n = hwloop_target_i; // PC is taken from hwloop start addr @@ -193,20 +184,26 @@ module if_stage // cache fetch interface instr_core_interface instr_core_if_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), - .req_i ( fetch_req ), - .addr_i ( fetch_addr_n ), - .valid_o ( fetch_valid ), - .rdata_o ( fetch_rdata ), - .last_addr_o ( fetch_addr_Q ), + .req_i ( 1'b1 ), + .clear_i ( branch_req ), + .addr_i ( fetch_addr_n ), - .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 ) + .ready_i ( fetch_ready ), + .valid_o ( fetch_valid ), + .rdata_o ( fetch_rdata ), + .addr_o ( fetch_addr ), + + .unaligned_valid_o ( fetch_unaligned_valid ), + .unaligned_rdata_o ( fetch_unaligned_rdata ), + + .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 ) ); @@ -225,162 +222,69 @@ module if_stage begin offset_fsm_ns = offset_fsm_cs; - fetch_req = 1'b0; - valid_o = 1'b0; + fetch_ready = 1'b0; + branch_req = 1'b0; + valid_o = 1'b0; unaligned = 1'b0; - crossword = 1'b0; unique case (offset_fsm_cs) // no valid instruction data for ID stage // assume aligned IDLE: begin if (req_i) begin - fetch_req = 1'b1; - offset_fsm_ns = WAIT_JUMPED_ALIGNED; + branch_req = 1'b1; + offset_fsm_ns = WAIT_ALIGNED; end end // serving aligned 32 bit or 16 bit instruction, we don't know yet - WAIT_ALIGNED, - VALID_ALIGNED: begin - if (fetch_valid || offset_fsm_cs == VALID_ALIGNED) begin + WAIT_ALIGNED: begin + if (fetch_valid) begin valid_o = 1'b1; // an instruction is ready for ID stage - offset_fsm_ns = VALID_ALIGNED; if (req_i && ~stall_if_i) begin if (~is_compressed[0]) begin // 32 bit aligned instruction found - fetch_req = 1'b1; + fetch_ready = 1'b1; offset_fsm_ns = WAIT_ALIGNED; end else begin // 16 bit aligned instruction found - if (is_compressed[1]) begin - // next is 16 bit unaligned instruction - // we already have that data, no need to fetch anything - offset_fsm_ns = UNALIGNED_16; - end else begin - // next is 32 bit unaligned instruction - // the upper half of this instruction is missing, start - // fetching it - fetch_req = 1'b1; - offset_fsm_ns = WAIT_UNALIGNED_32; - end + // next instruction will be unaligned + offset_fsm_ns = WAIT_UNALIGNED; end end end end - // serving unaligned 16 bit instruction - // next instruction will be aligned, either 16 bit or 32 bit - UNALIGNED_16: begin - unaligned = 1'b1; - - // we don't need to wait for a fetch_valid as we already have the data - valid_o = 1'b1; - - if (req_i && ~stall_if_i) begin - // next instruction will be aligned - fetch_req = 1'b1; - offset_fsm_ns = WAIT_ALIGNED; - end - end - // serving unaligned 32 bit instruction // next instruction might be 16 bit unaligned (no need to fetch) // or 32 bit unaligned (need to fetch another word from cache) - WAIT_UNALIGNED_32, - VALID_UNALIGNED_32: begin - unaligned = 1'b1; - crossword = 1'b1; - - if (fetch_valid || offset_fsm_cs == VALID_UNALIGNED_32) begin - valid_o = 1'b1; - offset_fsm_ns = VALID_UNALIGNED_32; - - if (req_i && ~stall_if_i) begin - - if (is_compressed[1]) begin - // next is 16 bit unaligned instruction - // we already have that data, no need to fetch anything - offset_fsm_ns = UNALIGNED_16; - end else begin - // next is 32 bit unaligned instruction - // the upper half of this instruction is missing, start - // fetching it - fetch_req = 1'b1; - offset_fsm_ns = WAIT_UNALIGNED_32; - end - end - end - end - - // we did an aligned jump - // current instruction is either 16 bit aligned or 32 bit aligned - // so next instruction can be one of the following: - // - 32 bit aligned (if 32 bit aligned now) - // - 16 bit unaligned (if 16 bit aligned now) - // - 32 bit unaligned (if 16 bit aligned now) - WAIT_JUMPED_ALIGNED, - VALID_JUMPED_ALIGNED: begin - - if (fetch_valid || offset_fsm_cs == VALID_JUMPED_ALIGNED) begin - valid_o = 1'b1; - offset_fsm_ns = VALID_JUMPED_ALIGNED; - - if (req_i && ~stall_if_i) begin - - if (is_compressed[0]) begin - // this instruction is 16 bit - - if (is_compressed[1]) begin - // next instruction is also 16 bit - offset_fsm_ns = UNALIGNED_16; - end else begin - // next is 32 bit unaligned instruction - // the upper half of this instruction is missing, start - // fetching it - fetch_req = 1'b1; - offset_fsm_ns = WAIT_UNALIGNED_32; - end - end else begin - // this instruction is 32 bit, so next one will be aligned - fetch_req = 1'b1; - offset_fsm_ns = WAIT_ALIGNED; - end - end - end - end - - // we did an unaligned jump - // current instruction is either 16 bit unaligned (ready to serve) or 32 - // bit unaligned (still need to get data) - WAIT_JUMPED_UNALIGNED, - VALID_JUMPED_UNALIGNED: begin + WAIT_UNALIGNED: begin unaligned = 1'b1; - if (fetch_valid || offset_fsm_cs == VALID_JUMPED_UNALIGNED) begin - // here we might not yet have the data, if the instruction is 32 bit - // unaligned - offset_fsm_ns = VALID_JUMPED_UNALIGNED; - + if (fetch_valid) begin if (is_compressed[1]) begin - // Puh, lucky, we got a 16 bit instruction - valid_o = 1'b1; + valid_o = 1'b1; // an instruction is ready for ID stage if (req_i && ~stall_if_i) begin // next instruction will be aligned - fetch_req = 1'b1; + fetch_ready = 1'b1; offset_fsm_ns = WAIT_ALIGNED; end - end else begin - // a 32 bit unaligned instruction, let's fetch the upper half - // we don't wait for stalls here as we still need data to get - // unstalled - fetch_req = 1'b1; - offset_fsm_ns = WAIT_UNALIGNED_32; + // not compressed, we are looking at a 32 bit instruction + + if (fetch_unaligned_valid) begin + valid_o = 1'b1; // an instruction is ready for ID stage + + if (req_i && ~stall_if_i) begin + // next instruction will be unaligned + fetch_ready = 1'b1; + offset_fsm_ns = WAIT_UNALIGNED; + end + end end end end @@ -396,50 +300,34 @@ module if_stage if (jump_in_ex_i == `BRANCH_COND) begin if (branch_decision_i) begin // branch taken - fetch_req = 1'b1; + branch_req = 1'b1; if (unaligned_jump) - offset_fsm_ns = WAIT_JUMPED_UNALIGNED; + offset_fsm_ns = WAIT_UNALIGNED; else - offset_fsm_ns = WAIT_JUMPED_ALIGNED; + offset_fsm_ns = WAIT_ALIGNED; end end else if (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR || dbg_set_npc_i || hwloop_jump_i) begin // switch to new PC from ID stage - fetch_req = 1'b1; + branch_req = 1'b1; if (unaligned_jump) - offset_fsm_ns = WAIT_JUMPED_UNALIGNED; + offset_fsm_ns = WAIT_UNALIGNED; else - offset_fsm_ns = WAIT_JUMPED_ALIGNED; + offset_fsm_ns = WAIT_ALIGNED; end end end - // store instr_core_if data in local cache - // store last address used to fetch an instruction - // we also store the address we used before, so - // fetch_addr_n -> fetch_addr_Q -> fetch_addr_QQ - always_ff @(posedge clk, negedge rst_n) - begin - if (rst_n == 1'b0) begin - data_arr <= 16'b0; - fetch_addr_QQ <= 32'b0; - end else begin - if (fetch_req) begin - data_arr <= fetch_rdata[31:16]; - fetch_addr_QQ <= fetch_addr_Q; - end - end - end - - assign if_busy_o = ~(offset_fsm_cs == IDLE || - offset_fsm_cs == VALID_JUMPED_ALIGNED || - offset_fsm_cs == VALID_JUMPED_UNALIGNED || - offset_fsm_cs == VALID_ALIGNED || - offset_fsm_cs == VALID_UNALIGNED_32 || - offset_fsm_cs == UNALIGNED_16) || instr_req_o; + assign if_busy_o = 1'b1; // TODO + // assign if_busy_o = ~(offset_fsm_cs == IDLE || + // offset_fsm_cs == VALID_JUMPED_ALIGNED || + // offset_fsm_cs == VALID_JUMPED_UNALIGNED || + // offset_fsm_cs == VALID_ALIGNED || + // offset_fsm_cs == VALID_UNALIGNED_32 || + // offset_fsm_cs == UNALIGNED_16) || instr_req_o; diff --git a/instr_core_interface.sv b/instr_core_interface.sv index 4e28bfdd..0eba8010 100644 --- a/instr_core_interface.sv +++ b/instr_core_interface.sv @@ -23,18 +23,194 @@ // // //////////////////////////////////////////////////////////////////////////////// +// input port: send address one cycle before the data +// clear_i clears the FIFO for the following cycle. in_addr_i can be sent in +// this cycle already +module fetch_fifo +( + input logic clk, + input logic rst_n, + // control signals + input logic clear_i, // clears the contents of the fifo + + // input port + input logic in_addr_valid_i, + output logic in_addr_ready_o, + input logic [31:0] in_addr_i, + output logic [31:0] in_last_addr_o, + + input logic in_rdata_valid_i, + output logic in_rdata_ready_o, + input logic [31:0] in_rdata_i, + + // output port + output logic out_valid_o, + input logic out_ready_i, + output logic [31:0] out_rdata_o, + output logic [31:0] out_addr_o, + + output logic out_unaligned_valid_o, + output logic [31:0] out_unaligned_rdata_o + ); + + localparam DEPTH = 2; // must be 2 or greater + + // index 0 is used for output + logic [0:DEPTH-1] [31:0] addr_n, addr_int, addr_Q; + logic [0:DEPTH-1] addr_valid_n, addr_valid_int, addr_valid_Q; + logic [0:DEPTH-1] [31:0] rdata_n, rdata_int, rdata_Q; + logic [0:DEPTH-1] rdata_valid_n, rdata_valid_int, rdata_valid_Q; + + ////////////////////////////////////////////////////////////////////////////// + // output port + ////////////////////////////////////////////////////////////////////////////// + + // output assignments + assign out_rdata_o = (rdata_valid_Q[0]) ? rdata_Q[0] : in_rdata_i; + assign out_addr_o = addr_Q[0]; // always output addr directly since we sent it one cycle earlier to the FIFO + + assign out_valid_o = (rdata_valid_Q[0] || (addr_valid_Q[0] && in_rdata_valid_i)); + + assign out_unaligned_rdata_o = (rdata_valid_Q[1]) ? {rdata_Q[1][15:0], rdata_Q[0][31:16]} : {in_rdata_i[15:0], rdata_Q[0][31:16]}; + // it is implied that rdata_valid_Q[0] is set + assign out_unaligned_valid_o = (rdata_valid_Q[1] || (addr_valid_Q[1] && in_rdata_valid_i)); + + + + ////////////////////////////////////////////////////////////////////////////// + // input port + ////////////////////////////////////////////////////////////////////////////// + + // we accept addresses as long as our fifo is not full or we are cleared + assign in_addr_ready_o = clear_i || (~addr_valid_Q[DEPTH-1]); + + // we accept data as long as our fifo is not full + // we don't care about clear here as the data will be received one cycle + // later anyway + assign in_rdata_ready_o = ~rdata_valid_Q[DEPTH-1]; + + + // output the latest valid address we got + int i; + always_comb + begin + in_last_addr_o = addr_Q[0]; + + for(i = 1; i < DEPTH; i++) begin + if (addr_valid_Q[i]) + in_last_addr_o = addr_Q[i]; + end + end + + ////////////////////////////////////////////////////////////////////////////// + // FIFO management + ////////////////////////////////////////////////////////////////////////////// + + int j; + always_comb + begin + addr_int = addr_Q; + addr_valid_int = addr_valid_Q; + + if (in_addr_valid_i && in_addr_ready_o) begin + for(j = 0; j < DEPTH; j++) begin + if (~addr_valid_Q[j]) begin + addr_int[j] = in_addr_i; + addr_valid_int[j] = 1'b1; + + break; + end + end + end + end + + int k; + always_comb + begin + rdata_int = rdata_Q; + rdata_valid_int = rdata_valid_Q; + + if (in_rdata_valid_i && in_rdata_ready_o) begin + for(k = 0; k < DEPTH; k++) begin + if (~rdata_valid_Q[k]) begin + rdata_int[k] = in_rdata_i; + rdata_valid_int[k] = 1'b1; + + break; + end + end + end + end + + // move everything by one step + always_comb + begin + addr_n = addr_int; + addr_valid_n = addr_valid_int; + rdata_n = rdata_int; + rdata_valid_n = rdata_valid_int; + + if (out_ready_i && out_valid_o) begin + addr_n = {addr_int[1:DEPTH-1], 32'b0}; + addr_valid_n = {addr_valid_int[1:DEPTH-1], 1'b0}; + rdata_n = {rdata_int[1:DEPTH-1], 32'b0}; + rdata_valid_n = {rdata_valid_int[1:DEPTH-1], 1'b0}; + end + end + + ////////////////////////////////////////////////////////////////////////////// + // registers + ////////////////////////////////////////////////////////////////////////////// + + always_ff @(posedge clk, negedge rst_n) + begin + if(rst_n == 1'b0) + begin + addr_Q <= '{default: '0}; + addr_valid_Q <= '0; + rdata_Q <= '{default: '0}; + rdata_valid_Q <= '0; + 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 + addr_Q[0] <= in_addr_i; + addr_valid_Q <= {in_addr_valid_i, {DEPTH-1{1'b0}}}; + rdata_valid_Q <= '0; + end else begin + addr_Q <= addr_n; + addr_valid_Q <= addr_valid_n; + rdata_Q <= rdata_n; + rdata_valid_Q <= rdata_valid_n; + end + end + end + +endmodule + +// clear_i deletes everything up to now, i.e. it assumes that addr_i now has +// the correct state and uses the current cycle's addr_i to fetch new data module instr_core_interface ( input logic clk, input logic rst_n, input logic req_i, + input logic clear_i, + input logic ready_i, input logic [31:0] addr_i, + output logic valid_o, output logic [31:0] rdata_o, - output logic [31:0] last_addr_o, + output logic [31:0] addr_o, + output logic unaligned_valid_o, + output logic [31:0] unaligned_rdata_o, + + // goes to instruction memory / instruction cache output logic instr_req_o, output logic [31:0] instr_addr_o, input logic instr_gnt_i, @@ -42,56 +218,84 @@ module instr_core_interface input logic [31:0] instr_rdata_i ); - enum logic [1:0] {IDLE, WAIT_RVALID, WAIT_GNT } CS, NS; + // TODO: THERE IS A PROBLEM WIHT REQ_I AND CLEAR_I + // i.e. what happens if req_i is low and clear_i is high? the core will miss + // the updated address.... - logic [31:0] rdata_Q; + enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED } CS, NS; - logic wait_gnt; - logic [31:0] addr_Q; + logic [31:0] addr_next; - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin - CS <= IDLE; - rdata_Q <= '0; - addr_Q <= '0; - end - else - begin - CS <= NS; + logic fifo_addr_valid; + logic fifo_addr_ready; + logic [31:0] fifo_last_addr; - if (wait_gnt) - addr_Q <= instr_addr_o; + logic fifo_rdata_valid; + logic fifo_rdata_ready; - if (instr_rvalid_i) - rdata_Q <= instr_rdata_i; - end - end - assign valid_o = instr_rvalid_i; - assign last_addr_o = addr_Q; + ////////////////////////////////////////////////////////////////////////////// + // address selection and increase + ////////////////////////////////////////////////////////////////////////////// + + assign addr_next = (clear_i) ? addr_i : (fifo_last_addr + 32'd4); + + + ////////////////////////////////////////////////////////////////////////////// + // fetch fifo + // consumes addresses and rdata + ////////////////////////////////////////////////////////////////////////////// + + fetch_fifo fifo_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + .clear_i ( clear_i ), + + .in_addr_valid_i ( fifo_addr_valid ), + .in_addr_ready_o ( fifo_addr_ready ), + .in_addr_i ( addr_next ), + .in_last_addr_o ( fifo_last_addr ), + + .in_rdata_valid_i ( fifo_rdata_valid ), + .in_rdata_ready_o ( fifo_rdata_ready ), + .in_rdata_i ( instr_rdata_i ), + + .out_valid_o ( valid_o ), + .out_ready_i ( ready_i ), + .out_rdata_o ( rdata_o ), + .out_addr_o ( addr_o ), + + .out_unaligned_valid_o ( unaligned_valid_o ), + .out_unaligned_rdata_o ( unaligned_rdata_o ) + ); + + + ////////////////////////////////////////////////////////////////////////////// + // instruction fetch FSM + // deals with instruction memory / instruction cache + ////////////////////////////////////////////////////////////////////////////// always_comb begin - instr_req_o = 1'b0; - rdata_o = instr_rdata_i; - instr_addr_o = addr_i; - wait_gnt = 1'b0; - NS = CS; + instr_req_o = 1'b0; + instr_addr_o = addr_next; + fifo_addr_valid = 1'b0; + fifo_rdata_valid = 1'b0; + NS = CS; unique case(CS) // default state, not waiting for requested data IDLE: begin - rdata_o = rdata_Q; - instr_req_o = 1'b0; - if(req_i) begin + if (req_i && fifo_addr_ready) begin instr_req_o = 1'b1; - wait_gnt = 1'b1; + fifo_addr_valid = 1'b1; + if(instr_gnt_i) //~> granted request NS = WAIT_RVALID; else begin //~> got a request but no grant @@ -103,25 +307,85 @@ module instr_core_interface // we sent a request but did not yet get a grant WAIT_GNT: begin - instr_addr_o = addr_Q; - instr_req_o = 1'b1; - if(instr_gnt_i) - NS = WAIT_RVALID; - else - NS = WAIT_GNT; + if (clear_i) begin + instr_addr_o = addr_next; + + if (req_i && fifo_addr_ready) begin + instr_req_o = 1'b1; + + fifo_addr_valid = 1'b1; + + if(instr_gnt_i) //~> granted request + NS = WAIT_ABORTED; + else begin //~> got a request but no grant + NS = WAIT_GNT; + end + end else begin + if(instr_gnt_i) //~> granted request + NS = WAIT_ABORTED; + else begin //~> got a request but no grant + NS = IDLE; + end + end + + end else begin + instr_req_o = 1'b1; + instr_addr_o = fifo_last_addr; + + if(instr_gnt_i) + NS = WAIT_RVALID; + else + NS = WAIT_GNT; + end end // case: WAIT_GNT // we wait for rvalid, after that we are ready to serve a new request - WAIT_RVALID : - begin + WAIT_RVALID: begin - if (req_i) begin + if (req_i && fifo_addr_ready) begin // prepare for next request instr_req_o = 1'b1; if (instr_rvalid_i) begin - wait_gnt = 1'b1; + fifo_rdata_valid = 1'b1; + fifo_addr_valid = 1'b1; + + if (instr_gnt_i) begin + NS = WAIT_RVALID; + end else begin + NS = WAIT_GNT; + end + end else begin + // we are requested to abort our current request + if (clear_i) + NS = WAIT_ABORTED; + end + end else begin + // just wait for rvalid and go back to IDLE, no new request + // requested + instr_req_o = 1'b0; + + if (instr_rvalid_i) begin + fifo_rdata_valid = 1'b1; + NS = IDLE; + end else begin + if (clear_i) + NS = WAIT_ABORTED; + end + end + end // case: WAIT_RVALID + + // our last request was aborted, but we didn't yet get a rvalid and + // there was no new request sent yet + WAIT_ABORTED: begin + if (req_i && fifo_addr_ready) begin + // prepare for next request + instr_req_o = 1'b1; + + if (instr_rvalid_i) begin + fifo_addr_valid = 1'b1; + if (instr_gnt_i) begin NS = WAIT_RVALID; end else begin @@ -137,7 +401,7 @@ module instr_core_interface NS = IDLE; end end - end // case: WAIT_RVALID + end default: begin @@ -147,4 +411,20 @@ module instr_core_interface endcase end + ////////////////////////////////////////////////////////////////////////////// + // registers + ////////////////////////////////////////////////////////////////////////////// + + always_ff @(posedge clk, negedge rst_n) + begin + if(rst_n == 1'b0) + begin + CS <= IDLE; + end + else + begin + CS <= NS; + end + end + endmodule