URL
https://opencores.org/ocsvn/open_free_list/open_free_list/trunk
Subversion Repositories open_free_list
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/open_free_list/trunk/hdl/open_free_list.v
0,0 → 1,314
module open_free_list #(parameter RAM_W = 128, RAM_E = 0, RAM_S = 64, CNK_S = 128, RAM_TYPE = "MRAM", FL_AEMPTY_LVL=2) ( |
input wire reset_n, |
input wire clk, |
// Write side |
output wire [clog2((RAM_S*1024)/CNK_S)-1:0] fl_q, |
output wire fl_aempty, |
output wire fl_empty, |
input wire wren, |
input wire [RAM_W+RAM_E-1:0] din, |
input wire eop, |
// Read side |
input wire [clog2((RAM_S*1024)/CNK_S)-1:0] chunk_num, |
input wire load_req, |
input wire rel_req, |
output reg load_rel_ack, |
input wire rden, |
output wire [RAM_W+RAM_E-1:0] dout |
); |
|
localparam FL_S = (RAM_S*1024)/CNK_S; |
localparam FL_W = clog2(FL_S); |
localparam FL_ADDR_W = FL_W; |
localparam LL_W = FL_W+1; |
localparam RAM_ADDR_W = clog2((RAM_S*1024)/(RAM_W/8)); |
localparam LINES_IN_CNK = CNK_S/(RAM_W/8); |
localparam IN_CNK_ADDR_W = clog2(LINES_IN_CNK); |
|
|
wire [RAM_W+RAM_E-1:0] ram_q; |
reg [RAM_ADDR_W-1:0] ram_rd_addr; |
wire [RAM_ADDR_W-1:0] ram_wr_addr; |
reg [RAM_ADDR_W-1:0] ram_wr_addr_lat; |
reg wr_eop_while_ll; |
reg [FL_W-1:0] fl_data; |
wire [FL_ADDR_W-1:0] fl_lvl; |
reg fl_rden; |
reg fl_wren; |
wire [FL_W:0] ll_data; |
wire [FL_W:0] ll_q; |
reg [FL_ADDR_W-1:0] ll_rd_addr; |
wire [FL_ADDR_W-1:0] ll_wr_addr; |
wire ll_wren; |
wire ll_eop; |
|
reg [FL_ADDR_W-1:0] fl_init_cnt; |
reg fl_init; |
reg fl_init_r1; |
reg fl_init_r2; |
reg fl_init_r3; |
reg fl_init_wr; |
|
reg int_sop; |
reg rel_req_from_idle; |
|
wire load_req_p; |
wire [FL_ADDR_W-1:0] nxt_chunk_ptr; |
|
reg [2:0] ns_rd_sm; |
reg [2:0] cs_rd_sm; |
parameter IDLE = 3'd0, |
PREFETCH = 3'd1, |
RD = 3'd2, |
WAIT_REL = 3'd3, |
REL_DELAY1 = 3'd4, |
REL_DELAY2 = 3'd5, |
REL_WR2FL = 3'd6; |
|
reg sm_rel_ctrl; |
reg sm_rel_wren; |
|
reg rden_r1; |
reg int_rden; |
reg int_rden_r1; |
reg load_req_r1; |
reg [RAM_ADDR_W-1:0] usr_ram_rd_addr_r1; |
|
altsyncram3 ram ( |
.data (din), |
.rd_aclr (~reset_n), |
.rdaddress (ram_rd_addr), |
.rdclock (clk), |
.rdclocken (int_rden | rden), |
.wraddress (ram_wr_addr), |
.wrclock (clk), |
.wrclocken (1'b1), |
.wren (wren), |
.q (dout) |
); |
defparam |
ram.A_WIDTH = RAM_W+RAM_E, |
ram.A_WIDTHAD = RAM_ADDR_W, |
ram.RAM_TYPE = RAM_TYPE, |
ram.USE_RDEN = 0; |
|
alt_scfifo free_list( |
.aclr (~reset_n), |
.clock (clk), |
.data (fl_init_wr ? fl_init_cnt : fl_data), |
.rdreq (fl_rden), |
.sclr (1'b0), |
.wrreq (fl_init_wr | fl_wren), |
.almost_empty (fl_aempty), |
.almost_full (), |
.empty (fl_empty), |
.full (), |
.q (fl_q), |
.usedw (fl_lvl) |
); |
defparam |
free_list.FIFO_WIDTH = FL_W, |
free_list.FIFO_DEPTH = FL_ADDR_W, |
free_list.FIFO_TYPE = "M4K", |
free_list.FIFO_SHOW = "ON", |
free_list.FIFO_AEMPTY = FL_AEMPTY_LVL; |
|
|
altsyncram3 link_list( |
.data (ll_data), |
.rd_aclr (~reset_n), |
.rdaddress (sm_rel_ctrl ? nxt_chunk_ptr : ll_rd_addr), |
.rdclock (clk), |
.rdclocken (1'b1), |
.wraddress (ll_wr_addr), |
.wrclock (clk), |
.wrclocken (1'b1), |
.wren (ll_wren), |
.q (ll_q) |
); |
defparam |
link_list.A_WIDTH = LL_W, |
link_list.A_WIDTHAD = FL_ADDR_W, |
link_list.RAM_TYPE = "M4K", |
link_list.USE_RDEN = 0; |
|
|
// Free list init |
|
always @ (posedge clk, negedge reset_n) |
begin |
if (reset_n==1'b0) |
begin |
fl_init_cnt <= {FL_ADDR_W{1'b0}}; |
fl_init <= 1'b0; |
fl_init_r1 <= 1'b0; |
fl_init_r2 <= 1'b0; |
fl_init_r3 <= 1'b0; |
fl_init_wr <= 1'b0; |
end |
else |
begin |
fl_init_cnt <= fl_init_wr ? fl_init_cnt + 1'b1 : {FL_ADDR_W{1'b0}}; |
fl_init <= 1'b1; |
fl_init_r1 <= fl_init; |
fl_init_r2 <= fl_init_r1; |
fl_init_r3 <= fl_init_r2; |
fl_init_wr <= !fl_init_r3 && fl_init_r2 ? 1'b1 : fl_init_cnt=={FL_ADDR_W{1'b1}} ? 1'b0 : fl_init_wr; |
end |
end |
|
|
// Write side |
|
assign ram_wr_addr = int_sop || (wren && ram_wr_addr_lat[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) ? {fl_q, {IN_CNK_ADDR_W{1'b0}}} |
: wren ? ram_wr_addr_lat + 1'b1 |
: ram_wr_addr_lat; |
assign ll_eop = wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b0 : eop | wr_eop_while_ll; |
assign ll_wr_addr = ram_wr_addr_lat[RAM_ADDR_W-1:IN_CNK_ADDR_W]; |
assign ll_data = {fl_q, ll_eop}; |
assign ll_wren = (wren && ((ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) || eop)) || wr_eop_while_ll ? 1'b1 : 1'b0; |
|
|
always @ (posedge clk, negedge reset_n) |
begin |
if (reset_n==1'b0) |
begin |
fl_rden <= 1'b0; |
int_sop <= 1'b1; |
ram_wr_addr_lat <= {RAM_ADDR_W{1'b0}}; |
wr_eop_while_ll <= 1'b0; |
end |
else |
begin |
fl_rden <= wren && (ram_wr_addr[IN_CNK_ADDR_W-1:0]==0) ? 1'b1 : 1'b0; |
int_sop <= wren && eop ? 1'b1 : |
wren ? 1'b0 : |
int_sop; |
ram_wr_addr_lat <= ram_wr_addr; |
wr_eop_while_ll <= wren && ram_wr_addr[IN_CNK_ADDR_W-1:0]==0 && eop ? 1'b1 : 1'b0; |
end |
end |
|
// Read side |
assign load_req_p = ~load_req_r1 & load_req; |
assign nxt_chunk_ptr = ll_q[FL_W:1]; //can be sampled |
|
always @* |
begin |
case(cs_rd_sm) |
IDLE: |
ns_rd_sm = fl_init_wr ? IDLE : |
rel_req ? REL_DELAY1 : |
load_req ? PREFETCH : |
IDLE; |
PREFETCH: |
ns_rd_sm = RD; |
RD: |
ns_rd_sm = load_req ? PREFETCH : |
rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) && ll_q[0] ? WAIT_REL : // true if the current chunk is the last chunk and was reached to its end and is released now : REL_WR2FL // true if the current chunk was reached to its end and is released now and is the last one |
rel_req ? REL_WR2FL : |
RD; |
WAIT_REL: |
ns_rd_sm = rel_req ? IDLE : WAIT_REL; |
REL_DELAY1: |
ns_rd_sm = REL_DELAY2; |
REL_DELAY2: |
ns_rd_sm = REL_WR2FL; |
REL_WR2FL: |
ns_rd_sm = ll_q[0] ? IDLE : REL_DELAY2; |
endcase |
end |
|
always @* |
begin |
rel_req_from_idle = 1'b0; |
int_rden = 1'b0; |
load_rel_ack = 1'b0; |
sm_rel_ctrl = 1'b1; |
sm_rel_wren = 1'b0; |
case(cs_rd_sm) |
IDLE: |
begin |
rel_req_from_idle = rel_req; |
sm_rel_ctrl = rel_req; |
end |
PREFETCH: |
begin |
int_rden = 1'b1; |
load_rel_ack = 1'b1; |
sm_rel_ctrl = 1'b0; |
end |
RD: |
begin |
sm_rel_ctrl = 1'b0; |
end |
WAIT_REL: |
begin |
load_rel_ack = rel_req; |
end |
REL_DELAY1: |
begin |
end |
REL_DELAY2: |
begin |
end |
REL_WR2FL: |
begin |
sm_rel_wren = 1'b1; |
load_rel_ack = ll_q[0]; |
end |
endcase |
end |
|
always @ (posedge clk, negedge reset_n) |
begin |
if (reset_n==1'b0) |
begin |
cs_rd_sm <= 3'd0; |
rden_r1 <= 1'b0; |
int_rden_r1 <= 1'b0; |
load_req_r1 <= 1'b0; |
ll_rd_addr <= {FL_ADDR_W{1'b0}}; |
ram_rd_addr <= {RAM_ADDR_W{1'b0}}; |
usr_ram_rd_addr_r1 <= {RAM_ADDR_W{1'b0}}; |
fl_wren <= 1'b0; |
fl_data <= {FL_W{1'b0}}; |
end |
else |
begin |
cs_rd_sm <= ns_rd_sm; |
rden_r1 <= rden; |
int_rden_r1 <= int_rden; |
load_req_r1 <= load_req; |
|
ll_rd_addr <= load_req_p || rel_req_from_idle ? chunk_num : |
sm_rel_wren || ((!sm_rel_ctrl && rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)))) ? nxt_chunk_ptr : |
ll_rd_addr; |
ram_rd_addr <= load_req_p ? {chunk_num, {IN_CNK_ADDR_W{1'b0}}} : |
rden && (ram_rd_addr[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1)) ? {nxt_chunk_ptr, {IN_CNK_ADDR_W{1'b0}}} : |
rden || int_rden ? ram_rd_addr + 1'b1 : |
ram_rd_addr; |
usr_ram_rd_addr_r1 <= !sm_rel_ctrl && (rden || int_rden) ? ram_rd_addr : usr_ram_rd_addr_r1; |
fl_wren <= (!sm_rel_ctrl && rden && (usr_ram_rd_addr_r1[IN_CNK_ADDR_W-1:0]==(LINES_IN_CNK-1))) || sm_rel_wren ? 1'b1 : 1'b0; |
fl_data <= rel_req_from_idle ? chunk_num : |
sm_rel_wren ? ll_rd_addr : |
usr_ram_rd_addr_r1[RAM_ADDR_W-1:IN_CNK_ADDR_W]; |
|
end |
end |
|
/******************************************************** |
clog2 - function that returns log2 of a value rounded up |
- min return value is 1 (in case of clog2(1)=1) |
********************************************************/ |
function integer clog2(input integer value); |
begin |
value = value-1; |
for (clog2=0; value>0; clog2=clog2+1) |
value = value>>1; |
if (clog2 == 0) |
clog2 = 1; |
end |
endfunction |
|
endmodule |
/open_free_list/trunk/docs/open_free_list.html
0,0 → 1,246
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
<html> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=windows-1255"> |
<title>Open FreeList Readme</title> |
</head> |
<body> |
<h1>General Description</h1> |
<p> |
The Open FreeList module is used to manage a set of variable sized packets inside a fixed memory block. |
The memory block is partitioned into fixed sized chunks and each packet uses one or more chunks. |
The module offers three possible actions: |
<ol> |
<li>Write a packet into memory</li> |
<li>Read a packet from memory</li> |
<li>Release a packet</li> |
</ol> |
</p> |
<h1>Using the Module</h1> |
<h2>Parameters</h2> |
<table border="1"> |
<col align="left"/> |
<col align="left"/> |
<col align="center"/> |
<col align="center"/> |
<tr> |
<th>Name</th> |
<th>Description</th> |
<th>Unit</th> |
<th>Default Value</th> |
</tr> |
<tr> |
<td>RAM_W</td> |
<td>Memory block width</td> |
<td>bits</td> |
<td>128</td> |
</tr> |
<tr> |
<td>RAM_E</td> |
<td>Memory block extra data</td> |
<td>bits</td> |
<td>0</td> |
</tr> |
<tr> |
<td>RAM_S</td> |
<td>Memory block size</td> |
<td>KBytes</td> |
<td>64</td> |
</tr> |
<tr> |
<td>CHK_S</td> |
<td>Chunk size</td> |
<td>Bytes</td> |
<td>128</td> |
</tr> |
<tr> |
<td>RAM_TYPE</td> |
<td>Memory block type</td> |
<td>string</td> |
<td>"MRAM"</td> |
</tr> |
<tr> |
<td>FL_AEMPTY_LVL</td> |
<td>FreeList almost empty level</td> |
<td>#</td> |
<td>2</td> |
</tr> |
</table> |
<h2>Interface</h2> |
<table border="1"> |
<col align="left"/> |
<col align="center"/> |
<col align="center"/> |
<col align="left"/> |
<tr> |
<th>Name</th> |
<th>Direction</th> |
<th>Width</th> |
<th>Description</th> |
</tr> |
<tr> |
<td colspan="4" align="center"><b>global signals</b></td> |
</tr> |
<tr> |
<td>reset_n</td> |
<td>input</td> |
<td>1</td> |
<td>async reset (active low)</td> |
</tr> |
<tr> |
<td>clk</td> |
<td>input</td> |
<td>1</td> |
<td>clock</td> |
</tr> |
<tr> |
<td colspan="4" align="center"><b>write interface</b></td> |
</tr> |
<tr> |
<td>fl_q</td> |
<td>output</td> |
<td>clog(#_of_chunks)</td> |
<td>first chunk number for a new packet.<br />capture this value and use it to read/release the packet</td> |
</tr> |
<tr> |
<td>fl_aempty</td> |
<td>output</td> |
<td>1</td> |
<td>indicates that the number of chunks reached the almost empty level</td> |
</tr> |
<tr> |
<td>fl_empty</td> |
<td>output</td> |
<td>1</td> |
<td>no more chunks available. do not write any more</td> |
</tr> |
<tr> |
<td>wren</td> |
<td>input</td> |
<td>1</td> |
<td>write pulse. writes the data on din into the memory block</td> |
</tr> |
<tr> |
<td>din</td> |
<td>input</td> |
<td>RAM_W+RAM_E</td> |
<td>data to write into memory block</td> |
</tr> |
<tr> |
<td>eop</td> |
<td>input</td> |
<td>1</td> |
<td>end-of-packet indication. assert on last write of packet</td> |
</tr> |
<tr> |
<td colspan="4" align="center"><b>read interface</b></td> |
</tr> |
<tr> |
<td>chunk_num</td> |
<td>input</td> |
<td>clog(#_of_chunks)</td> |
<td>first chunk in a packet to be read or released</td> |
</tr> |
<tr> |
<td>load_req</td> |
<td>input</td> |
<td>1</td> |
<td>request to read a packet starting at chunk number 'chunk_num'</td> |
</tr> |
<tr> |
<td>rel_req</td> |
<td>input</td> |
<td>1</td> |
<td>request to release a packet starting at chunk number 'chunk_num'.<br />also required after a packet is read</td> |
</tr> |
<tr> |
<td>load_rel_ack</td> |
<td>output</td> |
<td>1</td> |
<td>acknowledge a read or release request</td> |
</tr> |
<tr> |
<td>rden</td> |
<td>input</td> |
<td>1</td> |
<td>read request. data on 'dout' is valid one clock later</td> |
</tr> |
<tr> |
<td>dout</td> |
<td>output</td> |
<td>RAM_W+RAM_E</td> |
<td>data read from memory block</td> |
</tr> |
</table> |
<h2>Operations</h2> |
<h3>Write</h3> |
<p> |
To write a packet, do the following: |
<ul> |
<li>make sure 'fl_empty' is de-asserted</li> |
<li>capture the value on 'fl_q'. it will be used later to reference this packet</li> |
<li>while 'fl_empty' is not asserted do:</li> |
<ul> |
<li>write the next data line in 'din'</li> |
<li>assert 'wren'</li> |
<li>on the last line of the packet, assert 'eop' as well</li> |
</ul> |
</ul> |
</p> |
<h3>Read</h3> |
<p> |
To read a packet that was previously written, do the following: |
<ul> |
<li>set 'chunk_num' to the value of the first chunk in the packet.<br /> |
this value was obtained from 'fl_q' when the packet was written</li> |
<li>assert 'load_req'</li> |
<li>when 'load_rel_ack' is asserted, for each line of data do:</li> |
<ul> |
<li>assert 'rden'</li> |
<li>capture 'dout' one cycle later</li> |
</ul> |
</ul> |
To determine the last line of data, you could: |
<ul> |
<li>store the packet length in an external structure</li> |
<li>use the extra bits in the memory block to hold an indication such as end-of-packet</li> |
</ul> |
</p> |
<p> |
Note that the 'eop' indication that is written in the write operation is not available on a read operation. |
</p> |
<p> |
<i>Important:</i> after a read is complete, a release operation must be explicitly performed. |
There is no need to set the 'chunk_num' value after a read operation. |
The chunks are released when the packet is read, but the last chunk requires an explicit release operation. |
</p> |
<h3>Release</h3> |
<p>A packet can be released under two circumstances: |
<ol> |
<li>when a read is complete, a release must be issued</li> |
<li>if a packet is not needed, it can be released without reading it</li> |
</ol> |
To release a packet, do the following: |
<ul> |
<li>set 'chunk_num' to the first chunk of the packet (not required after a read)</li> |
<li>assert 'rel_req'</li> |
<li>when 'load_rel_ack' is asserted, you are done</li> |
</ul> |
</p> |
<h2>Memories</h2> |
<p> |
Three memories are used in this module: |
<ol> |
<li>ram - dual port memory. two cycles to read</li> |
<li>free_list - single clock lookahead FIFO</li> |
<li>link_list - dual port memory. two cycles to read</li> |
</ol> |
The target architecture is Altera Sratix. There should be matching memory blocks in other architectures. |
</p> |
<p><br /><br /></p> |
<p> |
Code: Alex Manash - Crescendo Networks<br /> |
Docs: Amit Fridman - Crescendo Networks |
</p> |
</body> |
</html> |
/open_free_list/trunk/sim/vlog.list
0,0 → 1,4
../hdl/open_free_list.v |
tb_open_free_list.v |
altsyncram3.v |
alt_scfifo.v |
/open_free_list/trunk/sim/altsyncram3.v
0,0 → 1,108
/******************************************************************************* |
|
MODULE NAME: altsyncram3 |
|
DESCRIPTION |
This module is a parametrized dual port ram with a registered output port |
It is optional to define it's input address and output address and it's |
depth. |
|
REVISION HISTORY |
05FEB03 First Created -ac- |
*******************************************************************************/ |
module altsyncram3 |
( |
data, |
byteena, |
rd_aclr, |
rdaddress, |
rdclock, |
rdclocken, |
rden, |
wraddress, |
wrclock, |
wrclocken, |
wren, |
q); |
|
parameter A_WIDTH = 288; |
parameter A_WIDTHAD = 9; |
parameter B_WIDTH = A_WIDTH; |
parameter B_WIDTHAD = A_WIDTHAD; |
parameter A_NUMWORDS = 1<<A_WIDTHAD; |
parameter B_NUMWORDS = 1<<B_WIDTHAD; |
parameter RAM_TYPE = "AUTO"; |
parameter BYTE_ENA = 1; |
parameter USE_RDEN = 1; |
|
parameter TYPE = RAM_TYPE == "M4K" | RAM_TYPE == "M9K"? "M9K": |
RAM_TYPE == "M512" | RAM_TYPE == "MLAB"? "MLAB": |
RAM_TYPE == "M-RAM" | RAM_TYPE == "M144K"? "M144K": |
"AUTO"; |
|
parameter REG_B = "CLOCK1"; |
|
input [A_WIDTH-1:0] data; |
input [BYTE_ENA-1 :0] byteena; |
input rd_aclr; |
input [B_WIDTHAD-1:0] rdaddress; |
input rdclock; |
input rdclocken; |
input rden; |
input [A_WIDTHAD-1:0] wraddress; |
input wrclock; |
input wrclocken; |
input wren; |
output [B_WIDTH-1:0] q; |
|
wire [B_WIDTH-1:0] sub_wire0; |
wire [B_WIDTH-1:0] q = sub_wire0[B_WIDTH-1:0]; |
wire [BYTE_ENA-1 :0] byteena_wire = BYTE_ENA==1 ? 1'b1 : byteena; |
wire rden_wire = USE_RDEN ? rden : 1'b1; |
|
altsyncram altsyncram_component ( |
.clocken0(wrclocken), |
.clocken1(rdclocken), |
.wren_a(wren), |
.clock0(wrclock), |
.aclr1 (rd_aclr), |
.clock1(rdclock), |
.address_a(wraddress), |
.address_b(rdaddress), |
.rden_b(rden_wire), |
.data_a(data), |
.q_b(sub_wire0), |
.aclr0 (1'b0), |
.addressstall_a (1'b0), |
.addressstall_b (1'b0), |
.byteena_a (byteena_wire), |
.byteena_b (1'b1), |
.clocken2 (1'b1), |
.clocken3 (1'b1), |
.data_b ({B_WIDTH{1'b1}}), |
.eccstatus (), |
.q_a (), |
.rden_a (1'b1), |
.wren_b (1'b0)); |
defparam |
altsyncram_component.address_aclr_b = "CLEAR1", |
altsyncram_component.address_reg_b = "CLOCK1", |
altsyncram_component.clock_enable_input_a = "NORMAL", |
altsyncram_component.clock_enable_input_b = "NORMAL", |
altsyncram_component.clock_enable_output_b = "NORMAL", |
altsyncram_component.intended_device_family = "Stratix III", |
altsyncram_component.lpm_type = "altsyncram", |
altsyncram_component.numwords_a = A_NUMWORDS, |
altsyncram_component.numwords_b = B_NUMWORDS, |
altsyncram_component.operation_mode = "DUAL_PORT", |
altsyncram_component.outdata_aclr_b = "CLEAR1", |
altsyncram_component.outdata_reg_b = REG_B, |
altsyncram_component.power_up_uninitialized = "FALSE", |
altsyncram_component.ram_block_type = TYPE, |
altsyncram_component.rdcontrol_reg_b = "CLOCK1", |
altsyncram_component.widthad_a = A_WIDTHAD, |
altsyncram_component.widthad_b = B_WIDTHAD, |
altsyncram_component.width_a = A_WIDTH, |
altsyncram_component.width_b = B_WIDTH, |
altsyncram_component.width_byteena_a = BYTE_ENA; |
endmodule // altsyncram3 |
/open_free_list/trunk/sim/tb_open_free_list.v
0,0 → 1,186
`timescale 1ns/1ps |
|
module tb_open_free_list; |
|
reg reset_n; |
reg clk; |
wire [8:0] fl_q; |
wire fl_aempty; |
wire fl_empty; |
reg wren; |
reg [71:0] din; |
reg eop; |
reg [8:0] chunk_num; |
reg load_req; |
reg rel_req; |
wire load_rel_ack; |
reg rden; |
wire [71:0] dout; |
|
reg [8:0] pkt1_chunk; |
reg [8:0] pkt2_chunk; |
reg [8:0] pkt3_chunk; |
|
open_free_list open_free_list( |
.reset_n(reset_n), |
.clk(clk), |
.fl_q(fl_q), |
.fl_aempty(fl_aempty), |
.fl_empty(fl_empty), |
.wren(wren), |
.din(din), |
.eop(eop), |
.chunk_num(chunk_num), |
.load_req(load_req), |
.rel_req(rel_req), |
.load_rel_ack(load_rel_ack), |
.rden(rden), |
.dout(dout) |
); |
defparam |
open_free_list.RAM_W = 64, |
open_free_list.RAM_E = 8; |
|
initial // reset |
begin |
reset_n <= 1'b0; |
#1000 reset_n <= 1'b1; |
end |
|
initial // clock |
clk <= 1'b0; |
always |
#5 clk <= ~clk; |
|
initial // init all signals |
begin |
wren <= 1'b0; |
din <= 72'b0; |
eop <= 1'b0; |
chunk_num <= 9'b0; |
load_req <= 1'b0; |
rel_req <= 1'b0; |
rden <= 1'b0; |
end |
|
initial // test |
begin |
#2000; |
@(posedge clk); |
|
// write a short packet |
pkt1_chunk <= fl_q; |
din <= 72'h000001020304050607; |
wren <= 1'b1; |
@(posedge clk); |
din <= 72'h0108090a0b0c0d0e0f; |
eop <= 1'b1; |
@(posedge clk); |
wren <= 1'b0; |
eop <= 1'b0; |
|
#1000; |
@(posedge clk); |
|
// write a longer packet |
pkt2_chunk <= fl_q; |
din <= 72'h800001020304050607; |
wren <= 1'b1; |
@(posedge clk); |
din <= 72'h8008090a0b0c0d0e0f; |
@(posedge clk); |
din <= 72'h801011121314151617; |
@(posedge clk); |
din <= 72'h8018191a1b1c1d1e1f; |
@(posedge clk); |
din <= 72'h802021222324252627; |
@(posedge clk); |
din <= 72'h8028292a2b2c2d2e2f; |
@(posedge clk); |
din <= 72'h803031323334353637; |
@(posedge clk); |
din <= 72'h8038393a3b3c3d3e3f; |
@(posedge clk); |
din <= 72'h804041424344454647; |
@(posedge clk); |
din <= 72'h8048494a4b4c4d4e4f; |
@(posedge clk); |
din <= 72'h805051525354555657; |
@(posedge clk); |
din <= 72'h8058595a5b5c5d5e5f; |
@(posedge clk); |
din <= 72'h806061626364656667; |
@(posedge clk); |
din <= 72'h8068696a6b6c6d6e6f; |
@(posedge clk); |
din <= 72'h807071727374757677; |
@(posedge clk); |
din <= 72'h8078797a7b7c7d7e7f; |
@(posedge clk); |
din <= 72'h818081828384858687; |
eop <= 1'b1; |
@(posedge clk); |
wren <= 1'b0; |
eop <= 1'b0; |
|
#1000; |
@(posedge clk); |
|
// read the first packet |
chunk_num <= pkt1_chunk; |
load_req <= 1'b1; |
@(posedge load_rel_ack); |
load_req <= 1'b0; |
@(posedge clk); |
rden <= 1'b1; |
@(posedge clk); |
@(posedge clk); |
rden <= 1'b0; |
rel_req <= 1'b1; |
@(posedge load_rel_ack); |
rel_req <= 1'b0; |
|
#1000; |
@(posedge clk); |
|
// write a 3rd packet (short) |
pkt3_chunk <= fl_q; |
din <= 72'hc00001020304050607; |
wren <= 1'b1; |
@(posedge clk); |
din <= 72'hc108090a0b0c0d0e0f; |
eop <= 1'b1; |
@(posedge clk); |
wren <= 1'b0; |
eop <= 1'b0; |
|
#1000; |
@(posedge clk); |
|
// release the third packet without reading |
chunk_num <= pkt3_chunk; |
rel_req <= 1'b1; |
@(posedge load_rel_ack); |
rel_req <= 1'b0; |
|
#1000; |
@(posedge clk); |
|
// read a few lines of packet 2 and then release it |
chunk_num <= pkt2_chunk; |
load_req <= 1'b1; |
@(posedge load_rel_ack); |
load_req <= 1'b0; |
@(posedge clk); |
rden <= 1'b1; |
@(posedge clk); |
@(posedge clk); |
@(posedge clk); |
@(posedge clk); |
rden <= 1'b0; |
rel_req <= 1'b1; |
@(posedge load_rel_ack); |
rel_req <= 1'b0; |
end |
|
endmodule // tb_open_free_list |
/open_free_list/trunk/sim/vsim.list
0,0 → 1,6
-L /mnt/nfs/work/quartus_81/altera_mf |
-L /mnt/nfs/work/quartus_81/220model |
-L /mnt/nfs/work/quartus_81/stratixiii_atoms |
-L /mnt/nfs/work/quartus_81/sgate |
|
work.tb_open_free_list |
/open_free_list/trunk/sim/alt_scfifo.v
0,0 → 1,134
// megafunction wizard: %FIFO% |
// GENERATION: STANDARD |
// VERSION: WM1.0 |
// MODULE: scfifo |
|
// ============================================================ |
// File Name: sc_fifo.v |
// Megafunction Name(s): |
// scfifo |
// |
// Simulation Library Files(s): |
// altera_mf |
// ============================================================ |
// ************************************************************ |
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! |
// |
// 7.2 Build 175 11/20/2007 SP 1 SJ Full Version |
// ************************************************************ |
|
|
//Copyright (C) 1991-2007 Altera Corporation |
//Your use of Altera Corporation's design tools, logic functions |
//and other software and tools, and its AMPP partner logic |
//functions, and any output files from any of the foregoing |
//(including device programming or simulation files), and any |
//associated documentation or information are expressly subject |
//to the terms and conditions of the Altera Program License |
//Subscription Agreement, Altera MegaCore Function License |
//Agreement, or other applicable license agreement, including, |
//without limitation, that your use is for the sole purpose of |
//programming logic devices manufactured by Altera and sold by |
//Altera or its authorized distributors. Please refer to the |
//applicable agreement for further details. |
|
module alt_scfifo ( |
aclr, |
clock, |
data, |
rdreq, |
sclr, |
wrreq, |
almost_empty, |
almost_full, |
empty, |
full, |
q, |
usedw, |
fifo_ovf, |
fifo_unf |
); |
|
parameter FIFO_WIDTH = 144; |
parameter FIFO_DEPTH = 7; |
parameter FIFO_TYPE = "AUTO"; |
parameter FIFO_SHOW = "OFF"; |
parameter USE_EAB = "ON"; |
|
parameter FIFO_NUMWORDS = 1 << FIFO_DEPTH; |
parameter FIFO_AEMPTY = 0; |
parameter FIFO_AFULL = FIFO_NUMWORDS; |
parameter FIFO_UNF = "TRUE"; |
|
parameter TYPE = FIFO_TYPE == "M4K" | FIFO_TYPE == "M9K" ? "RAM_BLOCK_TYPE=M9K": |
FIFO_TYPE == "M512" | FIFO_TYPE == "MLAB" ? "RAM_BLOCK_TYPE=MLAB": |
FIFO_TYPE == "M-RAM" | FIFO_TYPE == "M144K"? "RAM_BLOCK_TYPE=M144K": |
"RAM_BLOCK_TYPE=AUTO"; |
|
input aclr; |
input clock; |
input [FIFO_WIDTH-1:0] data; |
input rdreq; |
input sclr; |
input wrreq; |
output almost_empty; |
output almost_full; |
output empty; |
output full; |
output [FIFO_WIDTH-1:0] q; |
output [FIFO_DEPTH-1:0] usedw; |
output fifo_ovf; |
output fifo_unf; |
|
reg fifo_ovf; |
reg fifo_unf; |
|
always @ (posedge clock or posedge aclr) |
if (aclr) begin |
fifo_ovf <= 1'b0; |
fifo_unf <= 1'b0; |
end |
else begin |
// synthesis translate_off |
if (fifo_ovf) begin |
$display ("%m: ERROR!!! %m alt_scfifo FIFO overflow, simulation stop"); |
$stop; |
end |
if (fifo_unf & (FIFO_UNF == "TRUE")) begin |
$display ("%m: ERROR!!! alt_dcfifo FIFO underflow, simulation stop"); |
$stop; |
end |
// synthesis translate_on |
fifo_ovf <= (full & wrreq) | fifo_ovf; |
fifo_unf <= ((empty & rdreq) | fifo_unf) & (FIFO_UNF == "TRUE"); |
end |
|
scfifo scfifo_component ( |
.rdreq (rdreq), |
.sclr (sclr), |
.aclr (aclr), |
.clock (clock), |
.wrreq (wrreq), |
.data (data), |
.almost_full (almost_full), |
.usedw (usedw), |
.empty (empty), |
.almost_empty(almost_empty), |
.q (q), |
.full (full) |
); |
defparam |
scfifo_component.add_ram_output_register = "ON", |
scfifo_component.almost_empty_value = FIFO_AEMPTY, |
scfifo_component.almost_full_value = FIFO_AFULL, |
scfifo_component.intended_device_family = "Stratix III", |
scfifo_component.lpm_hint = TYPE, |
scfifo_component.lpm_numwords = FIFO_NUMWORDS, |
scfifo_component.lpm_showahead = FIFO_SHOW, |
scfifo_component.lpm_type = "scfifo", |
scfifo_component.lpm_width = FIFO_WIDTH, |
scfifo_component.lpm_widthu = FIFO_DEPTH, |
scfifo_component.overflow_checking = "ON", |
scfifo_component.underflow_checking = "ON", |
scfifo_component.use_eab = USE_EAB; |
endmodule // alt_scfifo |