diff --git a/ip_cores/fifo/src/rtl/width_change_cdc_fifo.sv b/ip_cores/fifo/src/rtl/width_change_cdc_fifo.sv index 672040d..7a2fb45 100644 --- a/ip_cores/fifo/src/rtl/width_change_cdc_fifo.sv +++ b/ip_cores/fifo/src/rtl/width_change_cdc_fifo.sv @@ -2,9 +2,9 @@ Changes the width between two streams (must be powers of 2). Goes through a clock crossing FIFO so can run on different clock domains. - + Input and output widths need to be a multiple of each other - + Copyright (C) 2019 Benjamin Devlin and Zcash Foundation 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 along with this program. If not, see . - */ + */ module width_change_cdc_fifo # ( parameter IN_DAT_BYTS, @@ -29,12 +29,12 @@ module width_change_cdc_fifo # ( parameter USE_BRAM ) ( 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 ); - + 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 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 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 always_comb 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)); end else begin 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; sop_l <= 0; 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.rdy) begin o_axi_b.reset_source(); end - + if (o_axi_int.val) begin - + if (byt_cnt == 0 && o_axi_int.sop) begin sop_l <= 1; if (SHIFT_DOWN) o_axi_b.sop <= 1; end - + if (SHIFT_DOWN) o_axi_b.dat <= o_axi_int.dat[byt_cnt*8 +: OUT_DAT_BITS]; else o_axi_b.dat[byt_cnt*8 +: IN_DAT_BITS] <= o_axi_int.dat; - + if (SHIFT_DOWN) begin if (o_axi_int.val) 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) byt_cnt <= byt_cnt + IN_DAT_BYTS; end - + if ((byt_cnt + IN_DAT_BYTS) % OUT_DAT_BYTS == 0 || o_axi_int.eop || SHIFT_DOWN ) begin o_axi_b.val <= 1; - + if (~SHIFT_DOWN) o_axi_b.sop <= sop_l || o_axi_int.sop; - + sop_l <= 0; if (SHIFT_DOWN) begin 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_b.eop <= o_axi_int.eop; - byt_cnt <= 0; + byt_cnt <= 0; end - + end else begin o_axi_b.eop <= o_axi_int.eop; byt_cnt <= 0; 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 +endgenerate + cdc_fifo #( - .SIZE ( 1<