module giantfifo #(parameter WIDTH=36) (input clk, input rst, input [WIDTH-1:0] datain, output [WIDTH-1:0] dataout, input read, input write, input clear, output full, output empty, output [15:0] space, output [15:0] occupied, // External RAM inout [17:0] RAM_D, output reg [18:0] RAM_A, output RAM_CE1n, output RAM_CENn, output reg RAM_CLK, output reg RAM_WEn, output RAM_OEn, output RAM_LDn ); wire [4:0] path1_occ, path2_space; wire [35:0] path1_dat, path2_dat; shortfifo #(.WIDTH(WIDTH)) sf1 (.clk(clk),.rst(rst),.clear(clear), .datain(datain),.write(write),.full(full), .dataout(path1_dat),.read(path1_read),.empty(path1_empty), .space(),.occupied(path1_occ) ); wire path1_almost_empty = (path1_occ == 5'd1); shortfifo #(.WIDTH(WIDTH)) sf2 (.clk(clk),.rst(rst),.clear(clear), .datain(path2_dat),.write(path2_write),.full(path2_full), .dataout(dataout),.read(read),.empty(empty), .space(path2_space),.occupied() ); wire path2_almost_full = (path2_space == 5'd1); assign RAM_CE1n = 1'b0; assign RAM_CENn = 1'b0; always @(clk) RAM_CLK <= #2 clk; assign RAM_LDn = 1'b0; // State machine wire write_now, read_now, idle, phase; reg ram_full, ram_empty; reg [17:0] read_ptr, write_ptr; reg [2:0] zbt_state; localparam ZBT_IDLE = 0; localparam ZBT_WRITE_UPPER = 2; localparam ZBT_WRITE_LOWER = 3; localparam ZBT_READ_UPPER = 4; localparam ZBT_READ_LOWER = 5; wire can_write = ~ram_full & ~path1_empty; wire can_write_chain = can_write & ~path1_almost_empty; wire can_read = ~ram_empty & ~path2_full; wire can_read_chain = can_read & ~path2_almost_full; assign phase = zbt_state[0]; reg [17:0] ram_occupied; wire ram_almost_empty = (write_ptr == (read_ptr+1'b1)); wire ram_almost_full = ((write_ptr+1'b1) == read_ptr); always @(posedge clk) if(rst | clear) begin zbt_state <= ZBT_IDLE; write_ptr <= 0; read_ptr <= 0; ram_full <= 0; ram_empty <= 1; ram_occupied <= 0; end else case(zbt_state) ZBT_IDLE : if(can_read) zbt_state <= ZBT_READ_UPPER; else if(can_write) zbt_state <= ZBT_WRITE_UPPER; ZBT_WRITE_UPPER : begin zbt_state <= ZBT_WRITE_LOWER; ram_occupied <= ram_occupied + 1; ram_empty <= 0; if(ram_occupied == 18'd10) ram_full <= 1; end ZBT_WRITE_LOWER : begin write_ptr <= write_ptr + 1; if(can_read_chain) zbt_state <= ZBT_READ_UPPER; else if(can_write_chain) zbt_state <= ZBT_WRITE_UPPER; else zbt_state <= ZBT_IDLE; end ZBT_READ_UPPER : begin zbt_state <= ZBT_READ_LOWER; ram_occupied <= ram_occupied - 1; ram_full <= 0; if(ram_occupied == 18'd1) ram_empty <= 1; end ZBT_READ_LOWER : begin read_ptr <= read_ptr + 1; if(can_read_chain) zbt_state <= ZBT_READ_UPPER; else if(can_write_chain) zbt_state <= ZBT_WRITE_UPPER; else zbt_state <= ZBT_IDLE; end default : zbt_state <= ZBT_IDLE; endcase // case(zbt_state) // Need to generate RAM_WEn, RAM_OEn, RAM_D, RAM_A; assign path1_read = (zbt_state == ZBT_WRITE_LOWER); reg path2_write, delayed_read_upper, delayed_read_lower, delayed_write; always @(posedge clk) if(delayed_read_upper) path2_dat[35:18] <= RAM_D; always @(posedge clk) if(delayed_read_lower) path2_dat[17:0] <= RAM_D; always @(posedge clk) if(rst) begin delayed_read_upper <= 0; delayed_read_lower <= 0; path2_write <= 0; end else begin delayed_read_upper <= (zbt_state == ZBT_READ_LOWER); delayed_read_lower <= delayed_read_upper; path2_write <= delayed_read_lower; end reg [17:0] RAM_D_pre2, RAM_D_pre1, RAM_D_out; always @(posedge clk) RAM_D_pre2 <= phase ? path1_dat[17:0] : path1_dat[35:18]; always @(posedge clk) RAM_D_pre1 <= RAM_D_pre2; always @(posedge clk) RAM_D_out <= RAM_D_pre1; reg wr_del_1, wr_del_2; always @(posedge clk) if(rst) begin wr_del_1 <= 0; wr_del_2 <= 0; delayed_write <= 0; end else begin delayed_write <= wr_del_2; wr_del_2 <= wr_del_1; wr_del_1 <= write_now; end reg delayed_read, rd_del_1, rd_del_2; always @(posedge clk) if(rst) begin rd_del_1 <= 0; rd_del_2 <= 0; delayed_read <= 0; end else begin delayed_read <= rd_del_2; rd_del_2 <= rd_del_1; rd_del_1 <= read_now; end assign RAM_D = delayed_write ? RAM_D_out : 18'bzzzzzzzzzzzzzzzzzz; assign write_now = (zbt_state == ZBT_WRITE_UPPER) || (zbt_state == ZBT_WRITE_LOWER); assign read_now = (zbt_state == ZBT_READ_UPPER) || (zbt_state == ZBT_READ_LOWER); always @(posedge clk) RAM_A <= write_now ? {write_ptr,phase} : {read_ptr,phase}; always @(posedge clk) RAM_WEn <= ~write_now; assign RAM_OEn = ~delayed_read; assign RAM_OEn = 0; endmodule // giantfifo