📄 220model.v
字号:
parameter lpm_widthad = 1 ;
parameter lpm_numwords = 1<< lpm_widthad ;
parameter lpm_address_control = "REGISTERED" ;
parameter lpm_outdata = "REGISTERED" ;
parameter lpm_file = "rom.hex" ;
parameter lpm_hint = "UNUSED" ;
input [lpm_widthad-1:0] address ;
input inclock, outclock ;
input memenab ;
output [lpm_width-1:0] q;
// inernal reg
reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
reg [lpm_widthad-1:0] paddress ;
reg [lpm_width-1:0] tmp_q ;
reg [lpm_width-1:0] tmp_q_reg ;
reg [lpm_width-1:0] ZEROS, UNKNOWN, HiZ ;
reg [8*256:1] rom_initf ;
integer i ;
function ValidAddress ;
input [lpm_widthad-1:0] address ;
begin
ValidAddress = 1'b0 ;
if(^address =='bx)
$display("%d:Error: Invalid address.", $time) ;
else if(address >= lpm_numwords)
$display("%d:Error: Address out of bound on ROM.", $time) ;
else
ValidAddress = 1'b1 ;
end
endfunction
initial
begin
// Initialize output
tmp_q = 0;
tmp_q_reg = 0;
paddress = 0;
if(lpm_file === "")
$display("Error! rom module must have data file for initialization\n.");
if(lpm_width <= 0)
$display("Error! lpm_width parameter must be greater than 0.");
if(lpm_widthad <= 0)
$display("Error! lpm_widthad parameter must be greater than 0.");
// check for number of words out of bound
if((lpm_numwords > (1 << lpm_widthad))
||(lpm_numwords <= (1 << (lpm_widthad-1))))
begin
$display("Error! lpm_numwords must equal to the ceiling of log2(lpm_widthad).");
end
if((lpm_address_control !== "REGISTERED") && (lpm_address_control !== "UNREGISTERED"))
begin
$display("Error! lpm_address_control must be REGISTERED (the default) or UNREGISTERED.");
end
if((lpm_outdata !== "REGISTERED") && (lpm_outdata !== "UNREGISTERED"))
begin
$display("Error! lpm_outdata must be REGISTERED (the default) or UNREGISTERED.");
end
// check if lpm_address_control is set to registered
// inclock must be used.
if((lpm_address_control === "REGISTERED") && (inclock === 1'bz))
begin
$display("Error! inclock = 1'bz. Inclock pin must be used.\n");
end
// check if lpm_outdata, outclock must be used
if((lpm_outdata === "REGISTERED") && (outclock === 1'bz))
begin
$display("Error! lpm_outdata is REGISTERED, outclock = 1'bz. Outclock must be used.\n");
end
for(i=0; i < lpm_width; i=i+1)
begin
ZEROS[i] = 1'b0 ;
UNKNOWN[i] = 1'bX ;
HiZ[i] = 1'bZ ;
end
for(i = 0; i < lpm_numwords; i=i+1)
mem_data[i] = ZEROS ;
// load data to the ROM
if(lpm_file != "")
begin
$convert_hex2ver(lpm_file, lpm_width, rom_initf);
$readmemh(rom_initf, mem_data);
end
end
always @(posedge inclock)
begin
if(lpm_address_control === "REGISTERED")
paddress <= address;
end
always @(address)
begin
if(lpm_address_control === "UNREGISTERED")
paddress <= address;
end
always @( paddress )
begin
if(ValidAddress(paddress))
begin
if(lpm_outdata === "UNREGISTERED")
tmp_q_reg <= mem_data[paddress] ;
end
else
begin
if(lpm_outdata === "UNREGISTERED")
tmp_q_reg <= UNKNOWN ;
end
end
always @(posedge outclock)
begin
if(lpm_outdata === "REGISTERED")
begin
if(ValidAddress(paddress))
tmp_q_reg <= mem_data[paddress] ;
else
tmp_q_reg <= UNKNOWN ;
end
end
always @(memenab or tmp_q_reg)
begin
if(memenab)
tmp_q <= tmp_q_reg ;
else if(!memenab)
tmp_q <= HiZ ;
end
assign q = tmp_q ;
endmodule // lpm_rom
//------------------------------------------------------------------------
module lpm_fifo (data, clock, wrreq, rdreq, aclr, sclr, q, usedw, full, empty);
parameter lpm_type = "lpm_fifo" ;
parameter lpm_width = 1 ;
parameter lpm_widthu = 1 ;
parameter lpm_numwords = 2 ;
parameter lpm_showahead = "OFF" ;
parameter lpm_hint = "UNUSED" ;
input [lpm_width-1:0] data;
input clock;
input wrreq;
input rdreq;
input aclr;
input sclr;
output [lpm_width-1:0] q;
output [lpm_widthu-1:0] usedw;
output full;
output empty;
// internal reg
reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
reg [lpm_width-1:0] tmp_q;
reg [lpm_width-1:0] ZEROS;
reg [lpm_widthu+1:0] count_id;
reg [lpm_widthu-1:0] write_id;
reg [lpm_widthu-1:0] read_id;
reg empty_flag;
reg full_flag;
integer i;
initial
begin
if(lpm_width <= 0)
$display("Error! lpm_width must be greater than 0.");
if(lpm_numwords <= 1)
$display("Error! lpm_numwords must be greater than or equal to 2.");
// check for number of words out of bound
if ((lpm_widthu !=1 ) && (lpm_numwords > (1 << lpm_widthu)))
$display("Error! lpm_numwords MUST equal to the ceiling of log2(lpm_widthu).");
if (lpm_numwords <= (1 << (lpm_widthu-1)))
begin
$display("Error! lpm_widthu is too big for the specified lpm_numwords.");
end
for (i=0; i < lpm_width; i=i+1)
ZEROS[i] = 1'b0;
for (i=0; i < lpm_widthu; i=i+1)
begin
count_id[i] = 1'b0;
write_id[i] = 1'b0;
read_id[i] = 1'b0;
end
for(i = 0; i < lpm_numwords; i=i+1)
mem_data[i] = ZEROS;
empty_flag = 1;
full_flag = 0;
end
always @( posedge clock )
if(lpm_showahead == "ON" && clock && aclr)
tmp_q = data;
always @( posedge clock or aclr )
begin
if (aclr)
begin
if (lpm_showahead != "ON")
tmp_q = ZEROS;
full_flag = 0;
empty_flag = 1;
read_id = 0;
write_id = 0;
count_id = 0;
end
else
if (clock)
begin
if (sclr)
begin
//tmp_q = ZEROS;
if (rdreq && !empty)
tmp_q = mem_data[read_id];
if (lpm_showahead == "ON" && rdreq)
tmp_q = data;
full_flag = 0;
empty_flag = 1;
read_id = 0;
write_id = 0;
count_id = 0;
end
else
begin
// WRITE
if (wrreq && !full)
begin
mem_data[write_id] = data;
if (lpm_showahead == "ON")
tmp_q = mem_data[read_id];
count_id = count_id + 1;
if (write_id == lpm_numwords - 1)
write_id = 0;
else
write_id = write_id + 1;
end
// READ
if (rdreq && !empty)
begin
tmp_q = mem_data[read_id];
count_id = count_id - 1;
if (read_id == lpm_numwords - 1 )
read_id = 0;
else
read_id = read_id + 1;
if (lpm_showahead == "ON")
tmp_q = mem_data[read_id];
end
if (!(wrreq && !full) && !(rdreq && !empty))
if (lpm_showahead == "ON" && empty)
tmp_q = data;
if(count_id == lpm_numwords)
full_flag = 1;
else
full_flag = 0;
if(count_id == 0)
begin
empty_flag = 1;
if (lpm_showahead == "ON")
tmp_q = data;
end
else
empty_flag = 0;
end
end
end
//assign q = (lpm_showahead == "ON") ? mem_data[read_id] : tmp_q;
assign q = tmp_q;
assign full = full_flag;
assign empty = empty_flag;
assign usedw = count_id;
endmodule // lpm_fifo
//------------------------------------------------------------------------
module lpm_fifo_dc (data, rdclock, wrclock, aclr, rdreq, wrreq, rdfull, wrfull, rdempty, wrempty, rdusedw, wrusedw, q );
parameter lpm_type = "lpm_fifo_dc" ;
parameter lpm_width = 1 ;
parameter lpm_widthu = 1 ;
parameter lpm_numwords = 2 ;
parameter lpm_showahead = "OFF" ;
parameter lpm_hint = "UNUSED" ;
input [lpm_width-1:0] data;
input rdclock;
input wrclock;
input wrreq;
input rdreq;
input aclr;
output rdfull;
output wrfull;
output rdempty;
output wrempty;
output [lpm_width-1:0] q;
output [lpm_widthu-1:0] rdusedw;
output [lpm_widthu-1:0] wrusedw;
// internal reg
reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
reg [lpm_width-1:0] tmp_q;
reg [lpm_width-1:0] ZEROS;
reg [lpm_widthu-1:0] wrcount_id;
reg [lpm_widthu-1:0] rdcount_id;
reg [lpm_widthu-1:0] ZEROSU;
integer count_id;
integer write_id;
integer read_id;
integer wrempty_count;
integer rdempty_count;
reg wrempty_flag;
reg wrfull_flag;
reg wrfull_f2;
reg tmp_wrfull_flag;
reg tmp_wrempty_flag;
reg rdempty_flag;
reg rdfull_flag;
reg rdfull_f2;
reg tmp_rdempty_flag;
integer i;
initial
begin
if(lpm_width <= 0)
$display("Error! lpm_width must be greater than 0.");
if(lpm_numwords <= 1)
$display("Error! lpm_numwords must be greater than or equal to 2.");
// check for number of words out of bound
if ((lpm_widthu !=1 ) && (lpm_numwords > (1 << lpm_widthu)))
$display("Error! lpm_numwords MUST equal to the ceiling of log2(lpm_widthu).");
if (lpm_numwords <= (1 << (lpm_widthu-1)))
$display("Error! lpm_widthu is too big for the specified lpm_numwords.");
for (i=0; i < lpm_width; i=i+1)
ZEROS[i] = 1'b0;
for (i=0; i < lpm_widthu; i=i+1)
ZEROSU[i] = 1'b0;
// MEMORY INITIALIZATION
for(i = 0; i < lpm_numwords; i=i+1)
mem_data[i] = ZEROS;
count_id = 0;
write_id = 0;
read_id = 0;
wrcount_id = ZEROSU;
rdcount_id = ZEROSU;
wrempty_flag = 1;
rdempty_flag = 1;
wrfull_flag = 0;
rdfull_flag = 0;
wrfull_f2 = 0;
rdfull_f2 = 0;
wrempty_count = 0;
rdempty_count = 0;
end
always @( aclr )
begin
if (aclr)
begin
tmp_q = ZEROS;
rdfull_flag = 0;
rdempty_flag = 1;
wrfull_flag = 0;
wrempty_flag = 1;
read_id = 0;
write_id = 0;
count_id = 0;
rdcount_id = 0;
wrcount_id = 0;
end
end
always @( posedge wrclock )
begin
if (!aclr)
begin
// PREPARE FLAGS FOR DELAY
tmp_wrfull_flag = wrfull_flag;
// SET EMPTY FLAG
if (wrempty_flag == 1 && wrcount_id > 0)
begin
wrempty_flag = 0;
wrempty_count = 0;
end
else if (wrempty_flag == 0 && wrcount_id == 0)
begin
if (wrempty_count < 1)
wrempty_count = wrempty_count + 1;
else
begin
wrempty_flag = 1;
wrempty_count = 0;
end
end
else
wrempty_count = 0;
// SET FULL FLAG
tmp_wrfull_flag = wrfull_f2;
wrfull_f2 = (wrcount_id >= lpm_numwords-3) ? 1 : 0;
// SET COUNTER
wrcount_id = count_id;
// if WRITE
if (wrreq && !wrfull_flag)
begin
// WRITE DATA
mem_data[write_id] = data;
// SET OUTPUT
if (lpm_showahead == "ON")
tmp_q = mem_data[read_id];
// SET FLAGS
wrempty_flag = 0;
wrempty_count = 0;
// INC COUNTER
wrcount_id = count_id + 1;
count_id = count_id + 1;
// INC POINTER
write_id = (write_id < lpm_numwords-1) ? write_id+1 : 0;
end
// SET DELAYED FLAGS
wrfull_flag = tmp_wrfull_flag;
end
end
always @( posedge rdclock )
begin
if (!aclr)
begin
// PREPARE FLAGS FOR DELAY
tmp_rdempty_flag = rdempty_flag;
// SET EMPTY FLAG
if (rdempty_flag == 1 && rdcount_id > 0)
begin
if (rdempty_count >= 0)
rdempty_count = rdempty_count - 1;
else
begin
tmp_rdempty_flag = 0;
rdempty_count = 0;
end
end
else if (rdempty_flag == 0 && rdcount_id == 0)
begin
tmp_rdempty_flag = 1;
rdempty_count = 0;
end
else
rdempty_count = 0;
// SET FULL FLAG
rdfull_flag = rdfull_f2;
rdfull_f2 = (rdcount_id >= lpm_numwords-3) ? 1 : 0;
// SET COUNTER
rdcount_id = count_id;
// if READ
if (rdreq && !rdempty_flag)
begin
// READ DATA/SET OUTPUT
tmp_q = mem_data[read_id];
// SET FLAGS
if (count_id-1 ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -