1`timescale 1ns / 1ps 2/* 3 * This software is Copyright (c) 2016 Denis Burykin 4 * [denis_burykin yahoo com], [denis-burykin2014 yandex ru] 5 * and it is hereby released to the general public under the following terms: 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted. 8 * 9 */ 10 11// 12// Synchronous FIFO (DRAM) 13// 1st Word Fall-Through 14// Area Optimized 15// 16module fifo_sync_small #( 17 parameter D_WIDTH = -1, 18 parameter A_WIDTH = 5 19 )( 20 input CLK, 21 input [D_WIDTH-1:0] din, 22 input wr_en, 23 output full, 24 25 output [D_WIDTH-1:0] dout, 26 input rd_en, 27 output empty 28 ); 29 30 (* RAM_STYLE="DISTRIBUTED" *) 31 reg [D_WIDTH-1:0] ram [2**A_WIDTH-1:0]; 32 reg [A_WIDTH-1:0] inptr = 0, outptr = 0; 33 34 assign empty = inptr == outptr; 35 assign full = inptr + 1'b1 == outptr; 36 assign dout = ram[outptr]; 37 38 always @(posedge CLK) begin 39 if (~full & wr_en) begin 40 ram[inptr] <= din; 41 inptr <= inptr + 1'b1; 42 end 43 if (~empty & rd_en) 44 outptr <= outptr + 1'b1; 45 end 46 47endmodule 48 49 50module fifo_sync_fast #( 51 parameter D_WIDTH = -1, 52 parameter A_WIDTH = 5 53 )( 54 input CLK, 55 input [D_WIDTH-1:0] din, 56 input wr_en, 57 output reg full = 0, 58 59 output [D_WIDTH-1:0] dout, 60 input rd_en, 61 output reg empty = 1 62 ); 63 64 (* RAM_STYLE="DISTRIBUTED" *) 65 reg [D_WIDTH-1:0] ram [2**A_WIDTH-1:0]; 66 reg [A_WIDTH-1:0] inptr = 0, outptr = 0; 67 68 assign dout = ram[outptr]; 69 70 wire do_write = ~full & wr_en; 71 wire do_read = ~empty & rd_en; 72 73 always @(posedge CLK) begin 74 if (do_write) begin 75 ram[inptr] <= din; 76 inptr <= inptr + 1'b1; 77 end 78 79 if (do_read) 80 outptr <= outptr + 1'b1; 81 82 full <= ~do_read & (inptr + 1'b1 == outptr 83 || inptr + 2'b10 == outptr & do_write); 84 85 empty <= ~do_write & (inptr == outptr 86 || inptr == outptr + 1'b1 & do_read); 87 end 88 89endmodule 90 91 92module fifo_sync_fast_af_ae #( 93 parameter D_WIDTH = -1, 94 parameter A_WIDTH = 5 95 )( 96 input CLK, 97 input [D_WIDTH-1:0] din, 98 input wr_en, 99 output reg full = 0, 100 output reg almost_full = 0, 101 102 output [D_WIDTH-1:0] dout, 103 input rd_en, 104 output reg empty = 1, 105 output reg almost_empty = 1 106 ); 107 108 (* RAM_STYLE="DISTRIBUTED" *) 109 reg [D_WIDTH-1:0] ram [2**A_WIDTH-1:0]; 110 reg [A_WIDTH-1:0] inptr = 0, outptr = 0; 111 112 assign dout = ram[outptr]; 113 114 wire do_write = ~full & wr_en; 115 wire do_read = ~empty & rd_en; 116 117 always @(posedge CLK) begin 118 if (do_write) begin 119 ram[inptr] <= din; 120 inptr <= inptr + 1'b1; 121 end 122 123 if (do_read) 124 outptr <= outptr + 1'b1; 125 126 full <= ~do_read & (inptr + 1'b1 == outptr 127 || inptr + 2'b10 == outptr & do_write); 128 129 almost_full <= full 130 || ~do_read & (inptr + 2'b10 == outptr 131 || inptr + 2'b11 == outptr & do_write); 132 133 empty <= ~do_write & (inptr == outptr 134 || inptr == outptr + 1'b1 & do_read); 135 136 almost_empty <= empty 137 || ~do_write & (inptr == outptr + 1'b1 138 || inptr == outptr + 2'b10 & do_read); 139 end 140 141endmodule 142 143 144