1 |
2 |
kdv |
/*
|
2 |
|
|
* read_write.v
|
3 |
|
|
*
|
4 |
|
|
* Copyright (c) 2007 Koen De Vleeschauwer.
|
5 |
|
|
*
|
6 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
7 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
8 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
9 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
10 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
11 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
12 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
13 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
14 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
15 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
16 |
|
|
* SUCH DAMAGE.
|
17 |
|
|
*/
|
18 |
|
|
|
19 |
|
|
/*
|
20 |
|
|
* read_write - Interface for framestore readers/writers.
|
21 |
|
|
*/
|
22 |
|
|
|
23 |
|
|
`include "timescale.v"
|
24 |
|
|
|
25 |
|
|
/*
|
26 |
|
|
* Address is a 22-bit memory address, which unequivocally determines the location of one 64-bit macroblock row, 8 pixels wide, 8 bits per pixel.
|
27 |
|
|
* Data is one 64-bit macroblock row, 8 pixels wide, 8 bits per pixel.
|
28 |
|
|
*
|
29 |
|
|
* Frame store and reader/writer may have different clocks.
|
30 |
|
|
* Reader/writer uses clock "clk", frame store uses clock "mem_clk".
|
31 |
|
|
* Only the reader/writer side has a clock enable clk_en; the frame store is free running.
|
32 |
|
|
*/
|
33 |
|
|
|
34 |
|
|
`undef CHECK
|
35 |
|
|
`ifdef __IVERILOG__
|
36 |
|
|
`define CHECK 1
|
37 |
|
|
`endif
|
38 |
|
|
|
39 |
|
|
module framestore_reader(
|
40 |
|
|
rst, clk,
|
41 |
|
|
wr_addr_clk_en, wr_addr_full, wr_addr_almost_full, wr_addr_en, wr_addr_ack, wr_addr_overflow, wr_addr, rd_dta_clk_en, rd_dta_almost_empty, rd_dta_empty, rd_dta_en, rd_dta_valid, rd_dta,
|
42 |
|
|
rd_addr_empty, rd_addr_en, rd_addr_valid, rd_addr, wr_dta_full, wr_dta_almost_full, wr_dta_en, wr_dta_ack, wr_dta_overflow, wr_dta
|
43 |
|
|
);
|
44 |
|
|
|
45 |
|
|
/*
|
46 |
|
|
* Note: maximum clock frequency may depend upon fifo depth.
|
47 |
|
|
* On Xilinx Spartan, once the fifo is too long to fit in single block ram, speed drops.
|
48 |
|
|
* For 64-bit words, a depth of 127-256 entries seems optimal. YMMV.
|
49 |
|
|
*/
|
50 |
|
|
parameter [8:0]fifo_dta_depth=9'd7; // number of levels in fifo = 2 ** fifo_depth. eg. fifo_depth=7 gives a fifo 128 levels deep.
|
51 |
|
|
parameter [8:0]fifo_addr_depth=9'd5; // number of levels in fifo = 2 ** fifo_depth. eg. fifo_depth=5 gives a fifo 32 levels deep.
|
52 |
|
|
parameter [8:0]fifo_addr_threshold=9'd8; // assert wr_addr_almost_full when 8 free slots left.
|
53 |
|
|
parameter [8:0]fifo_dta_threshold=9'd6; // assert wr_dta_almost_full when 6 free slots left.
|
54 |
|
|
|
55 |
|
|
/* address and data fifo reset and clock */
|
56 |
|
|
input rst;
|
57 |
|
|
input clk;
|
58 |
|
|
/* reader side, writing address */
|
59 |
|
|
input wr_addr_clk_en;
|
60 |
|
|
output wr_addr_full;
|
61 |
|
|
output wr_addr_almost_full;
|
62 |
|
|
input wr_addr_en;
|
63 |
|
|
input [21:0]wr_addr;
|
64 |
|
|
output wr_addr_ack;
|
65 |
|
|
output wr_addr_overflow;
|
66 |
|
|
/* reader side, reading data */
|
67 |
|
|
input rd_dta_clk_en;
|
68 |
|
|
output rd_dta_almost_empty;
|
69 |
|
|
output rd_dta_empty;
|
70 |
|
|
input rd_dta_en;
|
71 |
|
|
output [63:0]rd_dta;
|
72 |
|
|
output rd_dta_valid;
|
73 |
|
|
|
74 |
|
|
/* frame store side, reading address */
|
75 |
|
|
output rd_addr_empty;
|
76 |
|
|
input rd_addr_en;
|
77 |
|
|
output [21:0]rd_addr;
|
78 |
|
|
output rd_addr_valid;
|
79 |
|
|
/* frame store side, writing data */
|
80 |
|
|
output wr_dta_full;
|
81 |
|
|
output wr_dta_almost_full;
|
82 |
|
|
input wr_dta_en;
|
83 |
|
|
output wr_dta_ack;
|
84 |
|
|
input [63:0]wr_dta;
|
85 |
|
|
output wr_dta_overflow;
|
86 |
|
|
|
87 |
|
|
/* address fifo */
|
88 |
|
|
fifo_sc
|
89 |
|
|
#(.addr_width(fifo_addr_depth),
|
90 |
|
|
.dta_width(9'd22), // block row address is 22 bits.
|
91 |
|
|
.prog_thresh(fifo_addr_threshold))
|
92 |
|
|
reader_addr_fifo (
|
93 |
|
|
.rst(rst),
|
94 |
|
|
.clk(clk),
|
95 |
|
|
.din(wr_addr),
|
96 |
|
|
.wr_en(wr_addr_en && wr_addr_clk_en),
|
97 |
|
|
.wr_ack(wr_addr_ack),
|
98 |
|
|
.full(wr_addr_full),
|
99 |
|
|
.overflow(wr_addr_overflow),
|
100 |
|
|
.prog_full(wr_addr_almost_full),
|
101 |
|
|
.dout(rd_addr),
|
102 |
|
|
.rd_en(rd_addr_en),
|
103 |
|
|
.valid(rd_addr_valid),
|
104 |
|
|
.underflow(),
|
105 |
|
|
.empty(rd_addr_empty),
|
106 |
|
|
.prog_empty()
|
107 |
|
|
);
|
108 |
|
|
|
109 |
|
|
/*
|
110 |
|
|
* Generate an "almost full" signal when framestore should stop treating read requests for this reader.
|
111 |
|
|
* The 'almost full' signal is actually asserted when only 6 free slots remain in the fifo.
|
112 |
|
|
*/
|
113 |
|
|
|
114 |
|
|
fifo_sc
|
115 |
|
|
#(.addr_width(fifo_dta_depth),
|
116 |
|
|
.dta_width(9'd64), // one block row is 8 pixels at 8 bits each, 64 bits total.
|
117 |
|
|
.prog_thresh(fifo_dta_threshold)) // assert prog_full when fifo has space for 8 (or less) entries (= 1 block).
|
118 |
|
|
reader_dta_fifo (
|
119 |
|
|
.rst(rst),
|
120 |
|
|
.clk(clk),
|
121 |
|
|
.din(wr_dta),
|
122 |
|
|
.wr_en(wr_dta_en),
|
123 |
|
|
.wr_ack(wr_dta_ack),
|
124 |
|
|
.full(wr_dta_full),
|
125 |
|
|
.overflow(wr_dta_overflow),
|
126 |
|
|
.dout(rd_dta),
|
127 |
|
|
.rd_en(rd_dta_en && rd_dta_clk_en),
|
128 |
|
|
.valid(rd_dta_valid),
|
129 |
|
|
.underflow(),
|
130 |
|
|
.empty(rd_dta_empty),
|
131 |
|
|
.prog_empty(rd_dta_almost_empty),
|
132 |
|
|
.prog_full(wr_dta_almost_full)
|
133 |
|
|
);
|
134 |
|
|
|
135 |
|
|
`ifdef CHECK
|
136 |
|
|
always @(posedge clk)
|
137 |
|
|
if (wr_addr_overflow)
|
138 |
|
|
begin
|
139 |
|
|
#0 $display ("%m\t*** error: framestore_reader addr fifo overflow. ***");
|
140 |
|
|
$stop;
|
141 |
|
|
end
|
142 |
|
|
|
143 |
|
|
always @(posedge clk)
|
144 |
|
|
if (wr_dta_overflow)
|
145 |
|
|
begin
|
146 |
|
|
#0 $display ("%m\t*** error: framestore_reader data fifo overflow. ***");
|
147 |
|
|
$stop;
|
148 |
|
|
end
|
149 |
|
|
`endif
|
150 |
|
|
|
151 |
|
|
endmodule
|
152 |
|
|
|
153 |
|
|
module framestore_writer(
|
154 |
|
|
rst, clk, clk_en,
|
155 |
|
|
wr_full, wr_almost_full, wr_ack, wr_en, wr_addr, wr_dta, wr_overflow,
|
156 |
|
|
rd_empty, rd_almost_empty, rd_valid, rd_en, rd_addr, rd_dta
|
157 |
|
|
);
|
158 |
|
|
|
159 |
|
|
/*
|
160 |
|
|
* Fifo depth.
|
161 |
|
|
* Note: maximum clock frequency depends upon fifo depth.
|
162 |
|
|
* On Xilinx Spartan, once you go beyond a single block ram, speed drops. XXX Check.
|
163 |
|
|
* For 64-bit words, a depth of around 256 seems optimal. YMMV.
|
164 |
|
|
*/
|
165 |
|
|
parameter [8:0]fifo_depth=9'd7; // number of levels in fifo = 2 ** fifo_depth. eg. fifo_depth=7 gives a fifo 128 levels deep.
|
166 |
|
|
parameter [8:0]fifo_threshold=9'd8; // assert wr_almost_full when 8 free slots left.
|
167 |
|
|
|
168 |
|
|
/* fifo reset and clock */
|
169 |
|
|
input rst;
|
170 |
|
|
input clk;
|
171 |
|
|
input clk_en;
|
172 |
|
|
/* writer side, writing command and address */
|
173 |
|
|
output wr_full;
|
174 |
|
|
output wr_almost_full;
|
175 |
|
|
output wr_ack;
|
176 |
|
|
input wr_en;
|
177 |
|
|
input [21:0]wr_addr;
|
178 |
|
|
input [63:0]wr_dta;
|
179 |
|
|
output wr_overflow;
|
180 |
|
|
|
181 |
|
|
/* frame store side, reading command and address */
|
182 |
|
|
output rd_empty;
|
183 |
|
|
output rd_almost_empty;
|
184 |
|
|
output rd_valid;
|
185 |
|
|
input rd_en;
|
186 |
|
|
output [21:0]rd_addr;
|
187 |
|
|
output [63:0]rd_dta;
|
188 |
|
|
|
189 |
|
|
fifo_sc
|
190 |
|
|
#(.addr_width(fifo_depth),
|
191 |
|
|
.dta_width(9'd86), // 22 bit address + 64 bit data = 86 bits
|
192 |
|
|
.prog_thresh(fifo_threshold)) // assert prog_empty when fifo has 8 (or less than 8) entries.
|
193 |
|
|
writer_fifo (
|
194 |
|
|
.rst(rst),
|
195 |
|
|
.clk(clk),
|
196 |
|
|
.din({wr_addr, wr_dta}),
|
197 |
|
|
.wr_en(wr_en && clk_en),
|
198 |
|
|
.full(wr_full),
|
199 |
|
|
.prog_full(wr_almost_full),
|
200 |
|
|
.wr_ack(wr_ack),
|
201 |
|
|
.overflow(wr_overflow),
|
202 |
|
|
.dout({rd_addr, rd_dta}),
|
203 |
|
|
.rd_en(rd_en),
|
204 |
|
|
.empty(rd_empty),
|
205 |
|
|
.prog_empty(rd_almost_empty),
|
206 |
|
|
.valid(rd_valid),
|
207 |
|
|
.underflow()
|
208 |
|
|
);
|
209 |
|
|
|
210 |
|
|
`ifdef CHECK
|
211 |
|
|
always @(posedge clk)
|
212 |
|
|
if (wr_overflow)
|
213 |
|
|
begin
|
214 |
|
|
#0 $display ("%m\t*** error: framestore_writer fifo overflow ***");
|
215 |
|
|
$stop;
|
216 |
|
|
end
|
217 |
|
|
|
218 |
|
|
`endif
|
219 |
|
|
|
220 |
|
|
endmodule
|
221 |
|
|
/* not truncated */
|