mirror of
https://github.com/alexforencich/verilog-ethernet.git
synced 2025-01-28 07:03:08 +08:00
Add FIFO output pipeline registers to aid block RAM output timing closure
This commit is contained in:
parent
b44e401b95
commit
a961a9756a
@ -82,8 +82,11 @@ reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+2-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] output_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
@ -97,13 +100,14 @@ wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3_reg;
|
||||
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = output_data_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
@ -192,18 +196,19 @@ always @* begin
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -212,11 +217,11 @@ always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -226,4 +231,28 @@ always @(posedge output_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -84,9 +84,12 @@ reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+KEEP_WIDTH+2{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] output_data_reg = {DATA_WIDTH+KEEP_WIDTH+2{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
@ -100,13 +103,14 @@ wire empty = rd_ptr_gray_reg == wr_ptr_gray_sync2_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
assign input_axis_tready = ~full & ~input_rst_sync3_reg;
|
||||
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = output_data_reg;
|
||||
|
||||
// reset synchronization
|
||||
always @(posedge input_clk or posedge async_rst) begin
|
||||
@ -195,18 +199,19 @@ always @* begin
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -215,11 +220,11 @@ always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -229,4 +234,28 @@ always @(posedge output_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -92,9 +92,12 @@ reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+1{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+1-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+1-1:0] output_data_reg = {DATA_WIDTH+1{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
@ -111,6 +114,7 @@ wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
@ -135,7 +139,7 @@ assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tdata} = output_data_reg;
|
||||
|
||||
assign input_status_overflow = overflow_reg;
|
||||
assign input_status_bad_frame = bad_frame_reg;
|
||||
@ -308,18 +312,19 @@ always @* begin
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -328,11 +333,11 @@ always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -342,4 +347,28 @@ always @(posedge output_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -95,9 +95,12 @@ reg output_rst_sync2_reg = 1'b1;
|
||||
reg output_rst_sync3_reg = 1'b1;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+KEEP_WIDTH+1{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] output_data_reg = {DATA_WIDTH+KEEP_WIDTH+1{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first TWO MSBs do NOT match, but rest matches
|
||||
@ -114,6 +117,7 @@ wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
@ -138,7 +142,7 @@ assign input_axis_tready = (~full | DROP_WHEN_FULL) & ~input_rst_sync3_reg;
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = output_data_reg;
|
||||
|
||||
assign input_status_overflow = overflow_reg;
|
||||
assign input_status_bad_frame = bad_frame_reg;
|
||||
@ -311,18 +315,19 @@ always @* begin
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
rd_ptr_gray_next = rd_ptr_gray_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
rd_ptr_gray_next = rd_ptr_next ^ (rd_ptr_next >> 1);
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -331,11 +336,11 @@ always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
rd_ptr_gray_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
rd_ptr_gray_reg <= rd_ptr_gray_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -345,4 +350,28 @@ always @(posedge output_clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge output_clk) begin
|
||||
if (output_rst_sync3_reg) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -64,8 +64,11 @@ reg [ADDR_WIDTH:0] rd_addr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+2-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+2-1:0] output_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
@ -77,13 +80,14 @@ wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
assign input_axis_tready = ~full;
|
||||
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tuser, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = output_data_reg;
|
||||
|
||||
// Write logic
|
||||
always @* begin
|
||||
@ -121,17 +125,18 @@ always @* begin
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -139,10 +144,10 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -152,4 +157,28 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -66,9 +66,12 @@ reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_addr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_read_data_reg = {DATA_WIDTH+KEEP_WIDTH+2{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] output_data_reg = {DATA_WIDTH+KEEP_WIDTH+2{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
@ -80,15 +83,16 @@ wire empty = wr_ptr_reg == rd_ptr_reg;
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
assign input_axis_tready = ~full;
|
||||
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tuser, input_axis_tkeep, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tdata} = output_data_reg;
|
||||
|
||||
// FIFO write logic
|
||||
// Write logic
|
||||
always @* begin
|
||||
write = 1'b0;
|
||||
|
||||
@ -118,24 +122,24 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// FIFO read logic
|
||||
// Read logic
|
||||
always @* begin
|
||||
read = 1'b0;
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
// empty, invalidate
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -143,10 +147,10 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -156,4 +160,28 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -71,9 +71,12 @@ reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_addr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg [DATA_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+1{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+1-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+1-1:0] output_data_reg = {DATA_WIDTH+1{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
@ -88,6 +91,7 @@ wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
@ -99,7 +103,7 @@ assign input_axis_tready = (~full | DROP_WHEN_FULL);
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tdata} = output_data_reg;
|
||||
|
||||
assign overflow = overflow_reg;
|
||||
assign bad_frame = bad_frame_reg;
|
||||
@ -183,18 +187,18 @@ always @* begin
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
// empty, invalidate
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -202,10 +206,10 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -215,4 +219,28 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -74,9 +74,12 @@ reg [ADDR_WIDTH:0] rd_ptr_reg = {ADDR_WIDTH+1{1'b0}}, rd_ptr_next;
|
||||
reg [ADDR_WIDTH:0] rd_addr_reg = {ADDR_WIDTH+1{1'b0}};
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem[(2**ADDR_WIDTH)-1:0];
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+2{1'b0}};
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_read_data_reg = {DATA_WIDTH+KEEP_WIDTH+1{1'b0}};
|
||||
reg mem_read_data_valid_reg = 1'b0, mem_read_data_valid_next;
|
||||
wire [DATA_WIDTH+KEEP_WIDTH+1-1:0] mem_write_data;
|
||||
|
||||
reg [DATA_WIDTH+KEEP_WIDTH+1-1:0] output_data_reg = {DATA_WIDTH+KEEP_WIDTH+1{1'b0}};
|
||||
|
||||
reg output_axis_tvalid_reg = 1'b0, output_axis_tvalid_next;
|
||||
|
||||
// full when first MSB different but rest same
|
||||
@ -91,6 +94,7 @@ wire full_cur = ((wr_ptr_reg[ADDR_WIDTH] != wr_ptr_cur_reg[ADDR_WIDTH]) &&
|
||||
// control signals
|
||||
reg write;
|
||||
reg read;
|
||||
reg store_output;
|
||||
|
||||
reg drop_frame_reg = 1'b0, drop_frame_next;
|
||||
reg overflow_reg = 1'b0, overflow_next;
|
||||
@ -102,7 +106,7 @@ assign input_axis_tready = (~full | DROP_WHEN_FULL);
|
||||
assign output_axis_tvalid = output_axis_tvalid_reg;
|
||||
|
||||
assign mem_write_data = {input_axis_tlast, input_axis_tkeep, input_axis_tdata};
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = mem_read_data_reg;
|
||||
assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = output_data_reg;
|
||||
|
||||
assign overflow = overflow_reg;
|
||||
assign bad_frame = bad_frame_reg;
|
||||
@ -186,17 +190,18 @@ always @* begin
|
||||
|
||||
rd_ptr_next = rd_ptr_reg;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
mem_read_data_valid_next = mem_read_data_valid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
// output data not valid OR currently being transferred
|
||||
if (~empty) begin
|
||||
// not empty, perform read
|
||||
read = 1'b1;
|
||||
output_axis_tvalid_next = 1'b1;
|
||||
mem_read_data_valid_next = 1'b1;
|
||||
rd_ptr_next = rd_ptr_reg + 1;
|
||||
end else begin
|
||||
output_axis_tvalid_next = 1'b0;
|
||||
// empty, invalidate
|
||||
mem_read_data_valid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -204,10 +209,10 @@ end
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
rd_ptr_reg <= {ADDR_WIDTH+1{1'b0}};
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
mem_read_data_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
rd_ptr_reg <= rd_ptr_next;
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
mem_read_data_valid_reg <= mem_read_data_valid_next;
|
||||
end
|
||||
|
||||
rd_addr_reg <= rd_ptr_next;
|
||||
@ -217,4 +222,28 @@ always @(posedge clk) begin
|
||||
end
|
||||
end
|
||||
|
||||
// Output register
|
||||
always @* begin
|
||||
store_output = 1'b0;
|
||||
|
||||
output_axis_tvalid_next = output_axis_tvalid_reg;
|
||||
|
||||
if (output_axis_tready | ~output_axis_tvalid) begin
|
||||
store_output = 1'b1;
|
||||
output_axis_tvalid_next = mem_read_data_valid_reg;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
output_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
output_axis_tvalid_reg <= output_axis_tvalid_next;
|
||||
end
|
||||
|
||||
if (store_output) begin
|
||||
output_data_reg <= mem_read_data_reg;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
Loading…
x
Reference in New Issue
Block a user