blob: 48c2758b234d590bde0b37632b6a64a142a4c1bc [file] [log] [blame]
// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
module dc_token_ring_fifo_dout(clk, rstn, data_async, write_token, read_pointer, data, valid, ready);
parameter DATA_WIDTH = 10;
parameter BUFFER_DEPTH = 8;
input [DATA_WIDTH - 1 : 0] data_async;
input clk;
input rstn;
output [DATA_WIDTH - 1 : 0] data;
output valid;
input ready;
input [BUFFER_DEPTH - 1 : 0] write_token;
output [BUFFER_DEPTH - 1 : 0] read_pointer;
wire read_enable;
wire stall;
// Pointers to the write, read addresses (two-hot encoding)
wire [BUFFER_DEPTH - 1 : 0] read_token;
wire [BUFFER_DEPTH - 1 : 0] write_token_dn;
wire [BUFFER_DEPTH - 1 : 0] empty;
assign data = data_async;
assign stall = ~ready;
// FIFO read/write enable
assign read_enable = (valid & ~stall);
// Logic to compute the read, write pointers
dc_token_ring
#(
.BUFFER_DEPTH ( BUFFER_DEPTH ),
.RESET_VALUE ( 'h3 )
)
read_tr
(
.clk ( clk ),
.rstn ( rstn ),
.enable ( read_enable ),
.state ( read_token )
);
// Pointers to the write, read addresses (semi-accurate, leveraging the two-hot encoding for extra robustness)
assign read_pointer = {read_token[BUFFER_DEPTH - 3 : 0], read_token[BUFFER_DEPTH - 1 : BUFFER_DEPTH - 2]} &
{read_token[BUFFER_DEPTH - 4 : 0], read_token[BUFFER_DEPTH - 1 : BUFFER_DEPTH - 3]};
// Empty detector; if any of the bits is 1, the synchronizer is empty
dc_synchronizer
#(
.WIDTH ( BUFFER_DEPTH ),
.RESET_VALUE ( 'hc )
)
empty_synch
(
.clk ( clk ),
.rstn ( rstn ),
.d_in ( write_token ),
.d_out ( write_token_dn )
);
assign empty = ~write_token_dn & {write_token_dn[0], write_token_dn[BUFFER_DEPTH - 1 : 1]} & {read_pointer[1 : 0], read_pointer[BUFFER_DEPTH - 1 : 2]};
assign valid = ~(|empty);
endmodule