Width change fifo update

This commit is contained in:
bsdevlin 2019-04-05 17:48:18 -04:00
parent 12fd25958b
commit ee34650b44
1 changed files with 71 additions and 22 deletions

View File

@ -2,9 +2,9 @@
Changes the width between two streams (must be powers of 2). Changes the width between two streams (must be powers of 2).
Goes through a clock crossing FIFO so can run on different Goes through a clock crossing FIFO so can run on different
clock domains. clock domains.
Input and output widths need to be a multiple of each other Input and output widths need to be a multiple of each other
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -19,7 +19,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
module width_change_cdc_fifo # ( module width_change_cdc_fifo # (
parameter IN_DAT_BYTS, parameter IN_DAT_BYTS,
@ -29,12 +29,12 @@ module width_change_cdc_fifo # (
parameter USE_BRAM parameter USE_BRAM
) ( ) (
input i_clk_a, i_rst_a, input i_clk_a, i_rst_a,
input i_clk_b, i_rst_b, input i_clk_b, i_rst_b,
if_axi_stream.sink i_axi_a, if_axi_stream.sink i_axi_a,
if_axi_stream.source o_axi_b if_axi_stream.source o_axi_b
); );
localparam SHIFT_DOWN = IN_DAT_BYTS > OUT_DAT_BYTS; localparam SHIFT_DOWN = IN_DAT_BYTS > OUT_DAT_BYTS;
localparam SHIFT_RATIO = SHIFT_DOWN ? IN_DAT_BYTS/OUT_DAT_BYTS : OUT_DAT_BYTS/IN_DAT_BYTS; localparam SHIFT_RATIO = SHIFT_DOWN ? IN_DAT_BYTS/OUT_DAT_BYTS : OUT_DAT_BYTS/IN_DAT_BYTS;
localparam MAX_BYTS = SHIFT_DOWN ? IN_DAT_BYTS : OUT_DAT_BYTS; localparam MAX_BYTS = SHIFT_DOWN ? IN_DAT_BYTS : OUT_DAT_BYTS;
@ -52,10 +52,56 @@ if_axi_stream #(.DAT_BYTS(IN_DAT_BYTS), .CTL_BITS(CTL_BITS)) o_axi_int (i_clk_b)
logic [$clog2(MAX_BYTS)-1:0] byt_cnt; logic [$clog2(MAX_BYTS)-1:0] byt_cnt;
logic sop_l; logic sop_l;
generate if (SHIFT_DOWN) begin
always_ff @ (posedge i_clk_b) begin
if (i_rst_b) begin
o_axi_b.reset_source();
byt_cnt <= 0;
sop_l <= 0;
o_axi_int.rdy <= 0;
end else begin
o_axi_int.rdy <= 0;
if (~o_axi_b.val || (o_axi_b.val && o_axi_b.rdy)) begin
if (o_axi_int.val) begin
if (~sop_l) begin
o_axi_b.ctl <= o_axi_int.ctl;
o_axi_b.err <= o_axi_int.err;
sop_l <= 1;
end
o_axi_b.dat <= o_axi_int.dat[byt_cnt*8 +: OUT_DAT_BITS];
o_axi_b.sop <= ~sop_l;
o_axi_b.val <= 1;
byt_cnt <= byt_cnt + OUT_DAT_BYTS;
// Detect the last data
if ((byt_cnt + OUT_DAT_BYTS == IN_DAT_BYTS) || (o_axi_int.eop && o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod))) begin
byt_cnt <= 0;
o_axi_int.rdy <= 1;
if (o_axi_int.eop) begin
o_axi_b.eop <= 1;
o_axi_b.mod <= o_axi_int.mod == 0 ? 0 : (o_axi_int.mod % OUT_DAT_BYTS);
sop_l <= 0;
end
end
end
end
end
end
end else begin
// Logic to take words out of the CDC and form packets // Logic to take words out of the CDC and form packets
always_comb begin always_comb begin
if (SHIFT_DOWN) begin if (SHIFT_DOWN) begin
o_axi_int.rdy = (byt_cnt + OUT_DAT_BYTS == IN_DAT_BYTS) && o_axi_b.rdy || o_axi_int.rdy = (byt_cnt + OUT_DAT_BYTS == IN_DAT_BYTS) && o_axi_b.rdy ||
(o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod)); (o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod));
end else begin end else begin
o_axi_int.rdy = (~o_axi_b.val && (byt_cnt + IN_DAT_BYTS < OUT_DAT_BYTS)) || o_axi_int.rdy = (~o_axi_b.val && (byt_cnt + IN_DAT_BYTS < OUT_DAT_BYTS)) ||
@ -69,26 +115,26 @@ always_ff @ (posedge i_clk_b) begin
byt_cnt <= 0; byt_cnt <= 0;
sop_l <= 0; sop_l <= 0;
end else begin end else begin
if (~o_axi_b.val || (o_axi_b.val && o_axi_b.rdy)) begin if (~o_axi_b.val || (o_axi_b.val && o_axi_b.rdy)) begin
if (o_axi_b.val && o_axi_b.rdy) begin if (o_axi_b.val && o_axi_b.rdy) begin
o_axi_b.reset_source(); o_axi_b.reset_source();
end end
if (o_axi_int.val) begin if (o_axi_int.val) begin
if (byt_cnt == 0 && o_axi_int.sop) begin if (byt_cnt == 0 && o_axi_int.sop) begin
sop_l <= 1; sop_l <= 1;
if (SHIFT_DOWN) if (SHIFT_DOWN)
o_axi_b.sop <= 1; o_axi_b.sop <= 1;
end end
if (SHIFT_DOWN) if (SHIFT_DOWN)
o_axi_b.dat <= o_axi_int.dat[byt_cnt*8 +: OUT_DAT_BITS]; o_axi_b.dat <= o_axi_int.dat[byt_cnt*8 +: OUT_DAT_BITS];
else else
o_axi_b.dat[byt_cnt*8 +: IN_DAT_BITS] <= o_axi_int.dat; o_axi_b.dat[byt_cnt*8 +: IN_DAT_BITS] <= o_axi_int.dat;
if (SHIFT_DOWN) begin if (SHIFT_DOWN) begin
if (o_axi_int.val) if (o_axi_int.val)
byt_cnt <= byt_cnt + OUT_DAT_BYTS; byt_cnt <= byt_cnt + OUT_DAT_BYTS;
@ -96,39 +142,42 @@ always_ff @ (posedge i_clk_b) begin
if (o_axi_int.rdy && o_axi_int.val) if (o_axi_int.rdy && o_axi_int.val)
byt_cnt <= byt_cnt + IN_DAT_BYTS; byt_cnt <= byt_cnt + IN_DAT_BYTS;
end end
if ((byt_cnt + IN_DAT_BYTS) % OUT_DAT_BYTS == 0 || if ((byt_cnt + IN_DAT_BYTS) % OUT_DAT_BYTS == 0 ||
o_axi_int.eop || o_axi_int.eop ||
SHIFT_DOWN ) begin SHIFT_DOWN ) begin
o_axi_b.val <= 1; o_axi_b.val <= 1;
if (~SHIFT_DOWN) if (~SHIFT_DOWN)
o_axi_b.sop <= sop_l || o_axi_int.sop; o_axi_b.sop <= sop_l || o_axi_int.sop;
sop_l <= 0; sop_l <= 0;
if (SHIFT_DOWN) begin if (SHIFT_DOWN) begin
if((byt_cnt + OUT_DAT_BYTS) % IN_DAT_BYTS == 0 || if((byt_cnt + OUT_DAT_BYTS) % IN_DAT_BYTS == 0 ||
(o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod))) begin (o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod))) begin
o_axi_b.eop <= o_axi_int.eop; o_axi_b.eop <= o_axi_int.eop;
byt_cnt <= 0; byt_cnt <= 0;
end end
end else begin end else begin
o_axi_b.eop <= o_axi_int.eop; o_axi_b.eop <= o_axi_int.eop;
byt_cnt <= 0; byt_cnt <= 0;
end end
o_axi_b.mod <= o_axi_int.mod == 0 ? 0 : (byt_cnt + o_axi_int.mod); o_axi_b.mod <= o_axi_int.mod == 0 ? 0 : (byt_cnt + o_axi_int.mod);
end end
end end
end end
end end
end end
end
endgenerate
cdc_fifo #( cdc_fifo #(
.SIZE ( 1<<FIFO_ABITS ), .SIZE ( 1<<FIFO_ABITS ),
.DAT_BITS ( IN_DAT_BYTS*8 + IN_MOD_BITS + CTL_BITS + 3 ), .DAT_BITS ( IN_DAT_BYTS*8 + IN_MOD_BITS + CTL_BITS + 3 ),
.USE_BRAM ( USE_BRAM ) .USE_BRAM ( USE_BRAM )
) )