Skip to content

Commit

Permalink
hw: Trying something out with input FIFO
Browse files Browse the repository at this point in the history
  • Loading branch information
fischeti committed May 31, 2024
1 parent 5b06050 commit e5cc52b
Showing 1 changed file with 186 additions and 127 deletions.
313 changes: 186 additions & 127 deletions hw/vc_router_util/floo_input_fifo.sv
Original file line number Diff line number Diff line change
Expand Up @@ -9,141 +9,200 @@

// similar to spill_register, but writeable while full if ready_i
module floo_input_fifo #(
parameter int Depth = 2,
parameter type type_t = logic
parameter int unsigned Depth = 32'd2,
parameter type type_t = logic,
localparam AddrDepth = cf_math_pkg::idx_width(Depth)

Check warning on line 14 in hw/vc_router_util/floo_input_fifo.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] hw/vc_router_util/floo_input_fifo.sv#L14

Explicitly define a storage type for every parameter and localparam, (AddrDepth). [Style: constants] [explicit-parameter-storage-type]
Raw output
message:"Explicitly define a storage type for every parameter and localparam, (AddrDepth). [Style: constants] [explicit-parameter-storage-type]" location:{path:"./hw/vc_router_util/floo_input_fifo.sv" range:{start:{line:14 column:14}}} severity:WARNING source:{name:"verible-verilog-lint" url:"https://github.com/chipsalliance/verible"}
) (
input logic clk_i ,
input logic rst_ni ,
input logic valid_i ,
input type_t data_i ,
output logic valid_o ,
input logic ready_i ,
output type_t data_o
input logic clk_i,
input logic rst_ni,
input logic valid_i,
input type_t data_i,
output logic valid_o,
input logic ready_i,
output type_t data_o
);
if(Depth == 1) begin : gen_reg
logic ready_for_input;
type_t data_q;
logic full_q;
logic fill, drain;
`FFL(data_q, data_i, fill, '0)
`FFL(full_q, fill, fill || drain, '0)

assign fill = valid_i & ready_for_input;
assign drain = full_q & ready_i;

assign ready_for_input = ~full_q | ready_i;
assign valid_o = full_q;
assign data_o = data_q;

`ASSERT(RegFullWrite, ready_for_input | !valid_i)
end else if(Depth == 2) begin : gen_fifo_2
logic ready_for_input;
// The A register.
type_t a_data_q;
logic a_full_q;
logic a_fill, a_drain;
`FFL(a_data_q, data_i, a_fill, '0)
`FFL(a_full_q, a_fill, a_fill || a_drain, '0)

// The B register.
type_t b_data_q;
logic b_full_q;
logic b_fill, b_drain;
`FFL(b_data_q, a_data_q, b_fill, '0)
`FFL(b_full_q, b_fill, b_fill || b_drain, '0)


// Fill the A register when being filled. Drain the A register
// whenever data is popped or more space needed.
// If data is written to B or not (not -> data is output) is decided there
assign a_fill = valid_i & ready_for_input;
assign a_drain = (ready_i & ~b_full_q) | a_fill;

// Fill the B register when A is filled but already full.
// B full but A empty is impossible
assign b_fill = a_fill & (b_drain | (a_full_q & ~ready_i));
assign b_drain = b_full_q & ready_i;

// can accept input while full, if being read
assign ready_for_input = ~a_full_q | ~b_full_q | ready_i;

// The unit provides output as long as one of the registers is filled.
assign valid_o = a_full_q | b_full_q;

// Empty reg B before A
assign data_o = b_full_q ? b_data_q : a_data_q;

`ASSERT(RegFullWrite, ready_for_input | !valid_i)
end else if(Depth == 3) begin : gen_fifo_3
logic ready_for_input;
// The A register.
type_t a_data_q;
logic a_full_q;
logic a_fill, a_drain;
`FFL(a_data_q, data_i, a_fill, '0)
`FFL(a_full_q, a_fill, a_fill || a_drain, '0)

// The B register.
type_t b_data_q;
logic b_full_q;
logic b_fill, b_drain;
`FFL(b_data_q, a_data_q, b_fill, '0)
`FFL(b_full_q, b_fill, b_fill || b_drain, '0)

// The C register.
type_t c_data_q;
logic c_full_q;
logic c_fill, c_drain;
`FFL(c_data_q, b_data_q, c_fill, '0)
`FFL(c_full_q, c_fill, c_fill || c_drain, '0)


// Fill the A register when being filled. Drain the A register
// whenever data is popped or more space needed.
// If data is written to B or not (not -> data is output) is decided there
assign a_fill = valid_i & ready_for_input;
// Drain A if need data from A or if filling B
assign a_drain = (ready_i & ~b_full_q) | a_fill;

// Fill the B register when A is filled but already full.
// B full but A empty is impossible
assign b_fill = a_fill & (b_full_q | (a_full_q & ~ready_i));
// Drain B if need data from B or if filling B
assign b_drain = (b_full_q & ready_i & ~c_full_q) | b_fill;

// Fill the C register when B is filled but already full.
// C full but B empty is impossible
assign c_fill = b_fill & (c_drain | (b_full_q & ~ready_i));
assign c_drain = c_full_q & ready_i;

assign ready_for_input = ~a_full_q | ~b_full_q | ~c_full_q | ready_i;
assign valid_o = a_full_q | b_full_q | c_full_q;
assign data_o = c_full_q ? c_data_q : b_full_q ? b_data_q : a_data_q;

`ASSERT(CFullBEmpty, !c_full_q | b_full_q)
`ASSERT(CFullAEmpty, !c_full_q | a_full_q)
`ASSERT(BFullAEmpty, !b_full_q | a_full_q)
`ASSERT(RegFullWrite, ready_for_input | !valid_i)
end else begin : gen_fifo_general
logic reg_ready;
$warning("if depth != 2, write and read is not possible at same time while full");
stream_fifo_optimal_wrap #(
.Depth (Depth),
.type_t (type_t)
) i_fifo (
logic ready_out;
stream_register #(
.T(type_t)
) i_stream_register (
.clk_i,
.rst_ni,
.testmode_i ('0),
.flush_i ('0),
.usage_o (),
.data_i,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i,
.ready_o (reg_ready),
.data_o,
.ready_o ( ready_out ),
.data_i,
.valid_o,
.ready_i
.ready_i,
.data_o
);
`ASSERT(RegFullWrite, ready_out | !valid_i)
end else if (Depth > 1) begin

Check warning on line 41 in hw/vc_router_util/floo_input_fifo.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] hw/vc_router_util/floo_input_fifo.sv#L41

All generate block statements must have a label [Style: generate-statements] [generate-label]
Raw output
message:"All generate block statements must have a label [Style: generate-statements] [generate-label]" location:{path:"./hw/vc_router_util/floo_input_fifo.sv" range:{start:{line:41 column:27}}} severity:WARNING source:{name:"verible-verilog-lint" url:"https://github.com/chipsalliance/verible"}

logic [Depth-1:0] ready_out, valid_in, valid_out, ready_in;
logic [AddrDepth-1:0] read_pnt_q, write_pnt_q, read_pnt_d, write_pnt_d;

stream_register #(
.T(type_t)
) i_stream_register [Depth-1:0] (
.clk_i,
.rst_ni,
.clr_i ( 1'b0 ),
.testmode_i ( 1'b0 ),
.valid_i ( valid_in ),
.ready_o ( ready_out ),
.data_i,
.valid_o ( valid_out ),
.ready_i ( ready_in ),
.data_o ( data_out )
);
`ASSERT(RegNotReadyWrite, reg_ready | !valid_i)

always_comb begin
read_pnt_d = read_pnt_q;
write_pnt_d = write_pnt_q;
valid_in = '0;
ready_in = '0;

if (valid_i) begin
if (write_pnt_q == Depth[AddrDepth-1]-1) begin
write_pnt_d = 0;
end else begin
write_pnt_d = write_pnt_q + 1;
end
end

if (valid_out[read_pnt_q] && ready_i) begin
if (read_pnt_q == Depth[AddrDepth-1]-1) begin
read_pnt_d = 0;
end else begin
read_pnt_d = read_pnt_q + 1;
end
end

if (valid_i && ~valid_out[write_pnt_q]) begin
valid_in[write_pnt_q] = 1'b1;
end

if (valid_out[read_pnt_q] && ready_i) begin
ready_in[read_pnt_q] = 1'b1;
end
end

`FF(read_pnt_q, read_pnt_d, '0)
`FF(write_pnt_q, write_pnt_d, '0)

`ASSERT(RegFullWrite, &(ready_out | !valid_i))
end

// end else if(Depth == 2) begin : gen_fifo_2
// logic ready_for_input;
// // The A register.
// type_t a_data_q;
// logic a_full_q;
// logic a_fill, a_drain;
// `FFL(a_data_q, data_i, a_fill, '0)
// `FFL(a_full_q, a_fill, a_fill || a_drain, '0)

// // The B register.
// type_t b_data_q;
// logic b_full_q;
// logic b_fill, b_drain;
// `FFL(b_data_q, a_data_q, b_fill, '0)
// `FFL(b_full_q, b_fill, b_fill || b_drain, '0)


// // Fill the A register when being filled. Drain the A register
// // whenever data is popped or more space needed.
// // If data is written to B or not (not -> data is output) is decided there
// assign a_fill = valid_i & ready_for_input;
// assign a_drain = (ready_i & ~b_full_q) | a_fill;

// // Fill the B register when A is filled but already full.
// // B full but A empty is impossible
// assign b_fill = a_fill & (b_drain | (a_full_q & ~ready_i));
// assign b_drain = b_full_q & ready_i;

// // can accept input while full, if being read
// assign ready_for_input = ~a_full_q | ~b_full_q | ready_i;

// // The unit provides output as long as one of the registers is filled.
// assign valid_o = a_full_q | b_full_q;

// // Empty reg B before A
// assign data_o = b_full_q ? b_data_q : a_data_q;

// `ASSERT(RegFullWrite, ready_for_input | !valid_i)
// end else if(Depth == 3) begin : gen_fifo_3
// logic ready_for_input;
// // The A register.
// type_t a_data_q;
// logic a_full_q;
// logic a_fill, a_drain;
// `FFL(a_data_q, data_i, a_fill, '0)
// `FFL(a_full_q, a_fill, a_fill || a_drain, '0)

// // The B register.
// type_t b_data_q;
// logic b_full_q;
// logic b_fill, b_drain;
// `FFL(b_data_q, a_data_q, b_fill, '0)
// `FFL(b_full_q, b_fill, b_fill || b_drain, '0)

// // The C register.
// type_t c_data_q;
// logic c_full_q;
// logic c_fill, c_drain;
// `FFL(c_data_q, b_data_q, c_fill, '0)
// `FFL(c_full_q, c_fill, c_fill || c_drain, '0)


// // Fill the A register when being filled. Drain the A register
// // whenever data is popped or more space needed.
// // If data is written to B or not (not -> data is output) is decided there
// assign a_fill = valid_i & ready_for_input;
// // Drain A if need data from A or if filling B
// assign a_drain = (ready_i & ~b_full_q) | a_fill;

// // Fill the B register when A is filled but already full.
// // B full but A empty is impossible
// assign b_fill = a_fill & (b_full_q | (a_full_q & ~ready_i));
// // Drain B if need data from B or if filling B
// assign b_drain = (b_full_q & ready_i & ~c_full_q) | b_fill;

// // Fill the C register when B is filled but already full.
// // C full but B empty is impossible
// assign c_fill = b_fill & (c_drain | (b_full_q & ~ready_i));
// assign c_drain = c_full_q & ready_i;

// assign ready_for_input = ~a_full_q | ~b_full_q | ~c_full_q | ready_i;
// assign valid_o = a_full_q | b_full_q | c_full_q;
// assign data_o = c_full_q ? c_data_q : b_full_q ? b_data_q : a_data_q;

// `ASSERT(CFullBEmpty, !c_full_q | b_full_q)
// `ASSERT(CFullAEmpty, !c_full_q | a_full_q)
// `ASSERT(BFullAEmpty, !b_full_q | a_full_q)
// `ASSERT(RegFullWrite, ready_for_input | !valid_i)
// end else begin : gen_fifo_general
// logic reg_ready;
// $warning("if depth != 2, write and read is not possible at same time while full");
// stream_fifo_optimal_wrap #(
// .Depth (Depth),
// .type_t (type_t)
// ) i_fifo (
// .clk_i,
// .rst_ni,
// .testmode_i ('0),
// .flush_i ('0),
// .usage_o (),
// .data_i,
// .valid_i,
// .ready_o (reg_ready),
// .data_o,
// .valid_o,
// .ready_i
// );
// `ASSERT(RegNotReadyWrite, reg_ready | !valid_i)
// end

endmodule

0 comments on commit e5cc52b

Please sign in to comment.