| 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 */
|