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