// (C) Tomonori Izumi , Jul. 2014. All rigts reserved. // migratable FIFO module for any FPGA (Xilinx or Altera) // use two block RAMs // model ... 1port ,pipelined, 2cycles delay // parameter DW ... data bitwidth // parameter AW ... addr bitwidth // parameter SZ ... memory size (i.e. 2^AW) module fiforeg_module (xrst, clk, idata, ivalid, iwait, odata, ovalid, owait, count, clr); parameter DW = 8; parameter AW = 2; parameter SZ = 4; input xrst, clk; input [DW-1:0] idata; input ivalid; output iwait; output [DW-1:0] odata; output ovalid; input owait; output [AW:0] count; input clr; reg [DW-1:0] r[SZ-1:0]; reg [AW-1:0] waddr_reg,raddr_reg; reg [AW:0] count_reg; assign iwait = (count>=SZ) ? 1 : 0; assign ovalid = (count>0) ? 1 : 0; assign odata = r[raddr_reg]; assign count = count_reg; wire iexec, oexec; assign iexec = ivalid&~iwait; assign oexec = ovalid&~owait; always @(posedge clk or negedge xrst) if (~xrst) begin waddr_reg<=0; raddr_reg<=0; count_reg<=0; end else if (clr) begin waddr_reg<=0; raddr_reg<=0; count_reg<=0; end else begin case ({iexec,oexec}) 2'b11 : begin r[waddr_reg]<=idata; waddr_reg<=waddr_reg+1; raddr_reg<=raddr_reg+1; end 2'b10 : begin r[waddr_reg]<=idata; waddr_reg<=waddr_reg+1; count_reg<=count_reg+1; end 2'b01 : begin raddr_reg<=raddr_reg+1; count_reg<=count_reg-1; end endcase end endmodule module fifo2t_module (xrst, clk, idata,ivalid,iwait, odata,ovalid,owait, count,clr); parameter DW = 8; parameter AW = 3; parameter SZ = 8; input xrst, clk; input [DW-1:0] idata; input ivalid; output iwait; output [DW-1:0] odata; output ovalid; input owait; output [AW:0] count; // max SZ+4 input clr; wire iexec,oexec; assign iexec = ivalid&~iwait; assign oexec = ovalid&~owait; reg [AW:0] count_reg; assign count = count_reg; always @(posedge clk or negedge xrst) if (~xrst) count_reg<=0; else if (clr) count_reg<=0; else if (iexec&~oexec) count_reg<=count_reg+1; else if (oexec&~iexec) count_reg<=count_reg-1; reg [AW-1:0] raddr_reg, waddr_reg; reg [AW :0] memcount_reg; assign iwait = (memcount_reg>=SZ); wire [AW-1:0] mema; wire [DW-1:0] memd, memq; wire memwe, memre; reg mv1,mv2; // delayed valid for pipelined read defparam mem.DW=DW; defparam mem.AW=AW; defparam mem.SZ=SZ; mem2pipe_module mem(clk,mema,memd,memq,memwe); // 2cyc pipe mem wire [2:0] fifo4count; wire fifo4iwait; defparam fifo.DW=DW; defparam fifo.AW=2; defparam fifo.SZ=4; fiforeg_module fifo (xrst,clk,memq,mv2,fifo4iwait,odata,ovalid,owait,fifo4count,clr); wire [2:0] outbufcount; assign outbufcount = fifo4count+mv1+mv2; assign memwe = (~iwait) & ivalid; assign memre = (~memwe) & (memcount_reg>0) & (outbufcount<4); assign mema = memwe ? waddr_reg : raddr_reg; assign memd = idata; always @(posedge clk or negedge xrst) if (~xrst) begin waddr_reg<=0; raddr_reg<=0; memcount_reg<=0; mv1<=0; mv2<=0; end else if (clr) begin waddr_reg<=0; raddr_reg<=0; memcount_reg<=0; mv1<=0; mv2<=0; end else begin if (memwe) begin waddr_reg<=waddr_reg+1; memcount_reg<=memcount_reg+1; mv1<=0; end else if (memre) begin raddr_reg<=raddr_reg+1; memcount_reg<=memcount_reg-1; mv1<=1; end else begin mv1<=0; end mv2<=mv1; end endmodule module fifo_module (xrst, clk, idata, ivalid, iwait, odata, ovalid, owait, count, clr); parameter DW = 8; parameter AW = 3; parameter SZ = 8; input xrst, clk; input [DW-1:0] idata; input ivalid; output iwait; output [DW-1:0] odata; output ovalid; input owait; output [AW+1:0] count; // max 2*(SZ+4) input clr; wire iexec,oexec; assign iexec = ivalid&~iwait; assign oexec = ovalid&~owait; reg [AW+1:0] count_reg; assign count = count_reg; always @(posedge clk or negedge xrst) if (~xrst) count_reg<=0; else if (clr) count_reg<=0; else if (iexec&~oexec) count_reg<=count_reg+1; else if (oexec&~iexec) count_reg<=count_reg-1; wire [DW-1:0] fifo0idata, fifo1idata, fifo0odata, fifo1odata; wire fifo0ivalid, fifo1ivalid, fifo0ovalid, fifo1ovalid; wire fifo0iwait, fifo1iwait, fifo0owait, fifo1owait; wire [AW:0] fifo0count, fifo1count; defparam fifo0.DW=DW; defparam fifo0.AW=AW; defparam fifo0.SZ=SZ; fifo2t_module fifo0 (xrst, clk, fifo0idata,fifo0ivalid,fifo0iwait, fifo0odata,fifo0ovalid,fifo0owait, fifo0count,clr); defparam fifo1.DW=DW; defparam fifo1.AW=AW; defparam fifo1.SZ=SZ; fifo2t_module fifo1 (xrst, clk, fifo1idata,fifo1ivalid,fifo1iwait, fifo1odata,fifo1ovalid,fifo1owait, fifo1count,clr); reg [DW-1:0] data0i,data0o,data1i,data1o; reg valid0i,valid0o,valid1i,valid1o; reg seli,selo; wire iexec0,iexec1,ifwd0,ifwd1; wire oexec0,oexec1,orcv0,orcv1; assign iexec0 = ivalid & (seli==0) & ~valid0i; assign ifwd0 = valid0i & ~fifo0iwait; assign fifo0idata = data0i; assign fifo0ivalid = valid0i; assign iexec1 = ivalid & (seli==1) & ~valid1i; assign ifwd1 = valid1i & ~fifo1iwait; assign fifo1idata = data1i; assign fifo1ivalid = valid1i; assign iwait = seli ? valid1i : valid0i; always @(posedge clk or negedge xrst) if (~xrst) begin data0i<=0; valid0i<=0; end else if (clr) begin data0i<=0; valid0i<=0; end else if (iexec0) begin data0i<=idata; valid0i<=1; end else if (ifwd0) valid0i<=0; always @(posedge clk or negedge xrst) if (~xrst) begin data1i<=0; valid1i<=0; end else if (clr) begin data1i<=0; valid1i<=0; end else if (iexec1) begin data1i<=idata; valid1i<=1; end else if (ifwd1) valid1i<=0; always @(posedge clk or negedge xrst) if (~xrst) seli<=0; else if (clr) seli<=0; else if (iexec0) seli<=1; else if (iexec1) seli<=0; assign orcv0 = fifo0ovalid & ~valid0o; assign fifo0owait = valid0o; assign oexec0 = valid0o & (selo==0) & ~owait; assign orcv1 = fifo1ovalid & ~valid1o; assign fifo1owait = valid1o; assign oexec1 = valid1o & (selo==1) & ~owait; assign ovalid = selo ? valid1o : valid0o; assign odata = selo ? data1o : data0o; always @(posedge clk or negedge xrst) if (~xrst) begin data0o<=0; valid0o<=0; end else if (clr) begin data0o<=0; valid0o<=0; end else if (orcv0) begin data0o<=fifo0odata; valid0o<=1; end else if (oexec0) valid0o<=0; always @(posedge clk or negedge xrst) if (~xrst) begin data1o<=0; valid1o<=0; end else if (clr) begin data1o<=0; valid1o<=0; end else if (orcv1) begin data1o<=fifo1odata; valid1o<=1; end else if (oexec1) valid1o<=0; always @(posedge clk or negedge xrst) if (~xrst) selo<=0; else if (oexec0) selo<=1; else if (oexec1) selo<=0; endmodule