1// 2// Copyright 2012-2014 Ettus Research LLC 3// Copyright 2018 Ettus Research, a National Instruments Company 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7 8 9 10// Block RAM AXI fifo 11 12 13module axi_fifo_bram 14 #(parameter WIDTH=32, SIZE=9) 15 (input clk, input reset, input clear, 16 input [WIDTH-1:0] i_tdata, 17 input i_tvalid, 18 output i_tready, 19 output reg [WIDTH-1:0] o_tdata = 'd0, 20 output reg o_tvalid = 1'b0, 21 input o_tready, 22 23 output reg [15:0] space, 24 output reg [15:0] occupied); 25 26 wire [WIDTH-1:0] int_tdata; 27 wire int_tready; 28 29 wire full, empty; 30 wire write = i_tvalid & i_tready; 31 // read_int will assert when either a read occurs or the output register is empty (and there is data in the shift register fifo) 32 wire read_int = ~empty & int_tready; 33 // read will only assert when an actual 1read request occurs at the interface 34 wire read = o_tready & o_tvalid; 35 36 assign i_tready = ~full; 37 38 // Read side states 39 localparam ST_EMPTY = 0; 40 localparam PRE_READ = 1; 41 localparam READING = 2; 42 43 reg [SIZE-1:0] wr_addr, rd_addr; 44 reg [1:0] read_state; 45 46 reg empty_reg = 1'b1, full_reg = 1'b0; 47 always @(posedge clk) 48 if(reset) 49 wr_addr <= 0; 50 else if(clear) 51 wr_addr <= 0; 52 else if(write) 53 wr_addr <= wr_addr + 1; 54 55 ram_2port #(.DWIDTH(WIDTH),.AWIDTH(SIZE)) 56 ram (.clka(clk), 57 .ena(1'b1), 58 .wea(write), 59 .addra(wr_addr), 60 .dia(i_tdata), 61 .doa(), 62 63 .clkb(clk), 64 .enb((read_state==PRE_READ)|read_int), 65 .web(1'b0), 66 .addrb(rd_addr), 67 .dib({WIDTH{1'b1}}), 68 .dob(int_tdata)); 69 70 always @(posedge clk) 71 if(reset) 72 begin 73 read_state <= ST_EMPTY; 74 rd_addr <= 0; 75 empty_reg <= 1; 76 end 77 else 78 if(clear) 79 begin 80 read_state <= ST_EMPTY; 81 rd_addr <= 0; 82 empty_reg <= 1; 83 end 84 else 85 case(read_state) 86 ST_EMPTY : 87 if(write) 88 begin 89 //rd_addr <= wr_addr; 90 read_state <= PRE_READ; 91 end 92 PRE_READ : 93 begin 94 read_state <= READING; 95 empty_reg <= 0; 96 rd_addr <= rd_addr + 1; 97 end 98 99 READING : 100 if(read_int) 101 if(rd_addr == wr_addr) 102 begin 103 empty_reg <= 1; 104 if(write) 105 read_state <= PRE_READ; 106 else 107 read_state <= ST_EMPTY; 108 end 109 else 110 rd_addr <= rd_addr + 1; 111 endcase // case(read_state) 112 113 wire [SIZE-1:0] dont_write_past_me = rd_addr - 2; 114 wire becoming_full = wr_addr == dont_write_past_me; 115 116 always @(posedge clk) 117 if(reset) 118 full_reg <= 0; 119 else if(clear) 120 full_reg <= 0; 121 else if(read_int & ~write) 122 full_reg <= 0; 123 //else if(write & ~read_int & (wr_addr == (rd_addr-3))) 124 else if(write & ~read_int & becoming_full) 125 full_reg <= 1; 126 127 //assign empty = (read_state != READING); 128 assign empty = empty_reg; 129 130 // assign full = ((rd_addr - 1) == wr_addr); 131 assign full = full_reg; 132 133 // Output registered stage 134 always @(posedge clk) 135 begin 136 // Valid flag 137 if (reset | clear) 138 o_tvalid <= 1'b0; 139 else if (int_tready) 140 o_tvalid <= ~empty; 141 142 // Data 143 if (int_tready) 144 o_tdata <= int_tdata; 145 end 146 147 assign int_tready = o_tready | ~o_tvalid; 148 149 ////////////////////////////////////////////// 150 // space and occupied are for diagnostics only 151 // not guaranteed exact 152 153 localparam NUMLINES = (1<<SIZE)+1; //Output register increases capacity by 1 154 always @(posedge clk) 155 if(reset) 156 space <= NUMLINES; 157 else if(clear) 158 space <= NUMLINES; 159 else if(read & ~write) 160 space <= space + 16'b1; 161 else if(write & ~read) 162 space <= space - 16'b1; 163 164 always @(posedge clk) 165 if(reset) 166 occupied <= 16'b0; 167 else if(clear) 168 occupied <= 16'b0; 169 else if(read & ~write) 170 occupied <= occupied - 16'b1; 171 else if(write & ~read) 172 occupied <= occupied + 16'b1; 173 174endmodule // fifo_long 175