diff --git a/src/fetch_fifo.sv b/src/fetch_fifo.sv index 1226ddfcc..911059d93 100644 --- a/src/fetch_fifo.sv +++ b/src/fetch_fifo.sv @@ -23,219 +23,178 @@ import ariane_pkg::*; // 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 +// clear_i clears the FIFO for the following cycle. 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 [63:0] in_addr_i, input logic [31:0] in_rdata_i, input logic in_valid_i, output logic in_ready_o, - // output port output logic [63:0] out_addr_o, output logic [31:0] out_rdata_o, output logic out_valid_o, - input logic out_ready_i, + input logic out_ready_i +); - 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 = 4; // must be 3 or greater + /* verilator lint_off LITENDIAN */ + // index 0 is used for output + logic [0:DEPTH-1] [63:0] addr_n, addr_int, addr_Q; + logic [0:DEPTH-1] [31:0] rdata_n, rdata_int, rdata_Q; + logic [0:DEPTH-1] valid_n, valid_int, valid_Q; - localparam DEPTH = 4; // must be 3 or greater - /* verilator lint_off LITENDIAN */ - // index 0 is used for output - logic [0:DEPTH-1] [63:0] addr_n, addr_int, addr_Q; - logic [0:DEPTH-1] [31:0] rdata_n, rdata_int, rdata_Q; - logic [0:DEPTH-1] valid_n, valid_int, valid_Q; + logic [63:0] addr_next; + logic [31:0] rdata, rdata_unaligned; + logic valid, valid_unaligned; - logic [63:0] 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; + /* lint_on */ - logic aligned_is_compressed, unaligned_is_compressed; - logic aligned_is_compressed_st, unaligned_is_compressed_st; - /* lint_on */ - //---------------------------------------------------------------------------- - // output port - //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + // output port + //---------------------------------------------------------------------------- + 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]}; + // it is implied that rdata_valid_Q[0] is set + assign valid_unaligned = (valid_Q[1] || (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 unaligned_is_compressed = rdata[17:16] != 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; - 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)); + //---------------------------------------------------------------------------- + // instruction aligner (if unaligned) + //---------------------------------------------------------------------------- + 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 + if (out_addr_o[1]) begin + // unaligned case + out_rdata_o = rdata_unaligned; - assign unaligned_is_compressed = rdata[17:16] != 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 - // 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 - if (out_addr_o[1]) begin - // unaligned case - out_rdata_o = rdata_unaligned; - - if (unaligned_is_compressed) + if (unaligned_is_compressed) + out_valid_o = valid; + else + out_valid_o = valid_unaligned; + end else begin + // aligned case + out_rdata_o = rdata; out_valid_o = valid; - else - out_valid_o = valid_unaligned; - end else begin - // aligned case - out_rdata_o = rdata; - out_valid_o = valid; - end - end - - 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 - out_valid_stored_o = 1'b1; - - if (out_addr_o[1]) begin - if (unaligned_is_compressed_st) - out_valid_stored_o = 1'b1; - else - out_valid_stored_o = valid_Q[1]; - end else begin - out_valid_stored_o = valid_Q[0]; - end - end - - - //---------------------------------------------------------------------------- - // input port - //---------------------------------------------------------------------------- - - // 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_ready_o = ~valid_Q[DEPTH-2]; - - - //---------------------------------------------------------------------------- - // FIFO management - //---------------------------------------------------------------------------- - - int j; - 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 - 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][63:2], 2'b00} + 64'h4; + assign out_addr_o = (valid_Q[0]) ? addr_Q[0] : in_addr_i; - // move everything by one step - always_comb - begin - addr_n = addr_int; - rdata_n = rdata_int; - valid_n = valid_int; + //---------------------------------------------------------------------------- + // input port + //---------------------------------------------------------------------------- + // 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_ready_o = ~valid_Q[DEPTH-2]; - 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[63:2], 2'b00}; - end else begin - addr_n[0] = {addr_next[63:2], 2'b10}; - end + //---------------------------------------------------------------------------- + // FIFO management + //---------------------------------------------------------------------------- + always_comb begin + addr_int = addr_Q; + rdata_int = rdata_Q; + valid_int = valid_Q; - for (int i = 0; i < DEPTH - 1; i++) - begin - rdata_n[i] = rdata_int[i + 1]; - end - rdata_n[DEPTH - 1] = 32'b0; + if (in_valid_i) 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 - valid_n = {valid_int[1:DEPTH-1], 1'b0}; + assign addr_next = {addr_int[0][63:2], 2'b00} + 64'h4; + + // move everything by one step + always_comb begin + addr_n = addr_int; + rdata_n = rdata_int; + valid_n = valid_int; + + if (out_ready_i && out_valid_o) begin + if (addr_int[0][1]) begin + // unaligned case + if (unaligned_is_compressed) begin + addr_n[0] = {addr_next[63:2], 2'b00}; + end else begin + addr_n[0] = {addr_next[63:2], 2'b10}; + end + + // shift everything on ene step + for (int i = 0; i < DEPTH - 1; i++) + rdata_n[i] = rdata_int[i + 1]; + + rdata_n[DEPTH - 1] = 32'b0; + + valid_n = {valid_int[1:DEPTH-1], 1'b0}; + 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][63:2], 2'b10}; + end else begin + // move to next entry in FIFO + addr_n[0] = {addr_next[63:2], 2'b00}; + // shift entry + for (int i = 0; i < DEPTH - 1; i++) + rdata_n[i] = rdata_int[i + 1]; + + rdata_n[DEPTH - 1] = 32'b0; + valid_n = {valid_int[1:DEPTH-1], 1'b0}; + end + end + end + // on a clear signal from outside we invalidate the content of the FIFO + // completely and start from an empty state + if (clear_i) + valid_n = '0; + end + + //---------------------------------------------------------------------------- + // registers + //---------------------------------------------------------------------------- + + always_ff @(posedge clk, negedge rst_n) begin + if(rst_n == 1'b0) begin + addr_Q <= '{default: '0}; + rdata_Q <= '{default: '0}; + valid_Q <= '0; 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][63:2], 2'b10}; - end else begin - // move to next entry in FIFO - addr_n[0] = {addr_next[63:2], 2'b00}; - for (int i = 0; i < DEPTH - 1; i++) begin - rdata_n[i] = rdata_int[i + 1]; - end - rdata_n[DEPTH - 1] = 32'b0; - valid_n = {valid_int[1:DEPTH-1], 1'b0}; + addr_Q <= addr_n; + rdata_Q <= rdata_n; + valid_Q <= valid_n; end end - end end - end - //---------------------------------------------------------------------------- - // registers - //---------------------------------------------------------------------------- - - always_ff @(posedge clk, negedge rst_n) - begin - if(rst_n == 1'b0) - begin - addr_Q <= '{default: '0}; - rdata_Q <= '{default: '0}; - 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 - valid_Q <= '0; - end else begin - addr_Q <= addr_n; - rdata_Q <= rdata_n; - valid_Q <= valid_n; - end - end - end - - //---------------------------------------------------------------------------- - // Assertions - //---------------------------------------------------------------------------- - `ifndef SYNTHESIS - `ifndef VERILATOR - assert property ( - @(posedge clk) (in_valid_i) |-> ((valid_Q[DEPTH-1] == 1'b0) || (clear_i == 1'b1)) ); - `endif - `endif + //---------------------------------------------------------------------------- + // Assertions + //---------------------------------------------------------------------------- + `ifndef SYNTHESIS + `ifndef VERILATOR + assert property ( + @(posedge clk) (in_valid_i) |-> ((valid_Q[DEPTH-1] == 1'b0) || (clear_i == 1'b1)) ); + `endif + `endif endmodule \ No newline at end of file diff --git a/src/prefetch_buffer.sv b/src/prefetch_buffer.sv index fc47edbe4..5dd07ead8 100644 --- a/src/prefetch_buffer.sv +++ b/src/prefetch_buffer.sv @@ -58,9 +58,6 @@ module prefetch_buffer logic fifo_ready; logic fifo_clear; - logic valid_stored; - - //--------------------------------- // Prefetch buffer status //--------------------------------- @@ -71,26 +68,23 @@ module prefetch_buffer // Fetch FIFO // consumes addresses and rdata //--------------------------------- - fetch_fifo fifo_i - ( - .clk ( clk ), - .rst_n ( rst_n ), + 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_stored_o ( valid_stored ) - ); + .out_valid_o ( valid_o ), + .out_ready_i ( ready_i ), + .out_rdata_o ( rdata_o ), + .out_addr_o ( addr_o ) + ); //--------------- diff --git a/test/add_test.S b/test/add_test.S index 49a2173ab..1e26140ab 100755 --- a/test/add_test.S +++ b/test/add_test.S @@ -1,6 +1,4 @@ .text - nop - nop nop addi x1, x0, 1 addi x2, x0, 1