Rework async FIFO resets and synchronization

This commit is contained in:
Alex Forencich 2015-05-08 01:41:35 -07:00
parent 14f2d5e9f7
commit 51e65f5a22
4 changed files with 216 additions and 88 deletions

View File

@ -65,10 +65,13 @@ reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg input_rst_sync1 = 1;
reg input_rst_sync2 = 1;
reg output_rst_sync1 = 1;
reg output_rst_sync2 = 1;
reg [DATA_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {DATA_WIDTH{1'b0}}};
@ -83,11 +86,11 @@ wire [DATA_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser, input_axi
// full when first TWO MSBs do NOT match, but rest matches
// (gray code equivalent of first MSB different but rest same)
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync3[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync3[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync3[ADDR_WIDTH-2:0]));
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
// empty when pointers match exactly
wire empty = rd_ptr_gray == wr_ptr_gray_sync3;
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
wire write = input_axis_tvalid & ~full;
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
@ -97,9 +100,30 @@ assign {output_axis_tlast, output_axis_tuser, output_axis_tdata} = data_out_reg;
assign input_axis_tready = ~full;
assign output_axis_tvalid = output_axis_tvalid_reg;
// reset synchronization
always @(posedge input_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
input_rst_sync1 <= 1;
input_rst_sync2 <= 1;
end else begin
input_rst_sync1 <= 0;
input_rst_sync2 <= input_rst_sync1;
end
end
always @(posedge output_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
output_rst_sync1 <= 1;
output_rst_sync2 <= 1;
end else begin
output_rst_sync1 <= 0;
output_rst_sync2 <= output_rst_sync1;
end
end
// write
always @(posedge input_clk or posedge input_rst) begin
if (input_rst) begin
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
wr_ptr <= 0;
end else if (write) begin
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
@ -109,16 +133,20 @@ always @(posedge input_clk or posedge input_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge input_clk) begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
rd_ptr_gray_sync3 <= rd_ptr_gray_sync2;
// pointer synchronization
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
rd_ptr_gray_sync1 <= 0;
rd_ptr_gray_sync2 <= 0;
end else begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
end
end
// read
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
rd_ptr <= 0;
end else if (read) begin
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
@ -128,16 +156,20 @@ always @(posedge output_clk or posedge output_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge output_clk) begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
wr_ptr_gray_sync3 <= wr_ptr_gray_sync2;
// pointer synchronization
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
wr_ptr_gray_sync1 <= 0;
wr_ptr_gray_sync2 <= 0;
end else begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
end
end
// source ready output
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
output_axis_tvalid_reg <= 1'b0;
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
output_axis_tvalid_reg <= ~empty;

View File

@ -68,10 +68,13 @@ reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg input_rst_sync1 = 1;
reg input_rst_sync2 = 1;
reg output_rst_sync1 = 1;
reg output_rst_sync2 = 1;
reg [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_out_reg = {1'b0, 1'b0, {KEEP_WIDTH{1'b0}}, {DATA_WIDTH{1'b0}}};
@ -86,11 +89,11 @@ wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tuser
// full when first TWO MSBs do NOT match, but rest matches
// (gray code equivalent of first MSB different but rest same)
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync3[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync3[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync3[ADDR_WIDTH-2:0]));
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
// empty when pointers match exactly
wire empty = rd_ptr_gray == wr_ptr_gray_sync3;
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
wire write = input_axis_tvalid & ~full;
wire read = (output_axis_tready | ~output_axis_tvalid_reg) & ~empty;
@ -100,9 +103,30 @@ assign {output_axis_tlast, output_axis_tuser, output_axis_tkeep, output_axis_tda
assign input_axis_tready = ~full;
assign output_axis_tvalid = output_axis_tvalid_reg;
// reset synchronization
always @(posedge input_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
input_rst_sync1 <= 1;
input_rst_sync2 <= 1;
end else begin
input_rst_sync1 <= 0;
input_rst_sync2 <= input_rst_sync1;
end
end
always @(posedge output_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
output_rst_sync1 <= 1;
output_rst_sync2 <= 1;
end else begin
output_rst_sync1 <= 0;
output_rst_sync2 <= output_rst_sync1;
end
end
// write
always @(posedge input_clk or posedge input_rst) begin
if (input_rst) begin
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
wr_ptr <= 0;
end else if (write) begin
mem[wr_ptr[ADDR_WIDTH-1:0]] <= data_in;
@ -112,16 +136,20 @@ always @(posedge input_clk or posedge input_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge input_clk) begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
rd_ptr_gray_sync3 <= rd_ptr_gray_sync2;
// pointer synchronization
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
rd_ptr_gray_sync1 <= 0;
rd_ptr_gray_sync2 <= 0;
end else begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
end
end
// read
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
rd_ptr <= 0;
end else if (read) begin
data_out_reg <= mem[rd_ptr[ADDR_WIDTH-1:0]];
@ -131,16 +159,20 @@ always @(posedge output_clk or posedge output_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge output_clk) begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
wr_ptr_gray_sync3 <= wr_ptr_gray_sync2;
// pointer synchronization
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
wr_ptr_gray_sync1 <= 0;
wr_ptr_gray_sync2 <= 0;
end else begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
end
end
// source ready output
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
output_axis_tvalid_reg <= 1'b0;
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
output_axis_tvalid_reg <= ~empty;

View File

@ -66,10 +66,13 @@ reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg input_rst_sync1 = 1;
reg input_rst_sync2 = 1;
reg output_rst_sync1 = 1;
reg output_rst_sync2 = 1;
reg drop_frame = 1'b0;
@ -86,11 +89,11 @@ wire [DATA_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tdata};
// full when first TWO MSBs do NOT match, but rest matches
// (gray code equivalent of first MSB different but rest same)
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync3[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync3[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync3[ADDR_WIDTH-2:0]));
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
// empty when pointers match exactly
wire empty = rd_ptr_gray == wr_ptr_gray_sync3;
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
// overflow in single packet
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
@ -103,9 +106,30 @@ assign {output_axis_tlast, output_axis_tdata} = data_out_reg;
assign input_axis_tready = (~full | DROP_WHEN_FULL);
assign output_axis_tvalid = output_axis_tvalid_reg;
// reset synchronization
always @(posedge input_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
input_rst_sync1 <= 1;
input_rst_sync2 <= 1;
end else begin
input_rst_sync1 <= 0;
input_rst_sync2 <= input_rst_sync1;
end
end
always @(posedge output_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
output_rst_sync1 <= 1;
output_rst_sync2 <= 1;
end else begin
output_rst_sync1 <= 0;
output_rst_sync2 <= output_rst_sync1;
end
end
// write
always @(posedge input_clk or posedge input_rst) begin
if (input_rst) begin
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
wr_ptr <= 0;
wr_ptr_cur <= 0;
wr_ptr_gray <= 0;
@ -136,16 +160,20 @@ always @(posedge input_clk or posedge input_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge input_clk) begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
rd_ptr_gray_sync3 <= rd_ptr_gray_sync2;
// pointer synchronization
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
rd_ptr_gray_sync1 <= 0;
rd_ptr_gray_sync2 <= 0;
end else begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
end
end
// read
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
rd_ptr <= 0;
rd_ptr_gray <= 0;
end else if (read) begin
@ -156,16 +184,20 @@ always @(posedge output_clk or posedge output_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge output_clk) begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
wr_ptr_gray_sync3 <= wr_ptr_gray_sync2;
// pointer synchronization
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
wr_ptr_gray_sync1 <= 0;
wr_ptr_gray_sync2 <= 0;
end else begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
end
end
// source ready output
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
output_axis_tvalid_reg <= 1'b0;
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
output_axis_tvalid_reg <= ~empty;

View File

@ -69,10 +69,13 @@ reg [ADDR_WIDTH:0] rd_ptr_gray = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] wr_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync1 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync2 = {ADDR_WIDTH+1{1'b0}};
reg [ADDR_WIDTH:0] rd_ptr_gray_sync3 = {ADDR_WIDTH+1{1'b0}};
reg input_rst_sync1 = 1;
reg input_rst_sync2 = 1;
reg output_rst_sync1 = 1;
reg output_rst_sync2 = 1;
reg drop_frame = 1'b0;
@ -89,11 +92,11 @@ wire [DATA_WIDTH+KEEP_WIDTH+2-1:0] data_in = {input_axis_tlast, input_axis_tkeep
// full when first TWO MSBs do NOT match, but rest matches
// (gray code equivalent of first MSB different but rest same)
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync3[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync3[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync3[ADDR_WIDTH-2:0]));
wire full = ((wr_ptr_gray[ADDR_WIDTH] != rd_ptr_gray_sync2[ADDR_WIDTH]) &&
(wr_ptr_gray[ADDR_WIDTH-1] != rd_ptr_gray_sync2[ADDR_WIDTH-1]) &&
(wr_ptr_gray[ADDR_WIDTH-2:0] == rd_ptr_gray_sync2[ADDR_WIDTH-2:0]));
// empty when pointers match exactly
wire empty = rd_ptr_gray == wr_ptr_gray_sync3;
wire empty = rd_ptr_gray == wr_ptr_gray_sync2;
// overflow in single packet
wire full_cur = ((wr_ptr[ADDR_WIDTH] != wr_ptr_cur[ADDR_WIDTH]) &&
(wr_ptr[ADDR_WIDTH-1:0] == wr_ptr_cur[ADDR_WIDTH-1:0]));
@ -106,9 +109,30 @@ assign {output_axis_tlast, output_axis_tkeep, output_axis_tdata} = data_out_reg;
assign input_axis_tready = (~full | DROP_WHEN_FULL);
assign output_axis_tvalid = output_axis_tvalid_reg;
// reset synchronization
always @(posedge input_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
input_rst_sync1 <= 1;
input_rst_sync2 <= 1;
end else begin
input_rst_sync1 <= 0;
input_rst_sync2 <= input_rst_sync1;
end
end
always @(posedge output_clk or posedge input_rst or posedge output_rst) begin
if (input_rst | output_rst) begin
output_rst_sync1 <= 1;
output_rst_sync2 <= 1;
end else begin
output_rst_sync1 <= 0;
output_rst_sync2 <= output_rst_sync1;
end
end
// write
always @(posedge input_clk or posedge input_rst) begin
if (input_rst) begin
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
wr_ptr <= 0;
wr_ptr_cur <= 0;
wr_ptr_gray <= 0;
@ -139,16 +163,20 @@ always @(posedge input_clk or posedge input_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge input_clk) begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
rd_ptr_gray_sync3 <= rd_ptr_gray_sync2;
// pointer synchronization
always @(posedge input_clk or posedge input_rst_sync2) begin
if (input_rst_sync2) begin
rd_ptr_gray_sync1 <= 0;
rd_ptr_gray_sync2 <= 0;
end else begin
rd_ptr_gray_sync1 <= rd_ptr_gray;
rd_ptr_gray_sync2 <= rd_ptr_gray_sync1;
end
end
// read
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
rd_ptr <= 0;
rd_ptr_gray <= 0;
end else if (read) begin
@ -159,16 +187,20 @@ always @(posedge output_clk or posedge output_rst) begin
end
end
// pointer synchronization in SRL16
always @(posedge output_clk) begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
wr_ptr_gray_sync3 <= wr_ptr_gray_sync2;
// pointer synchronization
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
wr_ptr_gray_sync1 <= 0;
wr_ptr_gray_sync2 <= 0;
end else begin
wr_ptr_gray_sync1 <= wr_ptr_gray;
wr_ptr_gray_sync2 <= wr_ptr_gray_sync1;
end
end
// source ready output
always @(posedge output_clk or posedge output_rst) begin
if (output_rst) begin
always @(posedge output_clk or posedge output_rst_sync2) begin
if (output_rst_sync2) begin
output_axis_tvalid_reg <= 1'b0;
end else if (output_axis_tready | ~output_axis_tvalid_reg) begin
output_axis_tvalid_reg <= ~empty;