forked from github/verilator
6782 lines
233 KiB
Systemverilog
6782 lines
233 KiB
Systemverilog
//-------------------------------------------------------------------------
|
|
// This Verilog file was developed by Altera Corporation. It may be
|
|
// freely copied and/or distributed at no cost. Any persons using this
|
|
// file for any purpose do so at their own risk, and are responsible for
|
|
// the results of such use. Altera Corporation does not guarantee that
|
|
// this file is complete, correct, or fit for any particular purpose.
|
|
// NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must
|
|
// accompany any copy of this file.
|
|
//------------------------------------------------------------------------
|
|
//
|
|
// Quartus Prime 16.1.0 Build 196 10/24/2016
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// LPM Synthesizable Models (Support string type generic)
|
|
// These models are based on LPM version 220 (EIA-IS103 October 1998).
|
|
//------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Assumptions:
|
|
//
|
|
// 1. The default value for LPM_SVALUE, LPM_AVALUE, LPM_PVALUE, and
|
|
// LPM_STRENGTH is string UNUSED.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// Verilog Language Issues:
|
|
//
|
|
// Two dimensional ports are not supported. Modules with two dimensional
|
|
// ports are implemented as one dimensional signal of (LPM_SIZE * LPM_WIDTH)
|
|
// bits wide.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : LPM_MEMORY_INITIALIZATION
|
|
//
|
|
// Description : Common function to read intel-hex format data file with
|
|
// extension .hex and creates the equivalent verilog format
|
|
// data file with extension .ver.
|
|
//
|
|
// Limitation : Supports only record type '00'(data record), '01'(end of
|
|
// file record) and '02'(extended segment address record).
|
|
//
|
|
// Results expected: Creates the verilog format data file with extension .ver
|
|
// and return the name of the file.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
//See also: https://github.com/twosigma/verilator_support
|
|
// verilator lint_off COMBDLY
|
|
// verilator lint_off INITIALDLY
|
|
// verilator lint_off MULTIDRIVEN
|
|
// verilator lint_off UNSIGNED
|
|
// verilator lint_off WIDTH
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
`define LPM_TRUE 1
|
|
`define LPM_FALSE 0
|
|
`define LPM_NULL 0
|
|
`define LPM_EOF -1
|
|
`define LPM_MAX_NAME_SZ 128
|
|
`define LPM_MAX_WIDTH 256
|
|
`define LPM_COLON ":"
|
|
`define LPM_DOT "."
|
|
`define LPM_NEWLINE "\n"
|
|
`define LPM_CARRIAGE_RETURN 8'h0D
|
|
`define LPM_SPACE " "
|
|
`define LPM_TAB "\t"
|
|
`define LPM_OPEN_BRACKET "["
|
|
`define LPM_CLOSE_BRACKET "]"
|
|
`define LPM_OFFSET 9
|
|
`define LPM_H10 8'h10
|
|
`define LPM_H10000 20'h10000
|
|
`define LPM_AWORD 8
|
|
`define LPM_MASK15 32'h000000FF
|
|
`define LPM_EXT_STR "ver"
|
|
`define LPM_PERCENT "%"
|
|
`define LPM_MINUS "-"
|
|
`define LPM_SEMICOLON ";"
|
|
`define LPM_EQUAL "="
|
|
|
|
// MODULE DECLARATION
|
|
module LPM_MEMORY_INITIALIZATION;
|
|
|
|
/****************************************************************/
|
|
/* convert uppercase character values to lowercase. */
|
|
/****************************************************************/
|
|
function [8:1] tolower;
|
|
input [8:1] given_character;
|
|
reg [8:1] conv_char;
|
|
|
|
begin
|
|
if ((given_character >= 65) && (given_character <= 90)) // ASCII number of 'A' is 65, 'Z' is 90
|
|
begin
|
|
conv_char = given_character + 32; // 32 is the difference in the position of 'A' and 'a' in the ASCII char set
|
|
tolower = conv_char;
|
|
end
|
|
else
|
|
tolower = given_character;
|
|
end
|
|
endfunction
|
|
|
|
/****************************************************************/
|
|
/* Read in Altera-mif format data to verilog format data. */
|
|
/****************************************************************/
|
|
task convert_mif2ver;
|
|
input[`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
input width;
|
|
output [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] buffer;
|
|
reg [`LPM_MAX_WIDTH : 0] memory_data1, memory_data2;
|
|
reg [8 : 1] c;
|
|
reg [3 : 0] hex, tmp_char;
|
|
reg [24 : 1] address_radix, data_radix;
|
|
reg get_width;
|
|
reg get_depth;
|
|
reg get_data_radix;
|
|
reg get_address_radix;
|
|
reg width_found;
|
|
reg depth_found;
|
|
reg data_radix_found;
|
|
reg address_radix_found;
|
|
reg get_address_data_pairs;
|
|
reg get_address;
|
|
reg get_data;
|
|
reg display_address;
|
|
reg invalid_address;
|
|
reg get_start_address;
|
|
reg get_end_address;
|
|
reg done;
|
|
reg error_status;
|
|
reg first_rec;
|
|
reg last_rec;
|
|
|
|
integer width;
|
|
integer memory_width, memory_depth;
|
|
integer value;
|
|
integer ifp, ofp, r, r2;
|
|
integer i, j, k, m, n;
|
|
|
|
integer off_addr, nn, address, tt, cc, aah, aal, dd, sum ;
|
|
integer start_address, end_address;
|
|
integer line_no;
|
|
integer character_count;
|
|
integer comment_with_percent_found;
|
|
integer comment_with_double_minus_found;
|
|
|
|
begin
|
|
done = `LPM_FALSE;
|
|
error_status = `LPM_FALSE;
|
|
first_rec = `LPM_FALSE;
|
|
last_rec = `LPM_FALSE;
|
|
comment_with_percent_found = `LPM_FALSE;
|
|
comment_with_double_minus_found = `LPM_FALSE;
|
|
|
|
off_addr= 0;
|
|
nn= 0;
|
|
address = 0;
|
|
start_address = 0;
|
|
end_address = 0;
|
|
tt= 0;
|
|
cc= 0;
|
|
aah= 0;
|
|
aal= 0;
|
|
dd= 0;
|
|
sum = 0;
|
|
line_no = 1;
|
|
c = 0;
|
|
hex = 0;
|
|
value = 0;
|
|
buffer = "";
|
|
character_count = 0;
|
|
memory_width = 0;
|
|
memory_depth = 0;
|
|
memory_data1 = {(`LPM_MAX_WIDTH+1) {1'b0}};
|
|
memory_data2 = {(`LPM_MAX_WIDTH+1) {1'b0}};
|
|
address_radix = "hex";
|
|
data_radix = "hex";
|
|
get_width = `LPM_FALSE;
|
|
get_depth = `LPM_FALSE;
|
|
get_data_radix = `LPM_FALSE;
|
|
get_address_radix = `LPM_FALSE;
|
|
width_found = `LPM_FALSE;
|
|
depth_found = `LPM_FALSE;
|
|
data_radix_found = `LPM_FALSE;
|
|
address_radix_found = `LPM_FALSE;
|
|
get_address_data_pairs = `LPM_FALSE;
|
|
display_address = `LPM_FALSE;
|
|
invalid_address = `LPM_FALSE;
|
|
get_start_address = `LPM_FALSE;
|
|
get_end_address = `LPM_FALSE;
|
|
|
|
if((in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT"))
|
|
out_file = in_file;
|
|
else
|
|
begin
|
|
ifp = $fopen(in_file, "r");
|
|
|
|
if (ifp == `LPM_NULL)
|
|
begin
|
|
$display("ERROR: cannot read %0s.", in_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
|
|
out_file = in_file;
|
|
|
|
if((out_file[4*8 : 1] == ".mif") || (out_file[4*8 : 1] == ".MIF"))
|
|
out_file[3*8 : 1] = `LPM_EXT_STR;
|
|
else
|
|
begin
|
|
$display("ERROR: Invalid input file name %0s. Expecting file with .mif extension and Altera-mif data format.", in_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
|
|
if (!done)
|
|
begin
|
|
ofp = $fopen(out_file, "w");
|
|
|
|
if (ofp == `LPM_NULL)
|
|
begin
|
|
$display("ERROR : cannot write %0s.", out_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
end
|
|
|
|
while((!done) && (!error_status))
|
|
begin : READER
|
|
|
|
r = $fgetc(ifp);
|
|
|
|
if (r == `LPM_EOF)
|
|
begin
|
|
// to do : add more checking on whether a particular assigment(width, depth, memory/address) are mising
|
|
if(!first_rec)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("WARNING: %0s, Intel-hex data file is empty.", in_file);
|
|
$display ("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if (!get_address_data_pairs)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if(!last_rec)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Missing `end` statement.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
done = `LPM_TRUE;
|
|
end
|
|
else if ((r == `LPM_NEWLINE) || (r == `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
if ((buffer == "contentbegin") && (get_address_data_pairs == `LPM_FALSE))
|
|
begin
|
|
get_address_data_pairs = `LPM_TRUE;
|
|
get_address = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else if (buffer == "content")
|
|
begin
|
|
// continue to next character
|
|
end
|
|
else
|
|
if (buffer != "")
|
|
begin
|
|
// found invalid syntax in the particular line.
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
disable READER;
|
|
end
|
|
line_no = line_no +1;
|
|
|
|
end
|
|
else if ((r == `LPM_SPACE) || (r == `LPM_TAB))
|
|
begin
|
|
// continue to next character;
|
|
end
|
|
else if (r == `LPM_PERCENT)
|
|
begin
|
|
// Ignore all the characters which which is part of comment.
|
|
r = $fgetc(ifp);
|
|
|
|
while ((r != `LPM_PERCENT) && (r != `LPM_NEWLINE) && (r != `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
r = $fgetc(ifp);
|
|
end
|
|
|
|
if ((r == `LPM_NEWLINE) || (r == `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
line_no = line_no +1;
|
|
|
|
if ((buffer == "contentbegin") && (get_address_data_pairs == `LPM_FALSE))
|
|
begin
|
|
get_address_data_pairs = `LPM_TRUE;
|
|
get_address = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
end
|
|
end
|
|
else if (r == `LPM_MINUS)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
if (r == `LPM_MINUS)
|
|
begin
|
|
// Ignore all the characters which which is part of comment.
|
|
r = $fgetc(ifp);
|
|
|
|
while ((r != `LPM_NEWLINE) && (r != `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
end
|
|
|
|
if ((r == `LPM_NEWLINE) || (r == `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
line_no = line_no +1;
|
|
|
|
if ((buffer == "contentbegin") && (get_address_data_pairs == `LPM_FALSE))
|
|
begin
|
|
get_address_data_pairs = `LPM_TRUE;
|
|
get_address = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
else if (r == `LPM_EQUAL)
|
|
begin
|
|
if (buffer == "width")
|
|
begin
|
|
if (width_found == `LPM_FALSE)
|
|
begin
|
|
get_width = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Width has already been specified once.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if (buffer == "depth")
|
|
begin
|
|
get_depth = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else if (buffer == "data_radix")
|
|
begin
|
|
get_data_radix = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else if (buffer == "address_radix")
|
|
begin
|
|
get_address_radix = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Unknown setting (%0s).", in_file, line_no, buffer);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if (r == `LPM_COLON)
|
|
begin
|
|
if (!get_address_data_pairs)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if (invalid_address == `LPM_TRUE)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
begin
|
|
get_address = `LPM_FALSE;
|
|
get_data = `LPM_TRUE;
|
|
display_address = `LPM_TRUE;
|
|
end
|
|
end
|
|
else if (r == `LPM_DOT)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
if (r == `LPM_DOT)
|
|
begin
|
|
if (get_start_address == `LPM_TRUE)
|
|
begin
|
|
start_address = address;
|
|
address = 0;
|
|
get_start_address = `LPM_FALSE;
|
|
get_end_address = `LPM_TRUE;
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
else if (r == `LPM_OPEN_BRACKET)
|
|
begin
|
|
get_start_address = `LPM_TRUE;
|
|
end
|
|
else if (r == `LPM_CLOSE_BRACKET)
|
|
begin
|
|
if (get_end_address == `LPM_TRUE)
|
|
begin
|
|
end_address = address;
|
|
address = 0;
|
|
get_end_address = `LPM_FALSE;
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid Altera-mif record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
else if (r == `LPM_SEMICOLON)
|
|
begin
|
|
if (get_width == `LPM_TRUE)
|
|
begin
|
|
width_found = `LPM_TRUE;
|
|
memory_width = value;
|
|
value = 0;
|
|
get_width = `LPM_FALSE;
|
|
end
|
|
else if (get_depth == `LPM_TRUE)
|
|
begin
|
|
depth_found = `LPM_TRUE;
|
|
memory_depth = value;
|
|
value = 0;
|
|
get_depth = `LPM_FALSE;
|
|
end
|
|
else if (get_data_radix == `LPM_TRUE)
|
|
begin
|
|
data_radix_found = `LPM_TRUE;
|
|
get_data_radix = `LPM_FALSE;
|
|
|
|
if ((buffer == "bin") || (buffer == "oct") || (buffer == "dec") || (buffer == "uns") ||
|
|
(buffer == "hex"))
|
|
begin
|
|
data_radix = buffer[24 : 1];
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid assignment (%0s) to data_radix.", in_file, line_no, buffer);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
buffer = "";
|
|
end
|
|
else if (get_address_radix == `LPM_TRUE)
|
|
begin
|
|
address_radix_found = `LPM_TRUE;
|
|
get_address_radix = `LPM_FALSE;
|
|
|
|
if ((buffer == "bin") || (buffer == "oct") || (buffer == "dec") || (buffer == "uns") ||
|
|
(buffer == "hex"))
|
|
begin
|
|
address_radix = buffer[24 : 1];
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid assignment (%0s) to address radix.", in_file, line_no, buffer);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
buffer = "";
|
|
end
|
|
else if (buffer == "end")
|
|
begin
|
|
if (get_address_data_pairs == `LPM_TRUE)
|
|
begin
|
|
last_rec = `LPM_TRUE;
|
|
buffer = "";
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Missing `content begin` statement.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if (get_data == `LPM_TRUE)
|
|
begin
|
|
get_address = `LPM_TRUE;
|
|
get_data = `LPM_FALSE;
|
|
buffer = "";
|
|
character_count = 0;
|
|
|
|
if (start_address != end_address)
|
|
begin
|
|
for (address = start_address; address <= end_address; address = address+1)
|
|
begin
|
|
$fdisplay(ofp,"@%0h", address);
|
|
|
|
for (i = memory_width -1; i >= 0; i = i-1 )
|
|
begin
|
|
hex[(i % 4)] = memory_data1[i];
|
|
|
|
if ((i % 4) == 0)
|
|
begin
|
|
$fwrite(ofp, "%0h", hex);
|
|
hex = 0;
|
|
end
|
|
end
|
|
|
|
$fwrite(ofp, "\n");
|
|
end
|
|
start_address = 0;
|
|
end_address = 0;
|
|
address = 0;
|
|
hex = 0;
|
|
memory_data1 = {(`LPM_MAX_WIDTH+1) {1'b0}};
|
|
end
|
|
else
|
|
begin
|
|
if (display_address == `LPM_TRUE)
|
|
begin
|
|
$fdisplay(ofp,"@%0h", address);
|
|
display_address = `LPM_FALSE;
|
|
end
|
|
|
|
for (i = memory_width -1; i >= 0; i = i-1 )
|
|
begin
|
|
hex[(i % 4)] = memory_data1[i];
|
|
|
|
if ((i % 4) == 0)
|
|
begin
|
|
$fwrite(ofp, "%0h", hex);
|
|
hex = 0;
|
|
end
|
|
end
|
|
|
|
$fwrite(ofp, "\n");
|
|
address = 0;
|
|
hex = 0;
|
|
memory_data1 = {(`LPM_MAX_WIDTH+1) {1'b0}};
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid assigment.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if ((get_width == `LPM_TRUE) || (get_depth == `LPM_TRUE))
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (value * 10) + (r - 'h30);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid assignment to width/depth.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if (get_address == `LPM_TRUE)
|
|
begin
|
|
if (address_radix == "hex")
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
value = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
value = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
invalid_address = `LPM_TRUE;
|
|
end
|
|
|
|
address = (address * 16) + value;
|
|
end
|
|
else if ((address_radix == "dec"))
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
invalid_address = `LPM_TRUE;
|
|
end
|
|
|
|
address = (address * 10) + value;
|
|
end
|
|
else if (address_radix == "uns")
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
invalid_address = `LPM_TRUE;
|
|
end
|
|
|
|
address = (address * 10) + value;
|
|
end
|
|
else if (address_radix == "bin")
|
|
begin
|
|
if ((r >= "0") && (r <= "1"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
invalid_address = `LPM_TRUE;
|
|
end
|
|
|
|
address = (address * 2) + value;
|
|
end
|
|
else if (address_radix == "oct")
|
|
begin
|
|
if ((r >= "0") && (r <= "7"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
invalid_address = `LPM_TRUE;
|
|
end
|
|
|
|
address = (address * 8) + value;
|
|
end
|
|
|
|
if ((r >= 65) && (r <= 90))
|
|
c = tolower(r);
|
|
else
|
|
c = r;
|
|
|
|
{tmp_char,buffer} = {buffer, c};
|
|
end
|
|
else if (get_data == `LPM_TRUE)
|
|
begin
|
|
character_count = character_count +1;
|
|
|
|
if (data_radix == "hex")
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
value = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
value = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
memory_data1 = (memory_data1 * 16) + value;
|
|
end
|
|
else if ((data_radix == "dec"))
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
memory_data1 = (memory_data1 * 10) + value;
|
|
end
|
|
else if (data_radix == "uns")
|
|
begin
|
|
if ((r >= "0") && (r <= "9"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
memory_data1 = (memory_data1 * 10) + value;
|
|
end
|
|
else if (data_radix == "bin")
|
|
begin
|
|
if ((r >= "0") && (r <= "1"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
memory_data1 = (memory_data1 * 2) + value;
|
|
end
|
|
else if (data_radix == "oct")
|
|
begin
|
|
if ((r >= "0") && (r <= "7"))
|
|
value = (r - 'h30);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
memory_data1 = (memory_data1 * 8) + value;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
first_rec = `LPM_TRUE;
|
|
|
|
if ((r >= 65) && (r <= 90))
|
|
c = tolower(r);
|
|
else
|
|
c = r;
|
|
|
|
{tmp_char,buffer} = {buffer, c};
|
|
end
|
|
end
|
|
$fclose(ifp);
|
|
$fclose(ofp);
|
|
end
|
|
end
|
|
endtask // convert_mif2ver
|
|
|
|
/****************************************************************/
|
|
/* Read in Intel-hex format data to verilog format data. */
|
|
/* Intel-hex format :nnaaaaattddddcc */
|
|
/****************************************************************/
|
|
task convert_hex2ver;
|
|
input[`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
input width;
|
|
output [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
reg [8:1] c;
|
|
reg [3:0] hex, tmp_char;
|
|
reg done;
|
|
reg error_status;
|
|
reg first_rec;
|
|
reg last_rec;
|
|
|
|
integer width;
|
|
integer ifp, ofp, r, r2;
|
|
integer i, j, k, m, n;
|
|
|
|
integer off_addr, nn, aaaa, tt, cc, aah, aal, dd, sum ;
|
|
integer line_no;
|
|
|
|
begin
|
|
done = `LPM_FALSE;
|
|
error_status = `LPM_FALSE;
|
|
first_rec = `LPM_FALSE;
|
|
last_rec = `LPM_FALSE;
|
|
|
|
off_addr= 0;
|
|
nn= 0;
|
|
aaaa= 0;
|
|
tt= 0;
|
|
cc= 0;
|
|
aah= 0;
|
|
aal= 0;
|
|
dd= 0;
|
|
sum = 0;
|
|
line_no = 1;
|
|
c = 0;
|
|
hex = 0;
|
|
|
|
if((in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT"))
|
|
out_file = in_file;
|
|
else
|
|
begin
|
|
ifp = $fopen(in_file, "r");
|
|
if (ifp == `LPM_NULL)
|
|
begin
|
|
$display("ERROR: cannot read %0s.", in_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
|
|
out_file = in_file;
|
|
|
|
if((out_file[4*8 : 1] == ".hex") || (out_file[4*8 : 1] == ".HEX"))
|
|
out_file[3*8 : 1] = `LPM_EXT_STR;
|
|
else
|
|
begin
|
|
$display("ERROR: Invalid input file name %0s. Expecting file with .hex extension and Intel-hex data format.", in_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
|
|
if (!done)
|
|
begin
|
|
ofp = $fopen(out_file, "w");
|
|
if (ofp == `LPM_NULL)
|
|
begin
|
|
$display("ERROR : cannot write %0s.", out_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
end
|
|
|
|
while((!done) && (!error_status))
|
|
begin : READER
|
|
|
|
r = $fgetc(ifp);
|
|
|
|
if (r == `LPM_EOF)
|
|
begin
|
|
if(!first_rec)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("WARNING: %0s, Intel-hex data file is empty.", in_file);
|
|
$display ("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if(!last_rec)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Missing the last record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
else if (r == `LPM_COLON)
|
|
begin
|
|
first_rec = `LPM_TRUE;
|
|
nn= 0;
|
|
aaaa= 0;
|
|
tt= 0;
|
|
cc= 0;
|
|
aah= 0;
|
|
aal= 0;
|
|
dd= 0;
|
|
sum = 0;
|
|
|
|
// get record length bytes
|
|
for (i = 0; i < 2; i = i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
nn = (nn * 16) + (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
nn = (nn * 16) + 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
nn = (nn * 16) + 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
|
|
// get address bytes
|
|
for (i = 0; i < 4; i = i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
aaaa = (aaaa * 16) + hex;
|
|
|
|
if (i < 2)
|
|
aal = (aal * 16) + hex;
|
|
else
|
|
aah = (aah * 16) + hex;
|
|
end
|
|
|
|
// get record type bytes
|
|
for (i = 0; i < 2; i = i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
tt = (tt * 16) + (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
tt = (tt * 16) + 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
tt = (tt * 16) + 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
|
|
if((tt == 2) && (nn != 2) )
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid data record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else
|
|
begin
|
|
|
|
// get the sum of all the bytes for record length, address and record types
|
|
sum = nn + aah + aal + tt ;
|
|
|
|
// check the record type
|
|
case(tt)
|
|
// normal_record
|
|
8'h00 :
|
|
begin
|
|
first_rec = `LPM_TRUE;
|
|
i = 0;
|
|
k = width / `LPM_AWORD;
|
|
if ((width % `LPM_AWORD) != 0)
|
|
k = k + 1;
|
|
|
|
// k = no. of bytes per entry.
|
|
while (i < nn)
|
|
begin
|
|
$fdisplay(ofp,"@%0h", (aaaa + off_addr));
|
|
for (j = 1; j <= k; j = j +1)
|
|
begin
|
|
if ((k - j +1) > nn)
|
|
begin
|
|
for(m = 1; m <= 2; m= m+1)
|
|
begin
|
|
if((((k-j)*8) + ((3-m)*4) - width) < 4)
|
|
$fwrite(ofp, "0");
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
// get the data bytes
|
|
for(m = 1; m <= 2; m= m+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
if((((k-j)*8) + ((3-m)*4) - width) < 4)
|
|
$fwrite(ofp, "%h", hex);
|
|
dd = (dd * 16) + hex;
|
|
|
|
if(m % 2 == 0)
|
|
begin
|
|
sum = sum + dd;
|
|
dd = 0;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
$fwrite(ofp, "\n");
|
|
|
|
i = i + k;
|
|
aaaa = aaaa + 1;
|
|
end // end of while (i < nn)
|
|
end
|
|
// last record
|
|
8'h01:
|
|
begin
|
|
last_rec = `LPM_TRUE;
|
|
done = `LPM_TRUE;
|
|
end
|
|
// address base record
|
|
8'h02:
|
|
begin
|
|
off_addr= 0;
|
|
|
|
// get the extended segment address record
|
|
for(i = 1; i <= (nn*2); i= i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
off_addr = (off_addr * `LPM_H10) + hex;
|
|
dd = (dd * 16) + hex;
|
|
|
|
if(i % 2 == 0)
|
|
begin
|
|
sum = sum + dd;
|
|
dd = 0;
|
|
end
|
|
end
|
|
|
|
off_addr = off_addr * `LPM_H10;
|
|
end
|
|
// address base record
|
|
8'h03:
|
|
// get the start segment address record
|
|
for(i = 1; i <= (nn*2); i= i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
dd = (dd * 16) + hex;
|
|
|
|
if(i % 2 == 0)
|
|
begin
|
|
sum = sum + dd;
|
|
dd = 0;
|
|
end
|
|
end
|
|
// address base record
|
|
8'h04:
|
|
begin
|
|
off_addr= 0;
|
|
|
|
// get the extended linear address record
|
|
for(i = 1; i <= (nn*2); i= i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
|
|
off_addr = (off_addr * `LPM_H10) + hex;
|
|
dd = (dd * 16) + hex;
|
|
|
|
if(i % 2 == 0)
|
|
begin
|
|
sum = sum + dd;
|
|
dd = 0;
|
|
end
|
|
end
|
|
|
|
off_addr = off_addr * `LPM_H10000;
|
|
end
|
|
// address base record
|
|
8'h05:
|
|
// get the start linear address record
|
|
for(i = 1; i <= (nn*2); i= i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
hex = (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
hex = 10 + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
hex = 10 + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
dd = (dd * 16) + hex;
|
|
|
|
if(i % 2 == 0)
|
|
begin
|
|
sum = sum + dd;
|
|
dd = 0;
|
|
end
|
|
end
|
|
default:
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Unknown record type.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
endcase
|
|
|
|
// get the checksum bytes
|
|
for (i = 0; i < 2; i = i+1)
|
|
begin
|
|
r = $fgetc(ifp);
|
|
|
|
if ((r >= "0") && (r <= "9"))
|
|
cc = (cc * 16) + (r - 'h30);
|
|
else if ((r >= "A") && (r <= "F"))
|
|
cc = 10 + (cc * 16) + (r - 'h41);
|
|
else if ((r >= "a") && (r <= "f"))
|
|
cc = 10 + (cc * 16) + (r - 'h61);
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
disable READER;
|
|
end
|
|
end
|
|
|
|
// Perform check sum.
|
|
if(((~sum+1)& `LPM_MASK15) != cc)
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR: %0s, line %0d, Invalid checksum.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
end
|
|
else if ((r == `LPM_NEWLINE) || (r == `LPM_CARRIAGE_RETURN))
|
|
begin
|
|
line_no = line_no +1;
|
|
end
|
|
else if (r == `LPM_SPACE)
|
|
begin
|
|
// continue to next character;
|
|
end
|
|
else
|
|
begin
|
|
error_status = `LPM_TRUE;
|
|
$display("ERROR:%0s, line %0d, Invalid INTEL HEX record.", in_file, line_no);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
done = `LPM_TRUE;
|
|
end
|
|
end
|
|
$fclose(ifp);
|
|
$fclose(ofp);
|
|
end
|
|
end
|
|
endtask // convert_hex2ver
|
|
|
|
task convert_to_ver_file;
|
|
input[`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
input width;
|
|
output [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] in_file;
|
|
reg [`LPM_MAX_NAME_SZ*8 : 1] out_file;
|
|
integer width;
|
|
begin
|
|
|
|
if((in_file[4*8 : 1] == ".hex") || (in_file[4*8 : 1] == ".HEX") ||
|
|
(in_file[4*8 : 1] == ".dat") || (in_file[4*8 : 1] == ".DAT"))
|
|
convert_hex2ver(in_file, width, out_file);
|
|
else if((in_file[4*8 : 1] == ".mif") || (in_file[4*8 : 1] == ".MIF"))
|
|
convert_mif2ver(in_file, width, out_file);
|
|
else
|
|
begin
|
|
$display("ERROR: Invalid input file name %0s. Expecting file with .hex extension (with Intel-hex data format) or .mif extension (with Altera-mif data format).", in_file);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
end
|
|
endtask // convert_to_ver_file
|
|
|
|
endmodule // LPM_MEMORY_INITIALIZATION
|
|
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : LPM_HINT_EVALUATION
|
|
//
|
|
// Description : Common function to grep the value of altera specific parameters
|
|
// within the lpm_hint parameter.
|
|
//
|
|
// Limitation : No error checking to check whether the content of the lpm_hint
|
|
// is valid or not.
|
|
//
|
|
// Results expected: If the target parameter found, return the value of the parameter.
|
|
// Otherwise, return empty string.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module LPM_HINT_EVALUATION;
|
|
|
|
// FUNCTON DECLARATION
|
|
|
|
// This function will search through the string (given string) to look for a match for the
|
|
// a given parameter(compare_param_name). It will return the value for the given parameter.
|
|
function [8*200:1] GET_PARAMETER_VALUE;
|
|
input [8*200:1] given_string; // string to be searched
|
|
input [8*50:1] compare_param_name; // parameter name to be looking for in the given_string.
|
|
integer param_value_char_count; // to indicate current character count in the param_value
|
|
integer param_name_char_count; // to indicate current character count in the param_name
|
|
integer white_space_count;
|
|
|
|
reg extract_param_value; // if 1 mean extracting parameters value from given string
|
|
reg extract_param_name; // if 1 mean extracting parameters name from given string
|
|
reg param_found; // to indicate whether compare_param_name have been found in the given_string
|
|
reg include_white_space; // if 1, include white space in the parameter value
|
|
|
|
reg [8*200:1] reg_string; // to store the value of the given string
|
|
reg [8*50:1] param_name; // to store parameter name
|
|
reg [8*20:1] param_value; // to store parameter value
|
|
reg [8:1] tmp; // to get the value of the current byte
|
|
begin
|
|
reg_string = given_string;
|
|
param_value_char_count = 0;
|
|
param_name_char_count =0;
|
|
extract_param_value = 1;
|
|
extract_param_name = 0;
|
|
param_found = 0;
|
|
include_white_space = 0;
|
|
white_space_count = 0;
|
|
|
|
tmp = reg_string[8:1];
|
|
|
|
// checking every bytes of the reg_string from right to left.
|
|
while ((tmp != 0 ) && (param_found != 1))
|
|
begin
|
|
tmp = reg_string[8:1];
|
|
|
|
//if tmp != ' ' or should include white space (trailing white space are ignored)
|
|
if((tmp != 32) || (include_white_space == 1))
|
|
begin
|
|
if(tmp == 32)
|
|
begin
|
|
white_space_count = 1;
|
|
end
|
|
else if(tmp == 61) // if tmp = '='
|
|
begin
|
|
extract_param_value = 0;
|
|
extract_param_name = 1; // subsequent bytes should be part of param_name
|
|
include_white_space = 0; // ignore the white space (if any) between param_name and '='
|
|
white_space_count = 0;
|
|
param_value = param_value >> (8 * (20 - param_value_char_count));
|
|
param_value_char_count = 0;
|
|
end
|
|
else if (tmp == 44) // if tmp = ','
|
|
begin
|
|
extract_param_value = 1; // subsequent bytes should be part of param_value
|
|
extract_param_name = 0;
|
|
param_name = param_name >> (8 * (50 - param_name_char_count));
|
|
param_name_char_count = 0;
|
|
if(param_name == compare_param_name)
|
|
param_found = 1; // the compare_param_name have been found in the reg_string
|
|
end
|
|
else
|
|
begin
|
|
if(extract_param_value == 1)
|
|
begin
|
|
param_value_char_count = param_value_char_count + white_space_count + 1;
|
|
include_white_space = 1;
|
|
if(white_space_count > 0)
|
|
begin
|
|
param_value = {8'b100000, param_value[20*8:9]};
|
|
white_space_count = 0;
|
|
end
|
|
param_value = {tmp, param_value[20*8:9]};
|
|
end
|
|
else if(extract_param_name == 1)
|
|
begin
|
|
param_name = {tmp, param_name[50*8:9]};
|
|
param_name_char_count = param_name_char_count + 1;
|
|
end
|
|
end
|
|
end
|
|
reg_string = reg_string >> 8; // shift 1 byte to the right
|
|
end
|
|
|
|
// for the case whether param_name is the left most part of the reg_string
|
|
if(extract_param_name == 1)
|
|
begin
|
|
param_name = param_name >> (8 * (50 - param_name_char_count));
|
|
|
|
if(param_name == compare_param_name)
|
|
param_found = 1;
|
|
end
|
|
|
|
if (param_found == 1)
|
|
GET_PARAMETER_VALUE = param_value; // return the value of the parameter been looking for
|
|
else
|
|
GET_PARAMETER_VALUE = ""; // return empty string if parameter not found
|
|
|
|
end
|
|
endfunction
|
|
|
|
endmodule // LPM_HINT_EVALUATION
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module LPM_DEVICE_FAMILIES;
|
|
|
|
function IS_FAMILY_CYCLONE;
|
|
input[8*20:1] device;
|
|
reg is_cyclone;
|
|
begin
|
|
if ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado"))
|
|
is_cyclone = 1;
|
|
else
|
|
is_cyclone = 0;
|
|
|
|
IS_FAMILY_CYCLONE = is_cyclone;
|
|
end
|
|
endfunction //IS_FAMILY_CYCLONE
|
|
|
|
function IS_FAMILY_MAX3000A;
|
|
input[8*20:1] device;
|
|
reg is_max3000a;
|
|
begin
|
|
if ((device == "MAX3000A") || (device == "max3000a") || (device == "MAX 3000A") || (device == "max 3000a"))
|
|
is_max3000a = 1;
|
|
else
|
|
is_max3000a = 0;
|
|
|
|
IS_FAMILY_MAX3000A = is_max3000a;
|
|
end
|
|
endfunction //IS_FAMILY_MAX3000A
|
|
|
|
function IS_FAMILY_MAX7000A;
|
|
input[8*20:1] device;
|
|
reg is_max7000a;
|
|
begin
|
|
if ((device == "MAX7000A") || (device == "max7000a") || (device == "MAX 7000A") || (device == "max 7000a"))
|
|
is_max7000a = 1;
|
|
else
|
|
is_max7000a = 0;
|
|
|
|
IS_FAMILY_MAX7000A = is_max7000a;
|
|
end
|
|
endfunction //IS_FAMILY_MAX7000A
|
|
|
|
function IS_FAMILY_MAX7000AE;
|
|
input[8*20:1] device;
|
|
reg is_max7000ae;
|
|
begin
|
|
if ((device == "MAX7000AE") || (device == "max7000ae") || (device == "MAX 7000AE") || (device == "max 7000ae"))
|
|
is_max7000ae = 1;
|
|
else
|
|
is_max7000ae = 0;
|
|
|
|
IS_FAMILY_MAX7000AE = is_max7000ae;
|
|
end
|
|
endfunction //IS_FAMILY_MAX7000AE
|
|
|
|
function IS_FAMILY_MAX7000B;
|
|
input[8*20:1] device;
|
|
reg is_max7000b;
|
|
begin
|
|
if ((device == "MAX7000B") || (device == "max7000b") || (device == "MAX 7000B") || (device == "max 7000b"))
|
|
is_max7000b = 1;
|
|
else
|
|
is_max7000b = 0;
|
|
|
|
IS_FAMILY_MAX7000B = is_max7000b;
|
|
end
|
|
endfunction //IS_FAMILY_MAX7000B
|
|
|
|
function IS_FAMILY_MAX7000S;
|
|
input[8*20:1] device;
|
|
reg is_max7000s;
|
|
begin
|
|
if ((device == "MAX7000S") || (device == "max7000s") || (device == "MAX 7000S") || (device == "max 7000s"))
|
|
is_max7000s = 1;
|
|
else
|
|
is_max7000s = 0;
|
|
|
|
IS_FAMILY_MAX7000S = is_max7000s;
|
|
end
|
|
endfunction //IS_FAMILY_MAX7000S
|
|
|
|
function IS_FAMILY_STRATIXGX;
|
|
input[8*20:1] device;
|
|
reg is_stratixgx;
|
|
begin
|
|
if ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora"))
|
|
is_stratixgx = 1;
|
|
else
|
|
is_stratixgx = 0;
|
|
|
|
IS_FAMILY_STRATIXGX = is_stratixgx;
|
|
end
|
|
endfunction //IS_FAMILY_STRATIXGX
|
|
|
|
function IS_FAMILY_STRATIX;
|
|
input[8*20:1] device;
|
|
reg is_stratix;
|
|
begin
|
|
if ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager"))
|
|
is_stratix = 1;
|
|
else
|
|
is_stratix = 0;
|
|
|
|
IS_FAMILY_STRATIX = is_stratix;
|
|
end
|
|
endfunction //IS_FAMILY_STRATIX
|
|
|
|
function FEATURE_FAMILY_BASE_STRATIX;
|
|
input[8*20:1] device;
|
|
reg var_family_base_stratix;
|
|
begin
|
|
if (IS_FAMILY_STRATIX(device) || IS_FAMILY_STRATIXGX(device) )
|
|
var_family_base_stratix = 1;
|
|
else
|
|
var_family_base_stratix = 0;
|
|
|
|
FEATURE_FAMILY_BASE_STRATIX = var_family_base_stratix;
|
|
end
|
|
endfunction //FEATURE_FAMILY_BASE_STRATIX
|
|
|
|
function FEATURE_FAMILY_BASE_CYCLONE;
|
|
input[8*20:1] device;
|
|
reg var_family_base_cyclone;
|
|
begin
|
|
if (IS_FAMILY_CYCLONE(device) )
|
|
var_family_base_cyclone = 1;
|
|
else
|
|
var_family_base_cyclone = 0;
|
|
|
|
FEATURE_FAMILY_BASE_CYCLONE = var_family_base_cyclone;
|
|
end
|
|
endfunction //FEATURE_FAMILY_BASE_CYCLONE
|
|
|
|
function FEATURE_FAMILY_MAX;
|
|
input[8*20:1] device;
|
|
reg var_family_max;
|
|
begin
|
|
if ((device == "MAX5000") || IS_FAMILY_MAX3000A(device) || (device == "MAX7000") || IS_FAMILY_MAX7000A(device) || IS_FAMILY_MAX7000AE(device) || (device == "MAX7000E") || IS_FAMILY_MAX7000S(device) || IS_FAMILY_MAX7000B(device) || (device == "MAX9000") )
|
|
var_family_max = 1;
|
|
else
|
|
var_family_max = 0;
|
|
|
|
FEATURE_FAMILY_MAX = var_family_max;
|
|
end
|
|
endfunction //FEATURE_FAMILY_MAX
|
|
|
|
function IS_VALID_FAMILY;
|
|
input[8*20:1] device;
|
|
reg is_valid;
|
|
begin
|
|
if (((device == "Arria 10") || (device == "ARRIA 10") || (device == "arria 10") || (device == "Arria10") || (device == "ARRIA10") || (device == "arria10") || (device == "Arria VI") || (device == "ARRIA VI") || (device == "arria vi") || (device == "ArriaVI") || (device == "ARRIAVI") || (device == "arriavi") || (device == "Night Fury") || (device == "NIGHT FURY") || (device == "night fury") || (device == "nightfury") || (device == "NIGHTFURY") || (device == "Arria 10 (GX/SX/GT)") || (device == "ARRIA 10 (GX/SX/GT)") || (device == "arria 10 (gx/sx/gt)") || (device == "Arria10(GX/SX/GT)") || (device == "ARRIA10(GX/SX/GT)") || (device == "arria10(gx/sx/gt)") || (device == "Arria 10 (GX)") || (device == "ARRIA 10 (GX)") || (device == "arria 10 (gx)") || (device == "Arria10(GX)") || (device == "ARRIA10(GX)") || (device == "arria10(gx)") || (device == "Arria 10 (SX)") || (device == "ARRIA 10 (SX)") || (device == "arria 10 (sx)") || (device == "Arria10(SX)") || (device == "ARRIA10(SX)") || (device == "arria10(sx)") || (device == "Arria 10 (GT)") || (device == "ARRIA 10 (GT)") || (device == "arria 10 (gt)") || (device == "Arria10(GT)") || (device == "ARRIA10(GT)") || (device == "arria10(gt)"))
|
|
|| ((device == "Arria GX") || (device == "ARRIA GX") || (device == "arria gx") || (device == "ArriaGX") || (device == "ARRIAGX") || (device == "arriagx") || (device == "Stratix II GX Lite") || (device == "STRATIX II GX LITE") || (device == "stratix ii gx lite") || (device == "StratixIIGXLite") || (device == "STRATIXIIGXLITE") || (device == "stratixiigxlite"))
|
|
|| ((device == "Arria II GX") || (device == "ARRIA II GX") || (device == "arria ii gx") || (device == "ArriaIIGX") || (device == "ARRIAIIGX") || (device == "arriaiigx") || (device == "Arria IIGX") || (device == "ARRIA IIGX") || (device == "arria iigx") || (device == "ArriaII GX") || (device == "ARRIAII GX") || (device == "arriaii gx") || (device == "Arria II") || (device == "ARRIA II") || (device == "arria ii") || (device == "ArriaII") || (device == "ARRIAII") || (device == "arriaii") || (device == "Arria II (GX/E)") || (device == "ARRIA II (GX/E)") || (device == "arria ii (gx/e)") || (device == "ArriaII(GX/E)") || (device == "ARRIAII(GX/E)") || (device == "arriaii(gx/e)") || (device == "PIRANHA") || (device == "piranha"))
|
|
|| ((device == "Arria II GZ") || (device == "ARRIA II GZ") || (device == "arria ii gz") || (device == "ArriaII GZ") || (device == "ARRIAII GZ") || (device == "arriaii gz") || (device == "Arria IIGZ") || (device == "ARRIA IIGZ") || (device == "arria iigz") || (device == "ArriaIIGZ") || (device == "ARRIAIIGZ") || (device == "arriaiigz"))
|
|
|| ((device == "Arria V GZ") || (device == "ARRIA V GZ") || (device == "arria v gz") || (device == "ArriaVGZ") || (device == "ARRIAVGZ") || (device == "arriavgz"))
|
|
|| ((device == "Arria V") || (device == "ARRIA V") || (device == "arria v") || (device == "Arria V (GT/GX)") || (device == "ARRIA V (GT/GX)") || (device == "arria v (gt/gx)") || (device == "ArriaV(GT/GX)") || (device == "ARRIAV(GT/GX)") || (device == "arriav(gt/gx)") || (device == "ArriaV") || (device == "ARRIAV") || (device == "arriav") || (device == "Arria V (GT/GX/ST/SX)") || (device == "ARRIA V (GT/GX/ST/SX)") || (device == "arria v (gt/gx/st/sx)") || (device == "ArriaV(GT/GX/ST/SX)") || (device == "ARRIAV(GT/GX/ST/SX)") || (device == "arriav(gt/gx/st/sx)") || (device == "Arria V (GT)") || (device == "ARRIA V (GT)") || (device == "arria v (gt)") || (device == "ArriaV(GT)") || (device == "ARRIAV(GT)") || (device == "arriav(gt)") || (device == "Arria V (GX)") || (device == "ARRIA V (GX)") || (device == "arria v (gx)") || (device == "ArriaV(GX)") || (device == "ARRIAV(GX)") || (device == "arriav(gx)") || (device == "Arria V (ST)") || (device == "ARRIA V (ST)") || (device == "arria v (st)") || (device == "ArriaV(ST)") || (device == "ARRIAV(ST)") || (device == "arriav(st)") || (device == "Arria V (SX)") || (device == "ARRIA V (SX)") || (device == "arria v (sx)") || (device == "ArriaV(SX)") || (device == "ARRIAV(SX)") || (device == "arriav(sx)"))
|
|
|| ((device == "BS") || (device == "bs"))
|
|
|| ((device == "Cyclone II") || (device == "CYCLONE II") || (device == "cyclone ii") || (device == "Cycloneii") || (device == "CYCLONEII") || (device == "cycloneii") || (device == "Magellan") || (device == "MAGELLAN") || (device == "magellan") || (device == "CycloneII") || (device == "CYCLONEII") || (device == "cycloneii"))
|
|
|| ((device == "Cyclone III LS") || (device == "CYCLONE III LS") || (device == "cyclone iii ls") || (device == "CycloneIIILS") || (device == "CYCLONEIIILS") || (device == "cycloneiiils") || (device == "Cyclone III LPS") || (device == "CYCLONE III LPS") || (device == "cyclone iii lps") || (device == "Cyclone LPS") || (device == "CYCLONE LPS") || (device == "cyclone lps") || (device == "CycloneLPS") || (device == "CYCLONELPS") || (device == "cyclonelps") || (device == "Tarpon") || (device == "TARPON") || (device == "tarpon") || (device == "Cyclone IIIE") || (device == "CYCLONE IIIE") || (device == "cyclone iiie"))
|
|
|| ((device == "Cyclone III") || (device == "CYCLONE III") || (device == "cyclone iii") || (device == "CycloneIII") || (device == "CYCLONEIII") || (device == "cycloneiii") || (device == "Barracuda") || (device == "BARRACUDA") || (device == "barracuda") || (device == "Cuda") || (device == "CUDA") || (device == "cuda") || (device == "CIII") || (device == "ciii"))
|
|
|| ((device == "Cyclone IV E") || (device == "CYCLONE IV E") || (device == "cyclone iv e") || (device == "CycloneIV E") || (device == "CYCLONEIV E") || (device == "cycloneiv e") || (device == "Cyclone IVE") || (device == "CYCLONE IVE") || (device == "cyclone ive") || (device == "CycloneIVE") || (device == "CYCLONEIVE") || (device == "cycloneive"))
|
|
|| ((device == "Cyclone IV GX") || (device == "CYCLONE IV GX") || (device == "cyclone iv gx") || (device == "Cyclone IVGX") || (device == "CYCLONE IVGX") || (device == "cyclone ivgx") || (device == "CycloneIV GX") || (device == "CYCLONEIV GX") || (device == "cycloneiv gx") || (device == "CycloneIVGX") || (device == "CYCLONEIVGX") || (device == "cycloneivgx") || (device == "Cyclone IV") || (device == "CYCLONE IV") || (device == "cyclone iv") || (device == "CycloneIV") || (device == "CYCLONEIV") || (device == "cycloneiv") || (device == "Cyclone IV (GX)") || (device == "CYCLONE IV (GX)") || (device == "cyclone iv (gx)") || (device == "CycloneIV(GX)") || (device == "CYCLONEIV(GX)") || (device == "cycloneiv(gx)") || (device == "Cyclone III GX") || (device == "CYCLONE III GX") || (device == "cyclone iii gx") || (device == "CycloneIII GX") || (device == "CYCLONEIII GX") || (device == "cycloneiii gx") || (device == "Cyclone IIIGX") || (device == "CYCLONE IIIGX") || (device == "cyclone iiigx") || (device == "CycloneIIIGX") || (device == "CYCLONEIIIGX") || (device == "cycloneiiigx") || (device == "Cyclone III GL") || (device == "CYCLONE III GL") || (device == "cyclone iii gl") || (device == "CycloneIII GL") || (device == "CYCLONEIII GL") || (device == "cycloneiii gl") || (device == "Cyclone IIIGL") || (device == "CYCLONE IIIGL") || (device == "cyclone iiigl") || (device == "CycloneIIIGL") || (device == "CYCLONEIIIGL") || (device == "cycloneiiigl") || (device == "Stingray") || (device == "STINGRAY") || (device == "stingray"))
|
|
|| ((device == "Cyclone V") || (device == "CYCLONE V") || (device == "cyclone v") || (device == "CycloneV") || (device == "CYCLONEV") || (device == "cyclonev") || (device == "Cyclone V (GT/GX/E/SX)") || (device == "CYCLONE V (GT/GX/E/SX)") || (device == "cyclone v (gt/gx/e/sx)") || (device == "CycloneV(GT/GX/E/SX)") || (device == "CYCLONEV(GT/GX/E/SX)") || (device == "cyclonev(gt/gx/e/sx)") || (device == "Cyclone V (E/GX/GT/SX/SE/ST)") || (device == "CYCLONE V (E/GX/GT/SX/SE/ST)") || (device == "cyclone v (e/gx/gt/sx/se/st)") || (device == "CycloneV(E/GX/GT/SX/SE/ST)") || (device == "CYCLONEV(E/GX/GT/SX/SE/ST)") || (device == "cyclonev(e/gx/gt/sx/se/st)") || (device == "Cyclone V (E)") || (device == "CYCLONE V (E)") || (device == "cyclone v (e)") || (device == "CycloneV(E)") || (device == "CYCLONEV(E)") || (device == "cyclonev(e)") || (device == "Cyclone V (GX)") || (device == "CYCLONE V (GX)") || (device == "cyclone v (gx)") || (device == "CycloneV(GX)") || (device == "CYCLONEV(GX)") || (device == "cyclonev(gx)") || (device == "Cyclone V (GT)") || (device == "CYCLONE V (GT)") || (device == "cyclone v (gt)") || (device == "CycloneV(GT)") || (device == "CYCLONEV(GT)") || (device == "cyclonev(gt)") || (device == "Cyclone V (SX)") || (device == "CYCLONE V (SX)") || (device == "cyclone v (sx)") || (device == "CycloneV(SX)") || (device == "CYCLONEV(SX)") || (device == "cyclonev(sx)") || (device == "Cyclone V (SE)") || (device == "CYCLONE V (SE)") || (device == "cyclone v (se)") || (device == "CycloneV(SE)") || (device == "CYCLONEV(SE)") || (device == "cyclonev(se)") || (device == "Cyclone V (ST)") || (device == "CYCLONE V (ST)") || (device == "cyclone v (st)") || (device == "CycloneV(ST)") || (device == "CYCLONEV(ST)") || (device == "cyclonev(st)"))
|
|
|| ((device == "Cyclone") || (device == "CYCLONE") || (device == "cyclone") || (device == "ACEX2K") || (device == "acex2k") || (device == "ACEX 2K") || (device == "acex 2k") || (device == "Tornado") || (device == "TORNADO") || (device == "tornado"))
|
|
|| ((device == "HardCopy II") || (device == "HARDCOPY II") || (device == "hardcopy ii") || (device == "HardCopyII") || (device == "HARDCOPYII") || (device == "hardcopyii") || (device == "Fusion") || (device == "FUSION") || (device == "fusion"))
|
|
|| ((device == "HardCopy III") || (device == "HARDCOPY III") || (device == "hardcopy iii") || (device == "HardCopyIII") || (device == "HARDCOPYIII") || (device == "hardcopyiii") || (device == "HCX") || (device == "hcx"))
|
|
|| ((device == "HardCopy IV") || (device == "HARDCOPY IV") || (device == "hardcopy iv") || (device == "HardCopyIV") || (device == "HARDCOPYIV") || (device == "hardcopyiv") || (device == "HardCopy IV (GX)") || (device == "HARDCOPY IV (GX)") || (device == "hardcopy iv (gx)") || (device == "HardCopy IV (E)") || (device == "HARDCOPY IV (E)") || (device == "hardcopy iv (e)") || (device == "HardCopyIV(GX)") || (device == "HARDCOPYIV(GX)") || (device == "hardcopyiv(gx)") || (device == "HardCopyIV(E)") || (device == "HARDCOPYIV(E)") || (device == "hardcopyiv(e)") || (device == "HCXIV") || (device == "hcxiv") || (device == "HardCopy IV (GX/E)") || (device == "HARDCOPY IV (GX/E)") || (device == "hardcopy iv (gx/e)") || (device == "HardCopy IV (E/GX)") || (device == "HARDCOPY IV (E/GX)") || (device == "hardcopy iv (e/gx)") || (device == "HardCopyIV(GX/E)") || (device == "HARDCOPYIV(GX/E)") || (device == "hardcopyiv(gx/e)") || (device == "HardCopyIV(E/GX)") || (device == "HARDCOPYIV(E/GX)") || (device == "hardcopyiv(e/gx)"))
|
|
|| ((device == "MAX 10") || (device == "max 10") || (device == "MAX 10 FPGA") || (device == "max 10 fpga") || (device == "Zippleback") || (device == "ZIPPLEBACK") || (device == "zippleback") || (device == "MAX10") || (device == "max10") || (device == "MAX 10 (DA/DF/DC/SA/SC)") || (device == "max 10 (da/df/dc/sa/sc)") || (device == "MAX10(DA/DF/DC/SA/SC)") || (device == "max10(da/df/dc/sa/sc)") || (device == "MAX 10 (DA)") || (device == "max 10 (da)") || (device == "MAX10(DA)") || (device == "max10(da)") || (device == "MAX 10 (DF)") || (device == "max 10 (df)") || (device == "MAX10(DF)") || (device == "max10(df)") || (device == "MAX 10 (DC)") || (device == "max 10 (dc)") || (device == "MAX10(DC)") || (device == "max10(dc)") || (device == "MAX 10 (SA)") || (device == "max 10 (sa)") || (device == "MAX10(SA)") || (device == "max10(sa)") || (device == "MAX 10 (SC)") || (device == "max 10 (sc)") || (device == "MAX10(SC)") || (device == "max10(sc)"))
|
|
|| ((device == "MAX II") || (device == "max ii") || (device == "MAXII") || (device == "maxii") || (device == "Tsunami") || (device == "TSUNAMI") || (device == "tsunami"))
|
|
|| ((device == "MAX V") || (device == "max v") || (device == "MAXV") || (device == "maxv") || (device == "Jade") || (device == "JADE") || (device == "jade"))
|
|
|| ((device == "MAX3000A") || (device == "max3000a") || (device == "MAX 3000A") || (device == "max 3000a"))
|
|
|| ((device == "MAX7000A") || (device == "max7000a") || (device == "MAX 7000A") || (device == "max 7000a"))
|
|
|| ((device == "MAX7000AE") || (device == "max7000ae") || (device == "MAX 7000AE") || (device == "max 7000ae"))
|
|
|| ((device == "MAX7000B") || (device == "max7000b") || (device == "MAX 7000B") || (device == "max 7000b"))
|
|
|| ((device == "MAX7000S") || (device == "max7000s") || (device == "MAX 7000S") || (device == "max 7000s"))
|
|
|| ((device == "Stratix 10") || (device == "STRATIX 10") || (device == "stratix 10") || (device == "Stratix10") || (device == "STRATIX10") || (device == "stratix10") || (device == "nadder") || (device == "NADDER") || (device == "Stratix 10 (GX/SX)") || (device == "STRATIX 10 (GX/SX)") || (device == "stratix 10 (gx/sx)") || (device == "Stratix10(GX/SX)") || (device == "STRATIX10(GX/SX)") || (device == "stratix10(gx/sx)") || (device == "Stratix 10 (GX)") || (device == "STRATIX 10 (GX)") || (device == "stratix 10 (gx)") || (device == "Stratix10(GX)") || (device == "STRATIX10(GX)") || (device == "stratix10(gx)") || (device == "Stratix 10 (SX)") || (device == "STRATIX 10 (SX)") || (device == "stratix 10 (sx)") || (device == "Stratix10(SX)") || (device == "STRATIX10(SX)") || (device == "stratix10(sx)"))
|
|
|| ((device == "Stratix GX") || (device == "STRATIX GX") || (device == "stratix gx") || (device == "Stratix-GX") || (device == "STRATIX-GX") || (device == "stratix-gx") || (device == "StratixGX") || (device == "STRATIXGX") || (device == "stratixgx") || (device == "Aurora") || (device == "AURORA") || (device == "aurora"))
|
|
|| ((device == "Stratix II GX") || (device == "STRATIX II GX") || (device == "stratix ii gx") || (device == "StratixIIGX") || (device == "STRATIXIIGX") || (device == "stratixiigx"))
|
|
|| ((device == "Stratix II") || (device == "STRATIX II") || (device == "stratix ii") || (device == "StratixII") || (device == "STRATIXII") || (device == "stratixii") || (device == "Armstrong") || (device == "ARMSTRONG") || (device == "armstrong"))
|
|
|| ((device == "Stratix III") || (device == "STRATIX III") || (device == "stratix iii") || (device == "StratixIII") || (device == "STRATIXIII") || (device == "stratixiii") || (device == "Titan") || (device == "TITAN") || (device == "titan") || (device == "SIII") || (device == "siii"))
|
|
|| ((device == "Stratix IV") || (device == "STRATIX IV") || (device == "stratix iv") || (device == "TGX") || (device == "tgx") || (device == "StratixIV") || (device == "STRATIXIV") || (device == "stratixiv") || (device == "Stratix IV (GT)") || (device == "STRATIX IV (GT)") || (device == "stratix iv (gt)") || (device == "Stratix IV (GX)") || (device == "STRATIX IV (GX)") || (device == "stratix iv (gx)") || (device == "Stratix IV (E)") || (device == "STRATIX IV (E)") || (device == "stratix iv (e)") || (device == "StratixIV(GT)") || (device == "STRATIXIV(GT)") || (device == "stratixiv(gt)") || (device == "StratixIV(GX)") || (device == "STRATIXIV(GX)") || (device == "stratixiv(gx)") || (device == "StratixIV(E)") || (device == "STRATIXIV(E)") || (device == "stratixiv(e)") || (device == "StratixIIIGX") || (device == "STRATIXIIIGX") || (device == "stratixiiigx") || (device == "Stratix IV (GT/GX/E)") || (device == "STRATIX IV (GT/GX/E)") || (device == "stratix iv (gt/gx/e)") || (device == "Stratix IV (GT/E/GX)") || (device == "STRATIX IV (GT/E/GX)") || (device == "stratix iv (gt/e/gx)") || (device == "Stratix IV (E/GT/GX)") || (device == "STRATIX IV (E/GT/GX)") || (device == "stratix iv (e/gt/gx)") || (device == "Stratix IV (E/GX/GT)") || (device == "STRATIX IV (E/GX/GT)") || (device == "stratix iv (e/gx/gt)") || (device == "StratixIV(GT/GX/E)") || (device == "STRATIXIV(GT/GX/E)") || (device == "stratixiv(gt/gx/e)") || (device == "StratixIV(GT/E/GX)") || (device == "STRATIXIV(GT/E/GX)") || (device == "stratixiv(gt/e/gx)") || (device == "StratixIV(E/GX/GT)") || (device == "STRATIXIV(E/GX/GT)") || (device == "stratixiv(e/gx/gt)") || (device == "StratixIV(E/GT/GX)") || (device == "STRATIXIV(E/GT/GX)") || (device == "stratixiv(e/gt/gx)") || (device == "Stratix IV (GX/E)") || (device == "STRATIX IV (GX/E)") || (device == "stratix iv (gx/e)") || (device == "StratixIV(GX/E)") || (device == "STRATIXIV(GX/E)") || (device == "stratixiv(gx/e)"))
|
|
|| ((device == "Stratix V") || (device == "STRATIX V") || (device == "stratix v") || (device == "StratixV") || (device == "STRATIXV") || (device == "stratixv") || (device == "Stratix V (GS)") || (device == "STRATIX V (GS)") || (device == "stratix v (gs)") || (device == "StratixV(GS)") || (device == "STRATIXV(GS)") || (device == "stratixv(gs)") || (device == "Stratix V (GT)") || (device == "STRATIX V (GT)") || (device == "stratix v (gt)") || (device == "StratixV(GT)") || (device == "STRATIXV(GT)") || (device == "stratixv(gt)") || (device == "Stratix V (GX)") || (device == "STRATIX V (GX)") || (device == "stratix v (gx)") || (device == "StratixV(GX)") || (device == "STRATIXV(GX)") || (device == "stratixv(gx)") || (device == "Stratix V (GS/GX)") || (device == "STRATIX V (GS/GX)") || (device == "stratix v (gs/gx)") || (device == "StratixV(GS/GX)") || (device == "STRATIXV(GS/GX)") || (device == "stratixv(gs/gx)") || (device == "Stratix V (GS/GT)") || (device == "STRATIX V (GS/GT)") || (device == "stratix v (gs/gt)") || (device == "StratixV(GS/GT)") || (device == "STRATIXV(GS/GT)") || (device == "stratixv(gs/gt)") || (device == "Stratix V (GT/GX)") || (device == "STRATIX V (GT/GX)") || (device == "stratix v (gt/gx)") || (device == "StratixV(GT/GX)") || (device == "STRATIXV(GT/GX)") || (device == "stratixv(gt/gx)") || (device == "Stratix V (GX/GS)") || (device == "STRATIX V (GX/GS)") || (device == "stratix v (gx/gs)") || (device == "StratixV(GX/GS)") || (device == "STRATIXV(GX/GS)") || (device == "stratixv(gx/gs)") || (device == "Stratix V (GT/GS)") || (device == "STRATIX V (GT/GS)") || (device == "stratix v (gt/gs)") || (device == "StratixV(GT/GS)") || (device == "STRATIXV(GT/GS)") || (device == "stratixv(gt/gs)") || (device == "Stratix V (GX/GT)") || (device == "STRATIX V (GX/GT)") || (device == "stratix v (gx/gt)") || (device == "StratixV(GX/GT)") || (device == "STRATIXV(GX/GT)") || (device == "stratixv(gx/gt)") || (device == "Stratix V (GS/GT/GX)") || (device == "STRATIX V (GS/GT/GX)") || (device == "stratix v (gs/gt/gx)") || (device == "Stratix V (GS/GX/GT)") || (device == "STRATIX V (GS/GX/GT)") || (device == "stratix v (gs/gx/gt)") || (device == "Stratix V (GT/GS/GX)") || (device == "STRATIX V (GT/GS/GX)") || (device == "stratix v (gt/gs/gx)") || (device == "Stratix V (GT/GX/GS)") || (device == "STRATIX V (GT/GX/GS)") || (device == "stratix v (gt/gx/gs)") || (device == "Stratix V (GX/GS/GT)") || (device == "STRATIX V (GX/GS/GT)") || (device == "stratix v (gx/gs/gt)") || (device == "Stratix V (GX/GT/GS)") || (device == "STRATIX V (GX/GT/GS)") || (device == "stratix v (gx/gt/gs)") || (device == "StratixV(GS/GT/GX)") || (device == "STRATIXV(GS/GT/GX)") || (device == "stratixv(gs/gt/gx)") || (device == "StratixV(GS/GX/GT)") || (device == "STRATIXV(GS/GX/GT)") || (device == "stratixv(gs/gx/gt)") || (device == "StratixV(GT/GS/GX)") || (device == "STRATIXV(GT/GS/GX)") || (device == "stratixv(gt/gs/gx)") || (device == "StratixV(GT/GX/GS)") || (device == "STRATIXV(GT/GX/GS)") || (device == "stratixv(gt/gx/gs)") || (device == "StratixV(GX/GS/GT)") || (device == "STRATIXV(GX/GS/GT)") || (device == "stratixv(gx/gs/gt)") || (device == "StratixV(GX/GT/GS)") || (device == "STRATIXV(GX/GT/GS)") || (device == "stratixv(gx/gt/gs)") || (device == "Stratix V (GS/GT/GX/E)") || (device == "STRATIX V (GS/GT/GX/E)") || (device == "stratix v (gs/gt/gx/e)") || (device == "StratixV(GS/GT/GX/E)") || (device == "STRATIXV(GS/GT/GX/E)") || (device == "stratixv(gs/gt/gx/e)") || (device == "Stratix V (E)") || (device == "STRATIX V (E)") || (device == "stratix v (e)") || (device == "StratixV(E)") || (device == "STRATIXV(E)") || (device == "stratixv(e)"))
|
|
|| ((device == "Stratix") || (device == "STRATIX") || (device == "stratix") || (device == "Yeager") || (device == "YEAGER") || (device == "yeager"))
|
|
|| ((device == "eFPGA 28 HPM") || (device == "EFPGA 28 HPM") || (device == "efpga 28 hpm") || (device == "eFPGA28HPM") || (device == "EFPGA28HPM") || (device == "efpga28hpm") || (device == "Bedrock") || (device == "BEDROCK") || (device == "bedrock")))
|
|
is_valid = 1;
|
|
else
|
|
is_valid = 0;
|
|
|
|
IS_VALID_FAMILY = is_valid;
|
|
end
|
|
endfunction // IS_VALID_FAMILY
|
|
|
|
|
|
endmodule // LPM_DEVICE_FAMILIES
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_constant
|
|
//
|
|
// Description : Parameterized constant generator megafunction. lpm_constant
|
|
// may be useful for convert a parameter into a constant.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Value specified by the argument to LPM_CVALUE.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_constant (
|
|
result // Value specified by the argument to LPM_CVALUE. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the result[] port. (Required)
|
|
parameter lpm_cvalue = 0; // Constant value to be driven out on the
|
|
// result[] port. (Required)
|
|
parameter lpm_strength = "UNUSED";
|
|
parameter lpm_type = "lpm_constant";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg[32:0] int_value;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
int_value = lpm_cvalue;
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = int_value[lpm_width-1:0];
|
|
|
|
endmodule // lpm_constant
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_inv
|
|
//
|
|
// Description : Parameterized inverter megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Inverted value of input data
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_inv (
|
|
data, // Data input to the lpm_inv. (Required)
|
|
result // inverted result. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and result[] ports. (Required)
|
|
parameter lpm_type = "lpm_inv";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] result;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
result = ~data;
|
|
|
|
endmodule // lpm_inv
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_and
|
|
//
|
|
// Description : Parameterized AND gate. This megafunction takes in data inputs
|
|
// for a number of AND gates.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Each result[] bit is the result of each AND gate.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_and (
|
|
data, // Data input to the AND gate. (Required)
|
|
result // Result of the AND operators. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
// Width of the data[][] and result[] ports. Number of AND gates. (Required)
|
|
parameter lpm_width = 1;
|
|
// Number of inputs to each AND gate. Number of input buses. (Required)
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_and";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_tmp;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer j;
|
|
integer k;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_size <= 0)
|
|
begin
|
|
$display("Value of lpm_size parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result_tmp[i] = 1'b1;
|
|
for (j=0; j<lpm_size; j=j+1)
|
|
begin
|
|
k = (j * lpm_width) + i;
|
|
result_tmp[i] = result_tmp[i] & data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = result_tmp;
|
|
endmodule // lpm_and
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_or
|
|
//
|
|
// Description : Parameterized OR gate megafunction. This megafunction takes in
|
|
// data inputs for a number of OR gates.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Each result[] bit is the result of each OR gate.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_or (
|
|
data, // Data input to the OR gates. (Required)
|
|
result // Result of OR operators. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
// Width of the data[] and result[] ports. Number of OR gates. (Required)
|
|
parameter lpm_width = 1;
|
|
// Number of inputs to each OR gate. Number of input buses. (Required)
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_or";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_tmp;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer j;
|
|
integer k;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_size <= 0)
|
|
begin
|
|
$display("Value of lpm_size parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result_tmp[i] = 1'b0;
|
|
for (j=0; j<lpm_size; j=j+1)
|
|
begin
|
|
k = (j * lpm_width) + i;
|
|
result_tmp[i] = result_tmp[i] | data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = result_tmp;
|
|
|
|
endmodule // lpm_or
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_xor
|
|
//
|
|
// Description : Parameterized XOR gate megafunction. This megafunction takes in
|
|
// data inputs for a number of XOR gates.
|
|
//
|
|
// Limitation : n/a.
|
|
//
|
|
// Results expected: Each result[] bit is the result of each XOR gates.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_xor (
|
|
data, // Data input to the XOR gates. (Required)
|
|
result // Result of XOR operators. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
// Width of the data[] and result[] ports. Number of XOR gates. (Required)
|
|
parameter lpm_width = 1;
|
|
// Number of inputs to each XOR gate. Number of input buses. (Required)
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_xor";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_tmp;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer j;
|
|
integer k;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_size <= 0)
|
|
begin
|
|
$display("Value of lpm_size parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result_tmp[i] = 1'b0;
|
|
for (j=0; j<lpm_size; j=j+1)
|
|
begin
|
|
k = (j * lpm_width) + i;
|
|
result_tmp[i] = result_tmp[i] ^ data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = result_tmp;
|
|
|
|
endmodule // lpm_xor
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_bustri
|
|
//
|
|
// Description : Parameterized tri-state buffer. lpm_bustri is useful for
|
|
// controlling both unidirectional and bidirectional I/O bus
|
|
// controllers.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Belows are the three configurations which are valid:
|
|
//
|
|
// 1) Only the input ports data[LPM_WIDTH-1..0] and enabledt are
|
|
// present, and only the output ports tridata[LPM_WIDTH-1..0]
|
|
// are present.
|
|
//
|
|
// ----------------------------------------------------
|
|
// | Input | Output |
|
|
// |====================================================|
|
|
// | enabledt | tridata[LPM_WIDTH-1..0] |
|
|
// |----------------------------------------------------|
|
|
// | 0 | Z |
|
|
// |----------------------------------------------------|
|
|
// | 1 | DATA[LPM_WIDTH-1..0] |
|
|
// ----------------------------------------------------
|
|
//
|
|
// 2) Only the input ports tridata[LPM_WIDTH-1..0] and enabletr
|
|
// are present, and only the output ports result[LPM_WIDTH-1..0]
|
|
// are present.
|
|
//
|
|
// ----------------------------------------------------
|
|
// | Input | Output |
|
|
// |====================================================|
|
|
// | enabletr | result[LPM_WIDTH-1..0] |
|
|
// |----------------------------------------------------|
|
|
// | 0 | Z |
|
|
// |----------------------------------------------------|
|
|
// | 1 | tridata[LPM_WIDTH-1..0] |
|
|
// ----------------------------------------------------
|
|
//
|
|
// 3) All ports are present: input ports data[LPM_WIDTH-1..0],
|
|
// enabledt, and enabletr; output ports result[LPM_WIDTH-1..0];
|
|
// and bidirectional ports tridata[LPM_WIDTH-1..0].
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// | Input | Bidirectional | Output |
|
|
// |----------------------------------------------------------------------------|
|
|
// | enabledt | enabletr | tridata[LPM_WIDTH-1..0] | result[LPM_WIDTH-1..0] |
|
|
// |============================================================================|
|
|
// | 0 | 0 | Z (input) | Z |
|
|
// |----------------------------------------------------------------------------|
|
|
// | 0 | 1 | Z (input) | tridata[LPM_WIDTH-1..0] |
|
|
// |----------------------------------------------------------------------------|
|
|
// | 1 | 0 | data[LPM_WIDTH-1..0] | Z |
|
|
// |----------------------------------------------------------------------------|
|
|
// | 1 | 1 | data[LPM_WIDTH-1..0] | data[LPM_WIDTH-1..0] |
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_bustri (
|
|
tridata, // Bidirectional bus signal. (Required)
|
|
data, // Data input to the tridata[] bus. (Required)
|
|
enabletr, // If high, enables tridata[] onto the result bus.
|
|
enabledt, // If high, enables data onto the tridata[] bus.
|
|
result // Output from the tridata[] bus.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_bustri";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input enabletr;
|
|
input enabledt;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INPUT/OUTPUT PORT DECLARATION
|
|
inout [lpm_width-1:0] tridata;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] result;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri1 enabletr;
|
|
tri1 enabledt;
|
|
|
|
wire i_enabledt;
|
|
wire i_enabletr;
|
|
buf (i_enabledt, enabledt);
|
|
buf (i_enabletr, enabletr);
|
|
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or tridata or i_enabletr or i_enabledt)
|
|
begin
|
|
if ((i_enabledt == 1'b0) && (i_enabletr == 1'b1))
|
|
begin
|
|
result = tridata;
|
|
end
|
|
else if ((i_enabledt == 1'b1) && (i_enabletr == 1'b1))
|
|
begin
|
|
result = data;
|
|
end
|
|
else
|
|
begin
|
|
result = {lpm_width{1'bz}};
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign tridata = (i_enabledt == 1) ? data : {lpm_width{1'bz}};
|
|
|
|
endmodule // lpm_bustri
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_mux
|
|
//
|
|
// Description : Parameterized multiplexer megafunctions.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Selected input port.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_mux (
|
|
data, // Data input. (Required)
|
|
sel, // Selects one of the input buses. (Required)
|
|
clock, // Clock for pipelined usage
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
result // Selected input port. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[][] and result[] ports. (Required)
|
|
parameter lpm_size = 2; // Number of input buses to the multiplexer. (Required)
|
|
parameter lpm_widths = 1; // Width of the sel[] input port. (Required)
|
|
parameter lpm_pipeline = 0; // Specifies the number of Clock cycles of latency
|
|
// associated with the result[] output.
|
|
parameter lpm_type = "lpm_mux";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
input [lpm_widths-1:0] sel;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_pipe [lpm_pipeline+1:0];
|
|
reg [lpm_width-1:0] tmp_result;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
tri0 clock;
|
|
tri1 clken;
|
|
|
|
wire i_aclr;
|
|
wire i_clock;
|
|
wire i_clken;
|
|
buf (i_aclr, aclr);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_size <= 1)
|
|
begin
|
|
$display("Value of lpm_size parameter must be greater than 1 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_widths <= 0)
|
|
begin
|
|
$display("Value of lpm_widths parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_pipeline < 0)
|
|
begin
|
|
$display("Value of lpm_pipeline parameter must NOT less than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or sel)
|
|
begin
|
|
tmp_result = 0;
|
|
|
|
if (sel < lpm_size)
|
|
begin
|
|
for (i = 0; i < lpm_width; i = i + 1)
|
|
tmp_result[i] = data[(sel * lpm_width) + i];
|
|
end
|
|
else
|
|
tmp_result = {lpm_width{1'bx}};
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline+1); i = i + 1)
|
|
result_pipe[i] <= 1'b0;
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken == 1'b1)
|
|
begin
|
|
result_pipe[pipe_ptr] <= tmp_result;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = (lpm_pipeline > 0) ? result_pipe[pipe_ptr] : tmp_result;
|
|
|
|
endmodule // lpm_mux
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_decode
|
|
//
|
|
// Description : Parameterized decoder megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Decoded output.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_decode (
|
|
data, // Data input. Treated as an unsigned binary encoded number. (Required)
|
|
enable, // Enable. All outputs low when not active.
|
|
clock, // Clock for pipelined usage.
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
eq // Decoded output. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] port, or the
|
|
// input value to be decoded. (Required)
|
|
parameter lpm_decodes = 1 << lpm_width; // Number of explicit decoder outputs. (Required)
|
|
parameter lpm_pipeline = 0; // Number of Clock cycles of latency
|
|
parameter lpm_type = "lpm_decode";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input enable;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_decodes-1:0] eq;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_decodes-1:0] eq_pipe [(lpm_pipeline+1):0];
|
|
reg [lpm_decodes-1:0] tmp_eq;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri1 enable;
|
|
tri0 clock;
|
|
tri0 aclr;
|
|
tri1 clken;
|
|
|
|
wire i_clock;
|
|
wire i_clken;
|
|
wire i_aclr;
|
|
wire i_enable;
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
buf (i_aclr, aclr);
|
|
buf (i_enable, enable);
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_decodes <= 0)
|
|
begin
|
|
$display("Value of lpm_decodes parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_decodes > (1 << lpm_width))
|
|
begin
|
|
$display("Value of lpm_decodes parameter must be less or equal to 2^lpm_width (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_pipeline < 0)
|
|
begin
|
|
$display("Value of lpm_pipeline parameter must be greater or equal to 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or i_enable)
|
|
begin
|
|
tmp_eq = {lpm_decodes{1'b0}};
|
|
if (i_enable)
|
|
tmp_eq[data] = 1'b1;
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= lpm_pipeline; i = i + 1)
|
|
eq_pipe[i] <= {lpm_decodes{1'b0}};
|
|
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (clken == 1'b1)
|
|
begin
|
|
eq_pipe[pipe_ptr] <= tmp_eq;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
assign eq = (lpm_pipeline > 0) ? eq_pipe[pipe_ptr] : tmp_eq;
|
|
|
|
endmodule // lpm_decode
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_clshift
|
|
//
|
|
// Description : Parameterized combinatorial logic shifter or barrel shifter
|
|
// megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Return the shifted data and underflow/overflow status bit.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_clshift (
|
|
data, // Data to be shifted. (Required)
|
|
distance, // Number of positions to shift data[] in the direction specified
|
|
// by the direction port. (Required)
|
|
direction, // Direction of shift. Low = left (toward the MSB),
|
|
// high = right (toward the LSB).
|
|
clock, // Clock for pipelined usage.
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
result, // Shifted data. (Required)
|
|
underflow, // Logical or arithmetic underflow.
|
|
overflow // Logical or arithmetic overflow.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and result[] ports. Must be
|
|
// greater than 0 (Required)
|
|
parameter lpm_widthdist = 1; // Width of the distance[] input port. (Required)
|
|
parameter lpm_shifttype = "LOGICAL"; // Type of shifting operation to be performed.
|
|
parameter lpm_pipeline = 0; // Number of Clock cycles of latency
|
|
parameter lpm_type = "lpm_clshift";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] distance;
|
|
input direction;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
output underflow;
|
|
output overflow;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] ONES;
|
|
reg [lpm_width-1:0] ZEROS;
|
|
reg [lpm_width-1:0] tmp_result;
|
|
reg tmp_underflow;
|
|
reg tmp_overflow;
|
|
reg [lpm_width-1:0] result_pipe [(lpm_pipeline+1):0];
|
|
reg [(lpm_pipeline+1):0] overflow_pipe;
|
|
reg [(lpm_pipeline+1):0] underflow_pipe;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer i1;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 direction;
|
|
tri0 clock;
|
|
tri0 aclr;
|
|
tri1 clken;
|
|
|
|
wire i_direction;
|
|
wire i_clock;
|
|
wire i_clken;
|
|
wire i_aclr;
|
|
buf (i_direction, direction);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
buf (i_aclr, aclr);
|
|
|
|
|
|
// FUNCTON DECLARATION
|
|
// Perform logival shift operation
|
|
function [lpm_width+1:0] LogicShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] shift_num;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
reg underflow;
|
|
reg overflow;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
if ((direction) && (shift_num > 0)) // shift right
|
|
begin
|
|
tmp_buf = data >> shift_num;
|
|
if ((data != ZEROS) && ((shift_num >= lpm_width) || (tmp_buf == ZEROS)))
|
|
underflow = 1'b1;
|
|
end
|
|
else if (shift_num > 0) // shift left
|
|
begin
|
|
tmp_buf = data << shift_num;
|
|
if ((data != ZEROS) && ((shift_num >= lpm_width)
|
|
|| ((data >> (lpm_width-shift_num)) != ZEROS)))
|
|
overflow = 1'b1;
|
|
end
|
|
LogicShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
|
|
end
|
|
endfunction // LogicShift
|
|
|
|
// Perform Arithmetic shift operation
|
|
function [lpm_width+1:0] ArithShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] shift_num;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
reg underflow;
|
|
reg overflow;
|
|
integer i;
|
|
integer i1;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
|
|
if (shift_num < lpm_width)
|
|
begin
|
|
if ((direction) && (shift_num > 0)) // shift right
|
|
begin
|
|
if (data[lpm_width-1] == 1'b0) // positive number
|
|
begin
|
|
tmp_buf = data >> shift_num;
|
|
if ((data != ZEROS) && ((shift_num >= lpm_width) || (tmp_buf == ZEROS)))
|
|
underflow = 1'b1;
|
|
end
|
|
else // negative number
|
|
begin
|
|
tmp_buf = (data >> shift_num) | (ONES << (lpm_width - shift_num));
|
|
if ((data != ONES) && ((shift_num >= lpm_width-1) || (tmp_buf == ONES)))
|
|
underflow = 1'b1;
|
|
end
|
|
end
|
|
else if (shift_num > 0) // shift left
|
|
begin
|
|
tmp_buf = data << shift_num;
|
|
|
|
for (i=lpm_width-1; i >= lpm_width-shift_num; i=i-1)
|
|
begin
|
|
if(data[i-1] != data[lpm_width-1])
|
|
overflow = 1'b1;
|
|
end
|
|
end
|
|
end
|
|
else // shift_num >= lpm_width
|
|
begin
|
|
if (direction)
|
|
begin
|
|
for (i=0; i < lpm_width; i=i+1)
|
|
tmp_buf[i] = data[lpm_width-1];
|
|
|
|
underflow = 1'b1;
|
|
end
|
|
else
|
|
begin
|
|
tmp_buf = {lpm_width{1'b0}};
|
|
|
|
if (data != ZEROS)
|
|
begin
|
|
overflow = 1'b1;
|
|
end
|
|
end
|
|
end
|
|
ArithShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
|
|
end
|
|
endfunction // ArithShift
|
|
|
|
// Perform rotate shift operation
|
|
function [lpm_width+1:0] RotateShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] shift_num;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
if ((direction) && (shift_num > 0)) // shift right
|
|
tmp_buf = (data >> shift_num) | (data << (lpm_width - shift_num));
|
|
else if (shift_num > 0) // shift left
|
|
tmp_buf = (data << shift_num) | (data >> (lpm_width - shift_num));
|
|
RotateShift = {2'bx, tmp_buf[lpm_width-1:0]};
|
|
end
|
|
endfunction // RotateShift
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if ((lpm_shifttype != "LOGICAL") &&
|
|
(lpm_shifttype != "ARITHMETIC") &&
|
|
(lpm_shifttype != "ROTATE") &&
|
|
(lpm_shifttype != "UNUSED")) // non-LPM 220 standard
|
|
begin
|
|
$display("Error! LPM_SHIFTTYPE value must be \"LOGICAL\", \"ARITHMETIC\", or \"ROTATE\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_widthdist <= 0)
|
|
begin
|
|
$display("Value of lpm_widthdist parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i=0; i < lpm_width; i=i+1)
|
|
begin
|
|
ONES[i] = 1'b1;
|
|
ZEROS[i] = 1'b0;
|
|
end
|
|
|
|
for (i = 0; i <= lpm_pipeline; i = i + 1)
|
|
begin
|
|
result_pipe[i] = ZEROS;
|
|
overflow_pipe[i] = 1'b0;
|
|
underflow_pipe[i] = 1'b0;
|
|
end
|
|
|
|
tmp_result = ZEROS;
|
|
tmp_underflow = 1'b0;
|
|
tmp_overflow = 1'b0;
|
|
pipe_ptr = 0;
|
|
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or i_direction or distance)
|
|
begin
|
|
if ((lpm_shifttype == "LOGICAL") || (lpm_shifttype == "UNUSED"))
|
|
{tmp_overflow, tmp_underflow, tmp_result} = LogicShift(data, distance, i_direction);
|
|
else if (lpm_shifttype == "ARITHMETIC")
|
|
{tmp_overflow, tmp_underflow, tmp_result} = ArithShift(data, distance, i_direction);
|
|
else if (lpm_shifttype == "ROTATE")
|
|
{tmp_overflow, tmp_underflow, tmp_result} = RotateShift(data, distance, i_direction);
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i1 = 0; i1 <= lpm_pipeline; i1 = i1 + 1)
|
|
begin
|
|
result_pipe[i1] <= {lpm_width{1'b0}};
|
|
overflow_pipe[i1] <= 1'b0;
|
|
underflow_pipe[i1] <= 1'b0;
|
|
end
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken == 1'b1)
|
|
begin
|
|
result_pipe[pipe_ptr] <= tmp_result;
|
|
overflow_pipe[pipe_ptr] <= tmp_overflow;
|
|
underflow_pipe[pipe_ptr] <= tmp_underflow;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
assign result = (lpm_pipeline > 0) ? result_pipe[pipe_ptr] : tmp_result;
|
|
assign overflow = (lpm_pipeline > 0) ? overflow_pipe[pipe_ptr] : tmp_overflow;
|
|
assign underflow = (lpm_pipeline > 0) ? underflow_pipe[pipe_ptr] : tmp_underflow;
|
|
|
|
endmodule // lpm_clshift
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_add_sub
|
|
//
|
|
// Description : Parameterized adder/subtractor megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: If performs as adder, the result will be dataa[]+datab[]+cin.
|
|
// If performs as subtractor, the result will be dataa[]-datab[]+cin-1.
|
|
// Also returns carry out bit and overflow status bit.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_add_sub (
|
|
dataa, // Augend/Minuend
|
|
datab, // Addend/Subtrahend
|
|
cin, // Carry-in to the low-order bit.
|
|
add_sub, // If the signal is high, the operation = dataa[]+datab[]+cin.
|
|
// If the signal is low, the operation = dataa[]-datab[]+cin-1.
|
|
|
|
clock, // Clock for pipelined usage.
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
result, // dataa[]+datab[]+cin or dataa[]-datab[]+cin-1
|
|
cout, // Carry-out (borrow-in) of the MSB.
|
|
overflow // Result exceeds available precision.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the dataa[],datab[], and result[] ports.
|
|
parameter lpm_representation = "SIGNED"; // Type of addition performed
|
|
parameter lpm_direction = "UNUSED"; // Specify the operation of the lpm_add_sub function
|
|
parameter lpm_pipeline = 0; // Number of Clock cycles of latency
|
|
parameter lpm_type = "lpm_add_sub";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] dataa;
|
|
input [lpm_width-1:0] datab;
|
|
input cin;
|
|
input add_sub;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
output cout;
|
|
output overflow;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_pipe [(lpm_pipeline+1):0];
|
|
reg [(lpm_pipeline+1):0] cout_pipe;
|
|
reg [(lpm_pipeline+1):0] overflow_pipe;
|
|
reg tmp_cout;
|
|
reg tmp_overflow;
|
|
reg [lpm_width-1:0] tmp_result;
|
|
reg i_cin;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer borrow;
|
|
integer i;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri1 i_add_sub;
|
|
tri0 i_aclr;
|
|
tri1 i_clken;
|
|
tri0 i_clock;
|
|
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
// check if lpm_width < 0
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTH must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if ((lpm_direction != "ADD") &&
|
|
(lpm_direction != "SUB") &&
|
|
(lpm_direction != "UNUSED") && // non-LPM 220 standard
|
|
(lpm_direction != "DEFAULT")) // non-LPM 220 standard
|
|
begin
|
|
$display("Error! LPM_DIRECTION value must be \"ADD\" or \"SUB\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if ((lpm_representation != "SIGNED") &&
|
|
(lpm_representation != "UNSIGNED"))
|
|
begin
|
|
$display("Error! LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_pipeline < 0)
|
|
begin
|
|
$display("Error! LPM_PIPELINE must be greater than or equal to 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i = 0; i <= (lpm_pipeline+1); i = i + 1)
|
|
begin
|
|
result_pipe[i] = 'b0;
|
|
cout_pipe[i] = 1'b0;
|
|
overflow_pipe[i] = 1'b0;
|
|
end
|
|
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(cin or dataa or datab or i_add_sub)
|
|
begin
|
|
i_cin = 1'b0;
|
|
borrow = 1'b0;
|
|
|
|
// cout is the same for both signed and unsign representation.
|
|
if ((lpm_direction == "ADD") || ((i_add_sub == 1) &&
|
|
((lpm_direction == "UNUSED") || (lpm_direction == "DEFAULT")) ))
|
|
begin
|
|
i_cin = (cin === 1'bz) ? 0 : cin;
|
|
{tmp_cout, tmp_result} = dataa + datab + i_cin;
|
|
tmp_overflow = tmp_cout;
|
|
end
|
|
else if ((lpm_direction == "SUB") || ((i_add_sub == 0) &&
|
|
((lpm_direction == "UNUSED") || (lpm_direction == "DEFAULT")) ))
|
|
begin
|
|
i_cin = (cin === 1'bz) ? 1 : cin;
|
|
borrow = (~i_cin) ? 1 : 0;
|
|
{tmp_overflow, tmp_result} = dataa - datab - borrow;
|
|
tmp_cout = (dataa >= (datab+borrow))?1:0;
|
|
end
|
|
|
|
if (lpm_representation == "SIGNED")
|
|
begin
|
|
// perform the addtion or subtraction operation
|
|
if ((lpm_direction == "ADD") || ((i_add_sub == 1) &&
|
|
((lpm_direction == "UNUSED") || (lpm_direction == "DEFAULT")) ))
|
|
begin
|
|
tmp_result = dataa + datab + i_cin;
|
|
tmp_overflow = ((dataa[lpm_width-1] == datab[lpm_width-1]) &&
|
|
(dataa[lpm_width-1] != tmp_result[lpm_width-1])) ?
|
|
1 : 0;
|
|
end
|
|
else if ((lpm_direction == "SUB") || ((i_add_sub == 0) &&
|
|
((lpm_direction == "UNUSED") || (lpm_direction == "DEFAULT")) ))
|
|
begin
|
|
tmp_result = dataa - datab - borrow;
|
|
tmp_overflow = ((dataa[lpm_width-1] != datab[lpm_width-1]) &&
|
|
(dataa[lpm_width-1] != tmp_result[lpm_width-1])) ?
|
|
1 : 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline+1); i = i + 1)
|
|
begin
|
|
result_pipe[i] <= {lpm_width{1'b0}};
|
|
cout_pipe[i] <= 1'b0;
|
|
overflow_pipe[i] <= 1'b0;
|
|
end
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken == 1)
|
|
begin
|
|
result_pipe[pipe_ptr] <= tmp_result;
|
|
cout_pipe[pipe_ptr] <= tmp_cout;
|
|
overflow_pipe[pipe_ptr] <= tmp_overflow;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = (lpm_pipeline > 0) ? result_pipe[pipe_ptr] : tmp_result;
|
|
assign cout = (lpm_pipeline > 0) ? cout_pipe[pipe_ptr] : tmp_cout;
|
|
assign overflow = (lpm_pipeline > 0) ? overflow_pipe[pipe_ptr] : tmp_overflow;
|
|
assign i_clock = clock;
|
|
assign i_aclr = aclr;
|
|
assign i_clken = clken;
|
|
assign i_add_sub = add_sub;
|
|
|
|
endmodule // lpm_add_sub
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_compare
|
|
//
|
|
// Description : Parameterized comparator megafunction. The comparator will
|
|
// compare between data[] and datab[] and return the status of
|
|
// comparation for the following operation.
|
|
// 1) dataa[] < datab[].
|
|
// 2) dataa[] == datab[].
|
|
// 3) dataa[] > datab[].
|
|
// 4) dataa[] >= datab[].
|
|
// 5) dataa[] != datab[].
|
|
// 6) dataa[] <= datab[].
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Return status bits of the comparision between dataa[] and
|
|
// datab[].
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_compare (
|
|
dataa, // Value to be compared to datab[]. (Required)
|
|
datab, // Value to be compared to dataa[]. (Required)
|
|
clock, // Clock for pipelined usage.
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
|
|
// One of the following ports must be present.
|
|
alb, // High (1) if dataa[] < datab[].
|
|
aeb, // High (1) if dataa[] == datab[].
|
|
agb, // High (1) if dataa[] > datab[].
|
|
aleb, // High (1) if dataa[] <= datab[].
|
|
aneb, // High (1) if dataa[] != datab[].
|
|
ageb // High (1) if dataa[] >= datab[].
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the dataa[] and datab[] ports. (Required)
|
|
parameter lpm_representation = "UNSIGNED"; // Type of comparison performed:
|
|
// "SIGNED", "UNSIGNED"
|
|
parameter lpm_pipeline = 0; // Specifies the number of Clock cycles of latency
|
|
// associated with the alb, aeb, agb, ageb, aleb,
|
|
// or aneb output.
|
|
parameter lpm_type = "lpm_compare";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] dataa;
|
|
input [lpm_width-1:0] datab;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output alb;
|
|
output aeb;
|
|
output agb;
|
|
output aleb;
|
|
output aneb;
|
|
output ageb;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_pipeline+1:0] alb_pipe;
|
|
reg [lpm_pipeline+1:0] aeb_pipe;
|
|
reg [lpm_pipeline+1:0] agb_pipe;
|
|
reg [lpm_pipeline+1:0] aleb_pipe;
|
|
reg [lpm_pipeline+1:0] aneb_pipe;
|
|
reg [lpm_pipeline+1:0] ageb_pipe;
|
|
reg tmp_alb;
|
|
reg tmp_aeb;
|
|
reg tmp_agb;
|
|
reg tmp_aleb;
|
|
reg tmp_aneb;
|
|
reg tmp_ageb;
|
|
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
tri0 clock;
|
|
tri1 clken;
|
|
|
|
wire i_aclr;
|
|
wire i_clock;
|
|
wire i_clken;
|
|
buf (i_aclr, aclr);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if ((lpm_representation != "SIGNED") &&
|
|
(lpm_representation != "UNSIGNED"))
|
|
begin
|
|
$display("Error! LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
// get the status of comparison
|
|
always @(dataa or datab)
|
|
begin
|
|
tmp_aeb = (dataa == datab);
|
|
tmp_aneb = (dataa != datab);
|
|
|
|
if ((lpm_representation == "SIGNED") &&
|
|
((dataa[lpm_width-1] ^ datab[lpm_width-1]) == 1))
|
|
begin
|
|
// create latency
|
|
tmp_alb = (dataa > datab);
|
|
tmp_agb = (dataa < datab);
|
|
tmp_aleb = (dataa >= datab);
|
|
tmp_ageb = (dataa <= datab);
|
|
end
|
|
else
|
|
begin
|
|
// create latency
|
|
tmp_alb = (dataa < datab);
|
|
tmp_agb = (dataa > datab);
|
|
tmp_aleb = (dataa <= datab);
|
|
tmp_ageb = (dataa >= datab);
|
|
end
|
|
end
|
|
|
|
// pipelining process
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr) // reset all variables
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline + 1); i = i + 1)
|
|
begin
|
|
aeb_pipe[i] <= 1'b0;
|
|
agb_pipe[i] <= 1'b0;
|
|
alb_pipe[i] <= 1'b0;
|
|
aleb_pipe[i] <= 1'b0;
|
|
aneb_pipe[i] <= 1'b0;
|
|
ageb_pipe[i] <= 1'b0;
|
|
end
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken == 1)
|
|
begin
|
|
alb_pipe[pipe_ptr] <= tmp_alb;
|
|
aeb_pipe[pipe_ptr] <= tmp_aeb;
|
|
agb_pipe[pipe_ptr] <= tmp_agb;
|
|
aleb_pipe[pipe_ptr] <= tmp_aleb;
|
|
aneb_pipe[pipe_ptr] <= tmp_aneb;
|
|
ageb_pipe[pipe_ptr] <= tmp_ageb;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign alb = (lpm_pipeline > 0) ? alb_pipe[pipe_ptr] : tmp_alb;
|
|
assign aeb = (lpm_pipeline > 0) ? aeb_pipe[pipe_ptr] : tmp_aeb;
|
|
assign agb = (lpm_pipeline > 0) ? agb_pipe[pipe_ptr] : tmp_agb;
|
|
assign aleb = (lpm_pipeline > 0) ? aleb_pipe[pipe_ptr] : tmp_aleb;
|
|
assign aneb = (lpm_pipeline > 0) ? aneb_pipe[pipe_ptr] : tmp_aneb;
|
|
assign ageb = (lpm_pipeline > 0) ? ageb_pipe[pipe_ptr] : tmp_ageb;
|
|
|
|
endmodule // lpm_compare
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_mult
|
|
//
|
|
// Description : Parameterized multiplier megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: dataa[] * datab[] + sum[].
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_mult (
|
|
dataa, // Multiplicand. (Required)
|
|
datab, // Multiplier. (Required)
|
|
sum, // Partial sum.
|
|
aclr, // Asynchronous clear for pipelined usage.
|
|
sclr, // Synchronous clear for pipelined usage.
|
|
clock, // Clock for pipelined usage.
|
|
clken, // Clock enable for pipelined usage.
|
|
result // result = dataa[] * datab[] + sum. The product LSB is aligned with the sum LSB.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_widtha = 1; // Width of the dataa[] port. (Required)
|
|
parameter lpm_widthb = 1; // Width of the datab[] port. (Required)
|
|
parameter lpm_widthp = 1; // Width of the result[] port. (Required)
|
|
parameter lpm_widths = 1; // Width of the sum[] port. (Required)
|
|
parameter lpm_representation = "UNSIGNED"; // Type of multiplication performed
|
|
parameter lpm_pipeline = 0; // Number of clock cycles of latency
|
|
parameter lpm_type = "lpm_mult";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_widtha-1:0] dataa;
|
|
input [lpm_widthb-1:0] datab;
|
|
input [lpm_widths-1:0] sum;
|
|
input aclr;
|
|
input sclr;
|
|
input clock;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_widthp-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_widthp-1:0] result_pipe [lpm_pipeline+1:0];
|
|
reg [lpm_widthp-1:0] i_prod;
|
|
reg [lpm_widthp-1:0] t_p;
|
|
reg [lpm_widths-1:0] i_prod_s;
|
|
reg [lpm_widths-1:0] t_s;
|
|
reg [lpm_widtha+lpm_widthb-1:0] i_prod_ab;
|
|
reg [lpm_widtha-1:0] t_a;
|
|
reg [lpm_widthb-1:0] t_b;
|
|
reg sign_ab;
|
|
reg sign_s;
|
|
reg [8*5:1] input_a_is_constant;
|
|
reg [8*5:1] input_b_is_constant;
|
|
reg [8*lpm_widtha:1] input_a_fixed_value;
|
|
reg [8*lpm_widthb:1] input_b_fixed_value;
|
|
reg [lpm_widtha-1:0] dataa_fixed;
|
|
reg [lpm_widthb-1:0] datab_fixed;
|
|
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire [lpm_widtha-1:0] dataa_wire;
|
|
wire [lpm_widthb-1:0] datab_wire;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
tri0 sclr;
|
|
tri0 clock;
|
|
tri1 clken;
|
|
|
|
wire i_aclr;
|
|
wire i_sclr;
|
|
wire i_clock;
|
|
wire i_clken;
|
|
buf (i_aclr, aclr);
|
|
buf (i_sclr, sclr);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_HINT_EVALUATION eva();
|
|
|
|
// FUNCTION DECLARATION
|
|
// convert string to binary bits.
|
|
function integer str2bin;
|
|
input [8*256:1] str;
|
|
input str_width;
|
|
|
|
reg [8*256:1] reg_str;
|
|
reg [255:0] bin;
|
|
reg [8:1] tmp;
|
|
integer m;
|
|
integer str_width;
|
|
|
|
begin
|
|
reg_str = str;
|
|
for (m=0; m < str_width; m=m+1)
|
|
begin
|
|
tmp = reg_str[8:1];
|
|
reg_str = reg_str >> 8;
|
|
|
|
case (tmp)
|
|
"0" : bin[m] = 1'b0;
|
|
"1" : bin[m] = 1'b1;
|
|
default: bin[m] = 1'bx;
|
|
endcase
|
|
end
|
|
str2bin = bin;
|
|
end
|
|
endfunction
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
// check if lpm_widtha > 0
|
|
if (lpm_widtha <= 0)
|
|
begin
|
|
$display("Error! lpm_widtha must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check if lpm_widthb > 0
|
|
if (lpm_widthb <= 0)
|
|
begin
|
|
$display("Error! lpm_widthb must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check if lpm_widthp > 0
|
|
if (lpm_widthp <= 0)
|
|
begin
|
|
$display("Error! lpm_widthp must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check if lpm_widthp > 0
|
|
if (lpm_widths <= 0)
|
|
begin
|
|
$display("Error! lpm_widths must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check for valid lpm_rep value
|
|
if ((lpm_representation != "SIGNED") && (lpm_representation != "UNSIGNED"))
|
|
begin
|
|
$display("Error! lpm_representation value must be \"SIGNED\" or \"UNSIGNED\".", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
input_a_is_constant = eva.GET_PARAMETER_VALUE(lpm_hint, "INPUT_A_IS_CONSTANT");
|
|
|
|
if (input_a_is_constant == "FIXED")
|
|
begin
|
|
input_a_fixed_value = eva.GET_PARAMETER_VALUE(lpm_hint, "INPUT_A_FIXED_VALUE");
|
|
dataa_fixed = str2bin(input_a_fixed_value, lpm_widtha);
|
|
end
|
|
|
|
input_b_is_constant = eva.GET_PARAMETER_VALUE(lpm_hint, "INPUT_B_IS_CONSTANT");
|
|
|
|
if (input_b_is_constant == "FIXED")
|
|
begin
|
|
input_b_fixed_value = eva.GET_PARAMETER_VALUE(lpm_hint, "INPUT_B_FIXED_VALUE");
|
|
datab_fixed = str2bin(input_b_fixed_value, lpm_widthb);
|
|
end
|
|
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(dataa_wire or datab_wire or sum)
|
|
begin
|
|
t_a = dataa_wire;
|
|
t_b = datab_wire;
|
|
t_s = sum;
|
|
sign_ab = 1'b0;
|
|
sign_s = 1'b0;
|
|
|
|
// if inputs are sign number
|
|
if (lpm_representation == "SIGNED")
|
|
begin
|
|
sign_ab = dataa_wire[lpm_widtha-1] ^ datab_wire[lpm_widthb-1];
|
|
sign_s = sum[lpm_widths-1];
|
|
|
|
// if negative number, represent them as 2 compliment number.
|
|
if (dataa_wire[lpm_widtha-1] == 1)
|
|
t_a = (~dataa_wire) + 1;
|
|
if (datab_wire[lpm_widthb-1] == 1)
|
|
t_b = (~datab_wire) + 1;
|
|
if (sum[lpm_widths-1] == 1)
|
|
t_s = (~sum) + 1;
|
|
end
|
|
|
|
// if sum port is not used
|
|
if (sum === {lpm_widths{1'bz}})
|
|
begin
|
|
t_s = {lpm_widths{1'b0}};
|
|
sign_s = 1'b0;
|
|
end
|
|
|
|
if (sign_ab == sign_s)
|
|
begin
|
|
i_prod = (t_a * t_b) + t_s;
|
|
i_prod_s = (t_a * t_b) + t_s;
|
|
i_prod_ab = (t_a * t_b) + t_s;
|
|
end
|
|
else
|
|
begin
|
|
i_prod = (t_a * t_b) - t_s;
|
|
i_prod_s = (t_a * t_b) - t_s;
|
|
i_prod_ab = (t_a * t_b) - t_s;
|
|
end
|
|
|
|
// if dataa[] * datab[] produces negative number, compliment the result
|
|
if (sign_ab)
|
|
begin
|
|
i_prod = (~i_prod) + 1;
|
|
i_prod_s = (~i_prod_s) + 1;
|
|
i_prod_ab = (~i_prod_ab) + 1;
|
|
end
|
|
|
|
if ((lpm_widthp < lpm_widths) || (lpm_widthp < (lpm_widtha+lpm_widthb)))
|
|
for (i = 0; i < lpm_widthp; i = i + 1)
|
|
i_prod[lpm_widthp-1-i] = (lpm_widths > lpm_widtha+lpm_widthb)
|
|
? i_prod_s[lpm_widths-1-i]
|
|
: i_prod_ab[lpm_widtha+lpm_widthb-1-i];
|
|
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr) // clear the pipeline for result to 0
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline + 1); i = i + 1)
|
|
result_pipe[i] <= {lpm_widthp{1'b0}};
|
|
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken == 1)
|
|
begin
|
|
if(i_sclr)
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline + 1); i = i + 1)
|
|
result_pipe[i] <= {lpm_widthp{1'b0}};
|
|
|
|
pipe_ptr <= 0;
|
|
end
|
|
else
|
|
begin
|
|
result_pipe[pipe_ptr] <= i_prod;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign dataa_wire = (input_a_is_constant == "FIXED") ? dataa_fixed : dataa;
|
|
assign datab_wire = (input_b_is_constant == "FIXED") ? datab_fixed : datab;
|
|
assign result = (lpm_pipeline > 0) ? result_pipe[pipe_ptr] : i_prod;
|
|
|
|
endmodule // lpm_mult
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_divide
|
|
//
|
|
// Description : Parameterized divider megafunction. This function performs a
|
|
// divide operation such that denom * quotient + remain = numer
|
|
// The function allows for all combinations of signed(two's
|
|
// complement) and unsigned inputs. If any of the inputs is
|
|
// signed, the output is signed. Otherwise the output is unsigned.
|
|
// The function also allows the remainder to be specified as
|
|
// always positive (in which case remain >= 0); otherwise remain
|
|
// is zero or the same sign as the numerator
|
|
// (this parameter is ignored in the case of purely unsigned
|
|
// division). Finally the function is also pipelinable.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Return quotient and remainder.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_divide (
|
|
numer, // The numerator (Required)
|
|
denom, // The denominator (Required)
|
|
clock, // Clock input for pipelined usage
|
|
aclr, // Asynchronous clear signal
|
|
clken, // Clock enable for pipelined usage.
|
|
quotient, // Quotient (Required)
|
|
remain // Remainder (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_widthn = 1; // Width of the numer[] and quotient[] port. (Required)
|
|
parameter lpm_widthd = 1; // Width of the denom[] and remain[] port. (Required)
|
|
parameter lpm_nrepresentation = "UNSIGNED"; // The representation of numer
|
|
parameter lpm_drepresentation = "UNSIGNED"; // The representation of denom
|
|
parameter lpm_pipeline = 0; // Number of Clock cycles of latency
|
|
parameter lpm_type = "lpm_divide";
|
|
parameter lpm_hint = "LPM_REMAINDERPOSITIVE=TRUE";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_widthn-1:0] numer;
|
|
input [lpm_widthd-1:0] denom;
|
|
input clock;
|
|
input aclr;
|
|
input clken;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_widthn-1:0] quotient;
|
|
output [lpm_widthd-1:0] remain;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_widthn-1:0] quotient_pipe [lpm_pipeline+1:0];
|
|
reg [lpm_widthd-1:0] remain_pipe [lpm_pipeline+1:0];
|
|
reg [lpm_widthn-1:0] tmp_quotient;
|
|
reg [lpm_widthd-1:0] tmp_remain;
|
|
reg [lpm_widthn-1:0] not_numer;
|
|
reg [lpm_widthn-1:0] int_numer;
|
|
reg [lpm_widthd-1:0] not_denom;
|
|
reg [lpm_widthd-1:0] int_denom;
|
|
reg [lpm_widthn-1:0] t_numer;
|
|
reg [lpm_widthn-1:0] t_q;
|
|
reg [lpm_widthd-1:0] t_denom;
|
|
reg [lpm_widthd-1:0] t_r;
|
|
reg sign_q;
|
|
reg sign_r;
|
|
reg sign_n;
|
|
reg sign_d;
|
|
reg [8*5:1] lpm_remainderpositive;
|
|
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
integer rsig;
|
|
integer pipe_ptr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
tri0 clock;
|
|
tri1 clken;
|
|
|
|
wire i_aclr;
|
|
wire i_clock;
|
|
wire i_clken;
|
|
buf (i_aclr, aclr);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_HINT_EVALUATION eva();
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
// check if lpm_widthn > 0
|
|
if (lpm_widthn <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTHN must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check if lpm_widthd > 0
|
|
if (lpm_widthd <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTHD must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check for valid lpm_nrepresentation value
|
|
if ((lpm_nrepresentation != "SIGNED") && (lpm_nrepresentation != "UNSIGNED"))
|
|
begin
|
|
$display("Error! LPM_NREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check for valid lpm_drepresentation value
|
|
if ((lpm_drepresentation != "SIGNED") && (lpm_drepresentation != "UNSIGNED"))
|
|
begin
|
|
$display("Error! LPM_DREPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check for valid lpm_remainderpositive value
|
|
lpm_remainderpositive = eva.GET_PARAMETER_VALUE(lpm_hint, "LPM_REMAINDERPOSITIVE");
|
|
if ((lpm_remainderpositive == "TRUE") &&
|
|
(lpm_remainderpositive == "FALSE"))
|
|
begin
|
|
$display("Error! LPM_REMAINDERPOSITIVE value must be \"TRUE\" or \"FALSE\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i = 0; i <= (lpm_pipeline+1); i = i + 1)
|
|
begin
|
|
quotient_pipe[i] <= {lpm_widthn{1'b0}};
|
|
remain_pipe[i] <= {lpm_widthd{1'b0}};
|
|
end
|
|
|
|
pipe_ptr = 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(numer or denom or lpm_remainderpositive)
|
|
begin
|
|
sign_q = 1'b0;
|
|
sign_r = 1'b0;
|
|
sign_n = 1'b0;
|
|
sign_d = 1'b0;
|
|
t_numer = numer;
|
|
t_denom = denom;
|
|
|
|
if (lpm_nrepresentation == "SIGNED")
|
|
if (numer[lpm_widthn-1] == 1'b1)
|
|
begin
|
|
t_numer = ~numer + 1; // numer is negative number
|
|
sign_n = 1'b1;
|
|
end
|
|
|
|
if (lpm_drepresentation == "SIGNED")
|
|
if (denom[lpm_widthd-1] == 1'b1)
|
|
begin
|
|
t_denom = ~denom + 1; // denom is negative numbrt
|
|
sign_d = 1'b1;
|
|
end
|
|
|
|
t_q = t_numer / t_denom; // get quotient
|
|
t_r = t_numer % t_denom; // get remainder
|
|
sign_q = sign_n ^ sign_d;
|
|
sign_r = (t_r != {lpm_widthd{1'b0}}) ? sign_n : 1'b0;
|
|
|
|
// Pipeline the result
|
|
tmp_quotient = (sign_q == 1'b1) ? (~t_q + 1) : t_q;
|
|
tmp_remain = (sign_r == 1'b1) ? (~t_r + 1) : t_r;
|
|
|
|
// Recalculate the quotient and remainder if remainder is negative number
|
|
// and LPM_REMAINDERPOSITIVE=TRUE.
|
|
if ((sign_r) && (lpm_remainderpositive == "TRUE"))
|
|
begin
|
|
tmp_quotient = tmp_quotient + ((sign_d == 1'b1) ? 1 : -1 );
|
|
tmp_remain = tmp_remain + t_denom;
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= (lpm_pipeline+1); i = i + 1)
|
|
begin
|
|
quotient_pipe[i] <= {lpm_widthn{1'b0}};
|
|
remain_pipe[i] <= {lpm_widthd{1'b0}};
|
|
end
|
|
pipe_ptr <= 0;
|
|
end
|
|
else if (i_clken)
|
|
begin
|
|
quotient_pipe[pipe_ptr] <= tmp_quotient;
|
|
remain_pipe[pipe_ptr] <= tmp_remain;
|
|
|
|
if (lpm_pipeline > 1)
|
|
pipe_ptr <= (pipe_ptr + 1) % lpm_pipeline;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign quotient = (lpm_pipeline > 0) ? quotient_pipe[pipe_ptr] : tmp_quotient;
|
|
assign remain = (lpm_pipeline > 0) ? remain_pipe[pipe_ptr] : tmp_remain;
|
|
|
|
endmodule // lpm_divide
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_abs
|
|
//
|
|
// Description : Parameterized absolute value megafunction. This megafunction
|
|
// requires the input data to be signed number.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Return absolute value of data and the overflow status
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_abs (
|
|
data, // Signed number (Required)
|
|
result, // Absolute value of data[].
|
|
overflow // High if data = -2 ^ (LPM_WIDTH-1).
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and result[] ports.(Required)
|
|
parameter lpm_type = "lpm_abs";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
output overflow;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result_tmp;
|
|
reg overflow;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
begin
|
|
result_tmp = (data[lpm_width-1] == 1) ? (~data) + 1 : data;
|
|
overflow = (data[lpm_width-1] == 1) ? (result_tmp == (1<<(lpm_width-1))) : 0;
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign result = result_tmp;
|
|
|
|
endmodule // lpm_abs
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_counter
|
|
//
|
|
// Description : Parameterized counter megafunction. The lpm_counter
|
|
// megafunction is a binary counter that features an up,
|
|
// down, or up/down counter with optional synchronous or
|
|
// asynchronous clear, set, and load ports.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from the counter and carry-out of the MSB.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_counter (
|
|
clock, // Positive-edge-triggered clock. (Required)
|
|
clk_en, // Clock enable input. Enables all synchronous activities.
|
|
cnt_en, // Count enable input. Disables the count when low (0) without
|
|
// affecting sload, sset, or sclr.
|
|
updown, // Controls the direction of the count. High (1) = count up.
|
|
// Low (0) = count down.
|
|
aclr, // Asynchronous clear input.
|
|
aset, // Asynchronous set input.
|
|
aload, // Asynchronous load input. Asynchronously loads the counter with
|
|
// the value on the data input.
|
|
sclr, // Synchronous clear input. Clears the counter on the next active
|
|
// clock edge.
|
|
sset, // Synchronous set input. Sets the counter on the next active clock edge.
|
|
sload, // Synchronous load input. Loads the counter with data[] on the next
|
|
// active clock edge.
|
|
data, // Parallel data input to the counter.
|
|
cin, // Carry-in to the low-order bit.
|
|
q, // Data output from the counter.
|
|
cout, // Carry-out of the MSB.
|
|
eq // Counter decode output. Active high when the counter reaches the specified
|
|
// count value.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; //The number of bits in the count, or the width of the q[]
|
|
// and data[] ports, if they are used. (Required)
|
|
parameter lpm_direction = "UNUSED"; // Direction of the count.
|
|
parameter lpm_modulus = 0; // The maximum count, plus one.
|
|
parameter lpm_avalue = "UNUSED"; // Constant value that is loaded when aset is high.
|
|
parameter lpm_svalue = "UNUSED"; // Constant value that is loaded on the rising edge
|
|
// of clock when sset is high.
|
|
parameter lpm_pvalue = "UNUSED";
|
|
parameter lpm_port_updown = "PORT_CONNECTIVITY";
|
|
parameter lpm_type = "lpm_counter";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input clock;
|
|
input clk_en;
|
|
input cnt_en;
|
|
input updown;
|
|
input aclr;
|
|
input aset;
|
|
input aload;
|
|
input sclr;
|
|
input sset;
|
|
input sload;
|
|
input [lpm_width-1:0] data;
|
|
input cin;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
output cout;
|
|
output [15:0] eq;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] tmp_count;
|
|
reg [lpm_width-1:0] adata;
|
|
|
|
reg use_adata;
|
|
reg tmp_updown;
|
|
reg [lpm_width:0] tmp_modulus;
|
|
reg [lpm_width:0] max_modulus;
|
|
reg [lpm_width-1:0] svalue;
|
|
reg [lpm_width-1:0] avalue;
|
|
reg [lpm_width-1:0] pvalue;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire w_updown;
|
|
wire [lpm_width-1:0] final_count;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
|
|
tri1 clk_en;
|
|
tri1 cnt_en;
|
|
tri0 aclr;
|
|
tri0 aset;
|
|
tri0 aload;
|
|
tri0 sclr;
|
|
tri0 sset;
|
|
tri0 sload;
|
|
tri1 cin;
|
|
tri1 updown_z;
|
|
|
|
wire i_clk_en;
|
|
wire i_cnt_en;
|
|
wire i_aclr;
|
|
wire i_aset;
|
|
wire i_aload;
|
|
wire i_sclr;
|
|
wire i_sset;
|
|
wire i_sload;
|
|
wire i_cin;
|
|
wire i_updown;
|
|
buf (i_clk_en, clk_en);
|
|
buf (i_cnt_en, cnt_en);
|
|
buf (i_aclr, aclr);
|
|
buf (i_aset, aset);
|
|
buf (i_aload, aload);
|
|
buf (i_sclr, sclr);
|
|
buf (i_sset, sset);
|
|
buf (i_sload, sload);
|
|
buf (i_cin, cin);
|
|
buf (i_updown, updown_z);
|
|
|
|
// TASK DECLARATION
|
|
task string_to_reg;
|
|
input [8*40:1] string_value;
|
|
output [lpm_width-1:0] value;
|
|
|
|
reg [8*40:1] reg_s;
|
|
reg [8:1] digit;
|
|
reg [8:1] tmp;
|
|
reg [lpm_width-1:0] ivalue;
|
|
|
|
integer m;
|
|
|
|
begin
|
|
ivalue = {lpm_width{1'b0}};
|
|
reg_s = string_value;
|
|
for (m=1; m<=40; m=m+1)
|
|
begin
|
|
tmp = reg_s[320:313];
|
|
digit = tmp & 8'b00001111;
|
|
reg_s = reg_s << 8;
|
|
ivalue = ivalue * 10 + digit;
|
|
end
|
|
value = ivalue;
|
|
end
|
|
endtask
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
max_modulus = 1 << lpm_width;
|
|
|
|
// check if lpm_width < 0
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTH must be greater than 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
// check if lpm_modulus < 0
|
|
if (lpm_modulus < 0)
|
|
begin
|
|
$display("Error! LPM_MODULUS must be greater or equal to 0.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
// check if lpm_modulus > 1<<lpm_width
|
|
if (lpm_modulus > max_modulus)
|
|
begin
|
|
$display("Warning! LPM_MODULUS should be within 1 to 2^LPM_WIDTH. Assuming no modulus input.\n");
|
|
$display ("Time: %0t Instance: %m", $time);
|
|
end
|
|
// check if lpm_direction valid
|
|
if ((lpm_direction != "UNUSED") && (lpm_direction != "DEFAULT") &&
|
|
(lpm_direction != "UP") && (lpm_direction != "DOWN"))
|
|
begin
|
|
$display("Error! LPM_DIRECTION must be \"UP\" or \"DOWN\" if used.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_avalue == "UNUSED")
|
|
avalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_avalue, avalue);
|
|
|
|
if (lpm_svalue == "UNUSED")
|
|
svalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_svalue, svalue);
|
|
|
|
if (lpm_pvalue == "UNUSED")
|
|
pvalue = {lpm_width{1'b0}};
|
|
else
|
|
string_to_reg(lpm_pvalue, pvalue);
|
|
|
|
tmp_modulus = ((lpm_modulus == 0) || (lpm_modulus > max_modulus))
|
|
? max_modulus : lpm_modulus;
|
|
tmp_count = pvalue;
|
|
use_adata = 1'b0;
|
|
end
|
|
|
|
// NCSIM will only assigns 1'bZ to unconnected port at time 0fs + 1
|
|
// verilator lint_off STMTDLY
|
|
initial #0
|
|
// verilator lint_on STMTDLY
|
|
begin
|
|
// // check if lpm_direction valid
|
|
if ((lpm_direction != "UNUSED") && (lpm_direction != "DEFAULT") && (updown !== 1'bz) &&
|
|
(lpm_port_updown == "PORT_CONNECTIVITY"))
|
|
begin
|
|
$display("Error! LPM_DIRECTION and UPDOWN cannot be used at the same time.\n");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge i_aclr or posedge i_aset or posedge i_aload or posedge clock)
|
|
begin
|
|
if (i_aclr || i_aset || i_aload)
|
|
use_adata <= 1'b1;
|
|
else if ($time > 0)
|
|
begin
|
|
if (i_clk_en)
|
|
begin
|
|
use_adata <= 1'b0;
|
|
|
|
if (i_sclr)
|
|
tmp_count <= 0;
|
|
else if (i_sset)
|
|
tmp_count <= svalue;
|
|
else if (i_sload)
|
|
tmp_count <= data;
|
|
else if (i_cnt_en && i_cin)
|
|
begin
|
|
if (w_updown)
|
|
tmp_count <= (final_count == tmp_modulus-1) ? 0
|
|
: final_count+1;
|
|
else
|
|
tmp_count <= (final_count == 0) ? tmp_modulus-1
|
|
: final_count-1;
|
|
end
|
|
else
|
|
tmp_count <= final_count;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(i_aclr or i_aset or i_aload or data or avalue)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
adata <= 0;
|
|
end
|
|
else if (i_aset)
|
|
begin
|
|
adata <= avalue;
|
|
end
|
|
else if (i_aload)
|
|
adata <= data;
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign q = final_count;
|
|
assign final_count = (use_adata == 1'b1) ? adata : tmp_count;
|
|
assign cout = (i_cin && (((w_updown==0) && (final_count==0)) ||
|
|
((w_updown==1) && ((final_count==tmp_modulus-1) ||
|
|
(final_count=={lpm_width{1'b1}}))) ))
|
|
? 1'b1 : 1'b0;
|
|
assign updown_z = updown;
|
|
assign w_updown = (lpm_port_updown == "PORT_USED") ? i_updown :
|
|
(lpm_port_updown == "PORT_UNUSED") ? ((lpm_direction == "DOWN") ? 1'b0 : 1'b1) :
|
|
((((lpm_direction == "UNUSED") || (lpm_direction == "DEFAULT")) && (i_updown == 1)) ||
|
|
(lpm_direction == "UP"))
|
|
? 1'b1 : 1'b0;
|
|
assign eq = {16{1'b0}};
|
|
|
|
endmodule // lpm_counter
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_latch
|
|
//
|
|
// Description : Parameterized latch megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from the latch.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_latch (
|
|
data, // Data input to the latch.
|
|
gate, // Latch enable input. High = flow-through, low = latch. (Required)
|
|
aclr, // Asynchronous clear input.
|
|
aset, // Asynchronous set input.
|
|
aconst,
|
|
q // Data output from the latch.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and q[] ports. (Required)
|
|
parameter lpm_avalue = "UNUSED"; // Constant value that is loaded when aset is high.
|
|
parameter lpm_pvalue = "UNUSED";
|
|
parameter lpm_type = "lpm_latch";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input gate;
|
|
input aclr;
|
|
input aset;
|
|
input aconst;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] q;
|
|
reg [lpm_width-1:0] avalue;
|
|
reg [lpm_width-1:0] pvalue;
|
|
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 [lpm_width-1:0] data;
|
|
tri0 aclr;
|
|
tri0 aset;
|
|
tri0 aconst;
|
|
|
|
wire i_aclr;
|
|
wire i_aset;
|
|
buf (i_aclr, aclr);
|
|
buf (i_aset, aset);
|
|
|
|
// TASK DECLARATION
|
|
task string_to_reg;
|
|
input [8*40:1] string_value;
|
|
output [lpm_width-1:0] value;
|
|
|
|
reg [8*40:1] reg_s;
|
|
reg [8:1] digit;
|
|
reg [8:1] tmp;
|
|
reg [lpm_width-1:0] ivalue;
|
|
|
|
integer m;
|
|
|
|
begin
|
|
ivalue = {lpm_width{1'b0}};
|
|
reg_s = string_value;
|
|
for (m=1; m<=40; m=m+1)
|
|
begin
|
|
tmp = reg_s[320:313];
|
|
digit = tmp & 8'b00001111;
|
|
reg_s = reg_s << 8;
|
|
ivalue = ivalue * 10 + digit;
|
|
end
|
|
value = ivalue;
|
|
end
|
|
endtask
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_pvalue != "UNUSED")
|
|
begin
|
|
string_to_reg(lpm_pvalue, pvalue);
|
|
q = pvalue;
|
|
end
|
|
|
|
if (lpm_avalue == "UNUSED")
|
|
avalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_avalue, avalue);
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or gate or i_aclr or i_aset or avalue)
|
|
begin
|
|
if (i_aclr)
|
|
q <= {lpm_width{1'b0}};
|
|
else if (i_aset)
|
|
q <= avalue;
|
|
else if (gate)
|
|
q <= data;
|
|
end
|
|
|
|
endmodule // lpm_latch
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_ff
|
|
//
|
|
// Description : Parameterized flipflop megafunction. The lpm_ff function
|
|
// contains features that are not available in the DFF, DFFE,
|
|
// DFFEA, TFF, and TFFE primitives, such as synchronous or
|
|
// asynchronous set, clear, and load inputs.
|
|
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from D or T flipflops.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_ff (
|
|
data, // T-type flipflop: Toggle enable
|
|
// D-type flipflop: Data input
|
|
|
|
clock, // Positive-edge-triggered clock. (Required)
|
|
enable, // Clock enable input.
|
|
aclr, // Asynchronous clear input.
|
|
aset, // Asynchronous set input.
|
|
|
|
aload, // Asynchronous load input. Asynchronously loads the flipflop with
|
|
// the value on the data input.
|
|
|
|
sclr, // Synchronous clear input.
|
|
sset, // Synchronous set input.
|
|
|
|
sload, // Synchronous load input. Loads the flipflop with the value on the
|
|
// data input on the next active clock edge.
|
|
|
|
q // Data output from D or T flipflops. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and q[] ports. (Required)
|
|
parameter lpm_avalue = "UNUSED"; // Constant value that is loaded when aset is high.
|
|
parameter lpm_svalue = "UNUSED"; // Constant value that is loaded on the rising edge
|
|
// of clock when sset is high.
|
|
parameter lpm_pvalue = "UNUSED";
|
|
parameter lpm_fftype = "DFF"; // Type of flipflop
|
|
parameter lpm_type = "lpm_ff";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input clock;
|
|
input enable;
|
|
input aclr;
|
|
input aset;
|
|
input aload;
|
|
input sclr;
|
|
input sset;
|
|
input sload ;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] tmp_q;
|
|
reg [lpm_width-1:0] adata;
|
|
reg use_adata;
|
|
reg [lpm_width-1:0] svalue;
|
|
reg [lpm_width-1:0] avalue;
|
|
reg [lpm_width-1:0] pvalue;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire [lpm_width-1:0] final_q;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri1 [lpm_width-1:0] data;
|
|
tri1 enable;
|
|
tri0 sload;
|
|
tri0 sclr;
|
|
tri0 sset;
|
|
tri0 aload;
|
|
tri0 aclr;
|
|
tri0 aset;
|
|
|
|
wire i_enable;
|
|
wire i_sload;
|
|
wire i_sclr;
|
|
wire i_sset;
|
|
wire i_aload;
|
|
wire i_aclr;
|
|
wire i_aset;
|
|
buf (i_enable, enable);
|
|
buf (i_sload, sload);
|
|
buf (i_sclr, sclr);
|
|
buf (i_sset, sset);
|
|
buf (i_aload, aload);
|
|
buf (i_aclr, aclr);
|
|
buf (i_aset, aset);
|
|
|
|
// TASK DECLARATION
|
|
task string_to_reg;
|
|
input [8*40:1] string_value;
|
|
output [lpm_width-1:0] value;
|
|
|
|
reg [8*40:1] reg_s;
|
|
reg [8:1] digit;
|
|
reg [8:1] tmp;
|
|
reg [lpm_width-1:0] ivalue;
|
|
|
|
integer m;
|
|
|
|
begin
|
|
ivalue = {lpm_width{1'b0}};
|
|
reg_s = string_value;
|
|
for (m=1; m<=40; m=m+1)
|
|
begin
|
|
tmp = reg_s[320:313];
|
|
digit = tmp & 8'b00001111;
|
|
reg_s = reg_s << 8;
|
|
ivalue = ivalue * 10 + digit;
|
|
end
|
|
value = ivalue;
|
|
end
|
|
endtask
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_fftype != "DFF") &&
|
|
(lpm_fftype != "TFF") &&
|
|
(lpm_fftype != "UNUSED")) // non-LPM 220 standard
|
|
begin
|
|
$display("Error! LPM_FFTYPE value must be \"DFF\" or \"TFF\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_avalue == "UNUSED")
|
|
avalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_avalue, avalue);
|
|
|
|
if (lpm_svalue == "UNUSED")
|
|
svalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_svalue, svalue);
|
|
|
|
if (lpm_pvalue == "UNUSED")
|
|
pvalue = {lpm_width{1'b0}};
|
|
else
|
|
string_to_reg(lpm_pvalue, pvalue);
|
|
|
|
tmp_q = pvalue;
|
|
use_adata = 1'b0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge i_aclr or posedge i_aset or posedge i_aload or posedge clock)
|
|
begin // Asynchronous process
|
|
if (i_aclr || i_aset || i_aload)
|
|
use_adata <= 1'b1;
|
|
else if ($time > 0)
|
|
begin // Synchronous process
|
|
if (i_enable)
|
|
begin
|
|
use_adata <= 1'b0;
|
|
|
|
if (i_sclr)
|
|
tmp_q <= 0;
|
|
else if (i_sset)
|
|
tmp_q <= svalue;
|
|
else if (i_sload) // Load data
|
|
tmp_q <= data;
|
|
else
|
|
begin
|
|
if (lpm_fftype == "TFF") // toggle
|
|
begin
|
|
for (i = 0; i < lpm_width; i=i+1)
|
|
if (data[i] == 1'b1)
|
|
tmp_q[i] <= ~final_q[i];
|
|
else
|
|
tmp_q[i] <= final_q[i];
|
|
end
|
|
else // DFF, load data
|
|
tmp_q <= data;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(i_aclr or i_aset or i_aload or data or avalue or pvalue)
|
|
begin
|
|
if (i_aclr === 1'b1)
|
|
adata <= {lpm_width{1'b0}};
|
|
else if (i_aclr === 1'bx)
|
|
adata <= {lpm_width{1'bx}};
|
|
else if (i_aset)
|
|
adata <= avalue;
|
|
else if (i_aload)
|
|
adata <= data;
|
|
else if ((i_aclr === 1'b0) && ($time == 0))
|
|
adata <= pvalue;
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign q = final_q;
|
|
assign final_q = (use_adata == 1'b1) ? adata : tmp_q;
|
|
|
|
endmodule // lpm_ff
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_shiftreg
|
|
//
|
|
// Description : Parameterized shift register megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from the shift register and the Serial shift data output.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_shiftreg (
|
|
data, // Data input to the shift register.
|
|
clock, // Positive-edge-triggered clock. (Required)
|
|
enable, // Clock enable input
|
|
shiftin, // Serial shift data input.
|
|
load, // Synchronous parallel load. High (1): load operation;
|
|
// low (0): shift operation.
|
|
aclr, // Asynchronous clear input.
|
|
aset, // Asynchronous set input.
|
|
sclr, // Synchronous clear input.
|
|
sset, // Synchronous set input.
|
|
q, // Data output from the shift register.
|
|
shiftout // Serial shift data output.
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and q ports. (Required)
|
|
parameter lpm_direction = "LEFT"; // Values are "LEFT", "RIGHT", and "UNUSED".
|
|
parameter lpm_avalue = "UNUSED"; // Constant value that is loaded when aset is high.
|
|
parameter lpm_svalue = "UNUSED"; // Constant value that is loaded on the rising edge
|
|
// of clock when sset is high.
|
|
parameter lpm_pvalue = "UNUSED";
|
|
parameter lpm_type = "lpm_shiftreg";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input clock;
|
|
input enable;
|
|
input shiftin;
|
|
input load;
|
|
input aclr;
|
|
input aset;
|
|
input sclr;
|
|
input sset;
|
|
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
output shiftout;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] tmp_q;
|
|
reg abit;
|
|
reg [lpm_width-1:0] svalue;
|
|
reg [lpm_width-1:0] avalue;
|
|
reg [lpm_width-1:0] pvalue;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire tmp_shiftout;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri1 enable;
|
|
tri1 shiftin;
|
|
tri0 load;
|
|
tri0 aclr;
|
|
tri0 aset;
|
|
tri0 sclr;
|
|
tri0 sset;
|
|
|
|
wire i_enable;
|
|
wire i_shiftin;
|
|
wire i_load;
|
|
wire i_aclr;
|
|
wire i_aset;
|
|
wire i_sclr;
|
|
wire i_sset;
|
|
buf (i_enable, enable);
|
|
buf (i_shiftin, shiftin);
|
|
buf (i_load, load);
|
|
buf (i_aclr, aclr);
|
|
buf (i_aset, aset);
|
|
buf (i_sclr, sclr);
|
|
buf (i_sset, sset);
|
|
|
|
// TASK DECLARATION
|
|
task string_to_reg;
|
|
input [8*40:1] string_value;
|
|
output [lpm_width-1:0] value;
|
|
|
|
reg [8*40:1] reg_s;
|
|
reg [8:1] digit;
|
|
reg [8:1] tmp;
|
|
reg [lpm_width-1:0] ivalue;
|
|
|
|
integer m;
|
|
|
|
begin
|
|
ivalue = {lpm_width{1'b0}};
|
|
reg_s = string_value;
|
|
for (m=1; m<=40; m=m+1)
|
|
begin
|
|
tmp = reg_s[320:313];
|
|
digit = tmp & 8'b00001111;
|
|
reg_s = reg_s << 8;
|
|
ivalue = ivalue * 10 + digit;
|
|
end
|
|
value = ivalue;
|
|
end
|
|
endtask
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0 (ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_direction != "LEFT") &&
|
|
(lpm_direction != "RIGHT") &&
|
|
(lpm_direction != "UNUSED")) // non-LPM 220 standard
|
|
begin
|
|
$display("Error! LPM_DIRECTION value must be \"LEFT\" or \"RIGHT\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_avalue == "UNUSED")
|
|
avalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_avalue, avalue);
|
|
|
|
if (lpm_svalue == "UNUSED")
|
|
svalue = {lpm_width{1'b1}};
|
|
else
|
|
string_to_reg(lpm_svalue, svalue);
|
|
|
|
if (lpm_pvalue == "UNUSED")
|
|
pvalue = {lpm_width{1'b0}};
|
|
else
|
|
string_to_reg(lpm_pvalue, pvalue);
|
|
|
|
tmp_q = pvalue;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(i_aclr or i_aset or avalue)
|
|
begin
|
|
if (i_aclr)
|
|
tmp_q <= {lpm_width{1'b0}};
|
|
else if (i_aset)
|
|
tmp_q <= avalue;
|
|
end
|
|
|
|
always @(posedge clock)
|
|
begin
|
|
if (i_aclr)
|
|
tmp_q <= (i_aset) ? {lpm_width{1'bx}} : {lpm_width{1'b0}};
|
|
else if (i_aset)
|
|
tmp_q <= avalue;
|
|
else
|
|
begin
|
|
if (i_enable)
|
|
begin
|
|
if (i_sclr)
|
|
tmp_q <= {lpm_width{1'b0}};
|
|
else if (i_sset)
|
|
tmp_q <= svalue;
|
|
else if (i_load)
|
|
tmp_q <= data;
|
|
else if (!i_load)
|
|
begin
|
|
if ((lpm_direction == "LEFT") || (lpm_direction == "UNUSED"))
|
|
{abit,tmp_q} <= {tmp_q,i_shiftin};
|
|
else if (lpm_direction == "RIGHT")
|
|
{tmp_q,abit} <= {i_shiftin,tmp_q};
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign tmp_shiftout = (lpm_direction == "RIGHT") ? tmp_q[0]
|
|
: tmp_q[lpm_width-1];
|
|
assign q = tmp_q;
|
|
assign shiftout = tmp_shiftout;
|
|
|
|
endmodule // lpm_shiftreg
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_ram_dq
|
|
//
|
|
// Description : Parameterized RAM with separate input and output ports megafunction.
|
|
// lpm_ram_dq implement asynchronous memory or memory with synchronous
|
|
// inputs and/or outputs.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from the memory.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_ram_dq (
|
|
data, // Data input to the memory. (Required)
|
|
address, // Address input to the memory. (Required)
|
|
inclock, // Synchronizes memory loading.
|
|
outclock, // Synchronizes q outputs from memory.
|
|
we, // Write enable input. Enables write operations to the memory when high. (Required)
|
|
q // Data output from the memory. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of data[] and q[] ports. (Required)
|
|
parameter lpm_widthad = 1; // Width of the address port. (Required)
|
|
parameter lpm_numwords = 1 << lpm_widthad; // Number of words stored in memory.
|
|
parameter lpm_indata = "REGISTERED"; // Controls whether the data port is registered.
|
|
parameter lpm_address_control = "REGISTERED"; // Controls whether the address and we ports are registered.
|
|
parameter lpm_outdata = "REGISTERED"; // Controls whether the q ports are registered.
|
|
parameter lpm_file = "UNUSED"; // Name of the file containing RAM initialization data.
|
|
parameter use_eab = "ON"; // Specified whether to use the EAB or not.
|
|
parameter intended_device_family = "Stratix";
|
|
parameter lpm_type = "lpm_ram_dq";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthad-1:0] address;
|
|
input inclock;
|
|
input outclock;
|
|
input we;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
|
|
reg [lpm_width-1:0] tmp_q;
|
|
reg [lpm_width-1:0] pdata;
|
|
reg [lpm_width-1:0] in_data;
|
|
reg [lpm_widthad-1:0] paddress;
|
|
reg pwe;
|
|
reg [lpm_width-1:0] ZEROS, ONES, UNKNOWN;
|
|
`ifdef VERILATOR
|
|
reg [`LPM_MAX_NAME_SZ*8:1] ram_initf;
|
|
`else
|
|
reg [8*256:1] ram_initf;
|
|
`endif
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 inclock;
|
|
tri0 outclock;
|
|
|
|
wire i_inclock;
|
|
wire i_outclock;
|
|
buf (i_inclock, inclock);
|
|
buf (i_outclock, outclock);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_DEVICE_FAMILIES dev ();
|
|
LPM_MEMORY_INITIALIZATION mem ();
|
|
|
|
// FUNCTON DECLARATION
|
|
// Check the validity of the address.
|
|
function ValidAddress;
|
|
input [lpm_widthad-1:0] paddress;
|
|
|
|
begin
|
|
ValidAddress = 1'b0;
|
|
if (^paddress === {lpm_widthad{1'bx}})
|
|
begin
|
|
$display("%t:Error! Invalid address.\n", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if (paddress >= lpm_numwords)
|
|
begin
|
|
$display("%t:Error! Address out of bound on RAM.\n", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else
|
|
ValidAddress = 1'b1;
|
|
end
|
|
endfunction
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
|
|
// Initialize the internal data register.
|
|
pdata = {lpm_width{1'b0}};
|
|
paddress = {lpm_widthad{1'b0}};
|
|
pwe = 1'b0;
|
|
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTH parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_widthad <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTHAD parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
// check for number of words out of bound
|
|
if ((lpm_numwords > (1 << lpm_widthad)) ||
|
|
(lpm_numwords <= (1 << (lpm_widthad-1))))
|
|
begin
|
|
$display("Error! The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_address_control != "REGISTERED") && (lpm_address_control != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_INDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
|
|
begin
|
|
$display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i=0; i < lpm_width; i=i+1)
|
|
begin
|
|
ZEROS[i] = 1'b0;
|
|
ONES[i] = 1'b1;
|
|
UNKNOWN[i] = 1'bX;
|
|
end
|
|
|
|
for (i = 0; i < lpm_numwords; i=i+1)
|
|
mem_data[i] = {lpm_width{1'b0}};
|
|
|
|
// load data to the RAM
|
|
if (lpm_file != "UNUSED")
|
|
begin
|
|
mem.convert_to_ver_file(lpm_file, lpm_width, ram_initf);
|
|
$readmemh(ram_initf, mem_data);
|
|
end
|
|
|
|
tmp_q = ZEROS;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge i_inclock)
|
|
begin
|
|
if (lpm_address_control == "REGISTERED")
|
|
begin
|
|
if ((we) && (use_eab != "ON") &&
|
|
(lpm_hint != "USE_EAB=ON"))
|
|
begin
|
|
if (lpm_indata == "REGISTERED")
|
|
mem_data[address] <= data;
|
|
else
|
|
mem_data[address] <= pdata;
|
|
end
|
|
paddress <= address;
|
|
pwe <= we;
|
|
end
|
|
if (lpm_indata == "REGISTERED")
|
|
pdata <= data;
|
|
end
|
|
|
|
always @(data)
|
|
begin
|
|
if (lpm_indata == "UNREGISTERED")
|
|
pdata <= data;
|
|
end
|
|
|
|
always @(address)
|
|
begin
|
|
if (lpm_address_control == "UNREGISTERED")
|
|
paddress <= address;
|
|
end
|
|
|
|
always @(we)
|
|
begin
|
|
if (lpm_address_control == "UNREGISTERED")
|
|
pwe <= we;
|
|
end
|
|
|
|
always @(pdata or paddress or pwe)
|
|
begin :UNREGISTERED_INCLOCK
|
|
if (ValidAddress(paddress))
|
|
begin
|
|
if ((lpm_address_control == "UNREGISTERED") && (pwe))
|
|
mem_data[paddress] <= pdata;
|
|
end
|
|
else
|
|
begin
|
|
if (lpm_outdata == "UNREGISTERED")
|
|
tmp_q <= {lpm_width{1'bx}};
|
|
end
|
|
end
|
|
|
|
always @(posedge i_outclock)
|
|
begin
|
|
if (lpm_outdata == "REGISTERED")
|
|
begin
|
|
if (ValidAddress(paddress))
|
|
tmp_q <= mem_data[paddress];
|
|
else
|
|
tmp_q <= {lpm_width{1'bx}};
|
|
end
|
|
end
|
|
|
|
always @(i_inclock or pwe or paddress or pdata)
|
|
begin
|
|
if ((lpm_address_control == "REGISTERED") && (pwe))
|
|
if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
|
|
begin
|
|
if (i_inclock == 1'b0)
|
|
mem_data[paddress] = pdata;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign q = (lpm_outdata == "UNREGISTERED") ? mem_data[paddress] : tmp_q;
|
|
|
|
endmodule // lpm_ram_dq
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_ram_dp
|
|
//
|
|
// Description : Parameterized dual-port RAM megafunction.
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected: Data output from the memory.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_ram_dp (
|
|
data, // Data input to the memory. (Required)
|
|
rdaddress, // Read address input to the memory. (Required)
|
|
wraddress, // Write address input to the memory. (Required)
|
|
rdclock, // Positive-edge-triggered clock for read operation.
|
|
rdclken, // Clock enable for rdclock.
|
|
wrclock, // Positive-edge-triggered clock for write operation.
|
|
wrclken, // Clock enable for wrclock.
|
|
rden, // Read enable input. Disables reading when low (0).
|
|
wren, // Write enable input. (Required)
|
|
q // Data output from the memory. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the data[] and q[] ports. (Required)
|
|
parameter lpm_widthad = 1; // Width of the rdaddress[] and wraddress[] ports. (Required)
|
|
parameter lpm_numwords = 1 << lpm_widthad; // Number of words stored in memory.
|
|
parameter lpm_indata = "REGISTERED"; // Determines the clock used by the data port.
|
|
parameter lpm_rdaddress_control = "REGISTERED"; // Determines the clock used by the rdaddress and rden ports.
|
|
parameter lpm_wraddress_control = "REGISTERED"; // Determines the clock used by the wraddress and wren ports.
|
|
parameter lpm_outdata = "REGISTERED"; // Determines the clock used by the q[] pxort.
|
|
parameter lpm_file = "UNUSED"; // Name of the file containing RAM initialization data.
|
|
parameter use_eab = "ON"; // Specified whether to use the EAB or not.
|
|
parameter rden_used = "TRUE"; // Specified whether to use the rden port or not.
|
|
parameter intended_device_family = "Stratix";
|
|
parameter lpm_type = "lpm_ram_dp";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthad-1:0] rdaddress;
|
|
input [lpm_widthad-1:0] wraddress;
|
|
input rdclock;
|
|
input rdclken;
|
|
input wrclock;
|
|
input wrclken;
|
|
input rden;
|
|
input wren;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] mem_data [(1<<lpm_widthad)-1:0];
|
|
reg [lpm_width-1:0] i_data_reg, i_data_tmp, i_q_reg, i_q_tmp;
|
|
reg [lpm_widthad-1:0] i_wraddress_reg, i_wraddress_tmp;
|
|
reg [lpm_widthad-1:0] i_rdaddress_reg, i_rdaddress_tmp;
|
|
reg i_wren_reg, i_wren_tmp, i_rden_reg, i_rden_tmp;
|
|
`ifdef VERILATOR
|
|
reg [`LPM_MAX_NAME_SZ*8:1] ram_initf;
|
|
`else
|
|
reg [8*256:1] ram_initf;
|
|
`endif
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i, i_numwords;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 wrclock;
|
|
tri1 wrclken;
|
|
tri0 rdclock;
|
|
tri1 rdclken;
|
|
tri0 wren;
|
|
tri1 rden;
|
|
|
|
wire i_inclock;
|
|
wire i_inclocken;
|
|
wire i_outclock;
|
|
wire i_outclocken;
|
|
wire i_wren;
|
|
wire i_rden;
|
|
|
|
buf (i_inclock, wrclock);
|
|
buf (i_inclocken, wrclken);
|
|
buf (i_outclock, rdclock);
|
|
buf (i_outclocken, rdclken);
|
|
buf (i_wren, wren);
|
|
buf (i_rden, rden);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_DEVICE_FAMILIES dev ();
|
|
LPM_MEMORY_INITIALIZATION mem ();
|
|
|
|
// FUNCTON DECLARATION
|
|
function ValidAddress;
|
|
input [lpm_widthad-1:0] paddress;
|
|
|
|
begin
|
|
ValidAddress = 1'b0;
|
|
if (^paddress === {lpm_widthad{1'bx}})
|
|
begin
|
|
$display("%t:Error! Invalid address.\n", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else if (paddress >= lpm_numwords)
|
|
begin
|
|
$display("%t:Error! Address out of bound on RAM.\n", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
else
|
|
ValidAddress = 1'b1;
|
|
end
|
|
endfunction
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
// Check for invalid parameters
|
|
if (lpm_width < 1)
|
|
begin
|
|
$display("Error! lpm_width parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (lpm_widthad < 1)
|
|
begin
|
|
$display("Error! lpm_widthad parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! lpm_indata must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! lpm_outdata must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if ((lpm_wraddress_control != "REGISTERED") && (lpm_wraddress_control != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! lpm_wraddress_control must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
if ((lpm_rdaddress_control != "REGISTERED") && (lpm_rdaddress_control != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! lpm_rdaddress_control must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
|
|
begin
|
|
$display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
// Initialize mem_data
|
|
i_numwords = (lpm_numwords) ? lpm_numwords : (1<<lpm_widthad);
|
|
|
|
if (lpm_file == "UNUSED")
|
|
for (i=0; i<i_numwords; i=i+1)
|
|
mem_data[i] = {lpm_width{1'b0}};
|
|
else
|
|
begin
|
|
mem.convert_to_ver_file(lpm_file, lpm_width, ram_initf);
|
|
$readmemh(ram_initf, mem_data);
|
|
end
|
|
|
|
// Initialize registers
|
|
i_data_reg = {lpm_width{1'b0}};
|
|
i_wraddress_reg = {lpm_widthad{1'b0}};
|
|
i_rdaddress_reg = {lpm_widthad{1'b0}};
|
|
i_wren_reg = 1'b0;
|
|
if (rden_used == "TRUE")
|
|
i_rden_reg = 1'b0;
|
|
else
|
|
i_rden_reg = 1'b1;
|
|
|
|
// Initialize output
|
|
i_q_reg = {lpm_width{1'b0}};
|
|
if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
|
|
begin
|
|
i_q_tmp = {lpm_width{1'b1}};
|
|
end
|
|
else
|
|
i_q_tmp = {lpm_width{1'b0}};
|
|
end
|
|
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
|
|
always @(posedge i_inclock)
|
|
begin
|
|
if (lpm_indata == "REGISTERED")
|
|
if ((i_inclocken == 1'b1) && ($time > 0))
|
|
i_data_reg <= data;
|
|
|
|
if (lpm_wraddress_control == "REGISTERED")
|
|
if ((i_inclocken == 1'b1) && ($time > 0))
|
|
begin
|
|
i_wraddress_reg <= wraddress;
|
|
i_wren_reg <= i_wren;
|
|
end
|
|
|
|
end
|
|
|
|
always @(posedge i_outclock)
|
|
begin
|
|
if (lpm_outdata == "REGISTERED")
|
|
if ((i_outclocken == 1'b1) && ($time > 0))
|
|
begin
|
|
i_q_reg <= i_q_tmp;
|
|
end
|
|
|
|
if (lpm_rdaddress_control == "REGISTERED")
|
|
if ((i_outclocken == 1'b1) && ($time > 0))
|
|
begin
|
|
i_rdaddress_reg <= rdaddress;
|
|
i_rden_reg <= i_rden;
|
|
end
|
|
end
|
|
|
|
|
|
//=========
|
|
// Memory
|
|
//=========
|
|
|
|
always @(i_data_tmp or i_wren_tmp or i_wraddress_tmp or negedge i_inclock)
|
|
begin
|
|
if (i_wren_tmp == 1'b1)
|
|
if (ValidAddress(i_wraddress_tmp))
|
|
begin
|
|
if (((use_eab == "ON") || (lpm_hint == "USE_EAB=ON")) &&
|
|
(lpm_wraddress_control == "REGISTERED"))
|
|
begin
|
|
if (i_inclock == 1'b0)
|
|
mem_data[i_wraddress_tmp] <= i_data_tmp;
|
|
end
|
|
else
|
|
mem_data[i_wraddress_tmp] <= i_data_tmp;
|
|
end
|
|
end
|
|
|
|
always @(i_rden_tmp or i_rdaddress_tmp or mem_data[i_rdaddress_tmp])
|
|
begin
|
|
if (i_rden_tmp == 1'b1)
|
|
i_q_tmp = (ValidAddress(i_rdaddress_tmp))
|
|
? mem_data[i_rdaddress_tmp]
|
|
: {lpm_width{1'bx}};
|
|
end
|
|
|
|
|
|
//=======
|
|
// Sync
|
|
//=======
|
|
|
|
always @(wraddress or i_wraddress_reg)
|
|
i_wraddress_tmp = (lpm_wraddress_control == "REGISTERED")
|
|
? i_wraddress_reg
|
|
: wraddress;
|
|
always @(rdaddress or i_rdaddress_reg)
|
|
i_rdaddress_tmp = (lpm_rdaddress_control == "REGISTERED")
|
|
? i_rdaddress_reg
|
|
: rdaddress;
|
|
always @(i_wren or i_wren_reg)
|
|
i_wren_tmp = (lpm_wraddress_control == "REGISTERED")
|
|
? i_wren_reg
|
|
: i_wren;
|
|
always @(i_rden or i_rden_reg)
|
|
i_rden_tmp = (lpm_rdaddress_control == "REGISTERED")
|
|
? i_rden_reg
|
|
: i_rden;
|
|
always @(data or i_data_reg)
|
|
i_data_tmp = (lpm_indata == "REGISTERED")
|
|
? i_data_reg
|
|
: data;
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign q = (lpm_outdata == "REGISTERED") ? i_q_reg : i_q_tmp;
|
|
|
|
endmodule // lpm_ram_dp
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_ram_io
|
|
//
|
|
// Description : Parameterized RAM with a single I/O port megafunction
|
|
//
|
|
// Limitation : This megafunction is provided only for backward
|
|
// compatibility in Cyclone, Stratix, and Stratix GX designs;
|
|
// instead, Altera recommends using the altsyncram
|
|
// megafunction
|
|
//
|
|
// Results expected: Output of RAM content at bi-directional DIO.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_ram_io ( dio, inclock, outclock, we, memenab, outenab, address );
|
|
|
|
// PARAMETER DECLARATION
|
|
parameter lpm_type = "lpm_ram_io";
|
|
parameter lpm_width = 1;
|
|
parameter lpm_widthad = 1;
|
|
parameter lpm_numwords = 1<< lpm_widthad;
|
|
parameter lpm_indata = "REGISTERED";
|
|
parameter lpm_address_control = "REGISTERED";
|
|
parameter lpm_outdata = "REGISTERED";
|
|
parameter lpm_file = "UNUSED";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter use_eab = "ON";
|
|
parameter intended_device_family = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_widthad-1:0] address;
|
|
input inclock, outclock, we;
|
|
input memenab;
|
|
input outenab;
|
|
|
|
// INPUT/OUTPUT PORT DECLARATION
|
|
inout [lpm_width-1:0] dio;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] mem_data [lpm_numwords-1:0];
|
|
reg [lpm_width-1:0] tmp_io;
|
|
reg [lpm_width-1:0] tmp_q;
|
|
reg [lpm_width-1:0] pdio;
|
|
reg [lpm_widthad-1:0] paddress;
|
|
reg [lpm_widthad-1:0] paddress_tmp;
|
|
reg pwe;
|
|
`ifdef VERILATOR
|
|
reg [`LPM_MAX_NAME_SZ*8:1] ram_initf;
|
|
`else
|
|
reg [8*256:1] ram_initf;
|
|
`endif
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire [lpm_width-1:0] read_data;
|
|
wire i_inclock;
|
|
wire i_outclock;
|
|
wire i_memenab;
|
|
wire i_outenab;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 inclock;
|
|
tri0 outclock;
|
|
tri1 memenab;
|
|
tri1 outenab;
|
|
|
|
// INTERNAL BUF DECLARATION
|
|
buf (i_inclock, inclock);
|
|
buf (i_outclock, outclock);
|
|
buf (i_memenab, memenab);
|
|
buf (i_outenab, outenab);
|
|
|
|
|
|
// FUNCTON DECLARATION
|
|
function ValidAddress;
|
|
input [lpm_widthad-1:0] paddress;
|
|
|
|
begin
|
|
ValidAddress = 1'b0;
|
|
if (^paddress === {lpm_widthad{1'bx}})
|
|
begin
|
|
$display("%t:Error: Invalid address.", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
else if (paddress >= lpm_numwords)
|
|
begin
|
|
$display("%t:Error: Address out of bound on RAM.", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
else
|
|
ValidAddress = 1'b1;
|
|
end
|
|
endfunction
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_MEMORY_INITIALIZATION mem ();
|
|
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTH parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_widthad <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTHAD parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
// check for number of words out of bound
|
|
if ((lpm_numwords > (1 << lpm_widthad))
|
|
||(lpm_numwords <= (1 << (lpm_widthad-1))))
|
|
begin
|
|
$display("Error! The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_indata != "REGISTERED") && (lpm_indata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_INDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_address_control != "REGISTERED") && (lpm_address_control != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i = 0; i < lpm_numwords; i=i+1)
|
|
mem_data[i] = {lpm_width{1'b0}};
|
|
|
|
// Initialize input/output
|
|
pwe = 1'b0;
|
|
pdio = {lpm_width{1'b0}};
|
|
paddress = {lpm_widthad{1'b0}};
|
|
paddress_tmp = {lpm_widthad{1'b0}};
|
|
tmp_io = {lpm_width{1'b0}};
|
|
tmp_q = {lpm_width{1'b0}};
|
|
|
|
// load data to the RAM
|
|
if (lpm_file != "UNUSED")
|
|
begin
|
|
mem.convert_to_ver_file(lpm_file, lpm_width, ram_initf);
|
|
$readmemh(ram_initf, mem_data);
|
|
end
|
|
end
|
|
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(dio)
|
|
begin
|
|
if (lpm_indata == "UNREGISTERED")
|
|
pdio <= dio;
|
|
end
|
|
|
|
always @(address)
|
|
begin
|
|
if (lpm_address_control == "UNREGISTERED")
|
|
paddress <= address;
|
|
end
|
|
|
|
|
|
always @(we)
|
|
begin
|
|
if (lpm_address_control == "UNREGISTERED")
|
|
pwe <= we;
|
|
end
|
|
|
|
always @(posedge i_inclock)
|
|
begin
|
|
if (lpm_indata == "REGISTERED")
|
|
pdio <= dio;
|
|
|
|
if (lpm_address_control == "REGISTERED")
|
|
begin
|
|
paddress <= address;
|
|
pwe <= we;
|
|
end
|
|
end
|
|
|
|
always @(pdio or paddress or pwe or i_memenab)
|
|
begin
|
|
if (ValidAddress(paddress))
|
|
begin
|
|
paddress_tmp <= paddress;
|
|
if (lpm_address_control == "UNREGISTERED")
|
|
if (pwe && i_memenab)
|
|
mem_data[paddress] <= pdio;
|
|
end
|
|
else
|
|
begin
|
|
if (lpm_outdata == "UNREGISTERED")
|
|
tmp_q <= {lpm_width{1'bx}};
|
|
end
|
|
end
|
|
|
|
always @(read_data)
|
|
begin
|
|
if (lpm_outdata == "UNREGISTERED")
|
|
tmp_q <= read_data;
|
|
end
|
|
|
|
always @(negedge i_inclock or pdio)
|
|
begin
|
|
if (lpm_address_control == "REGISTERED")
|
|
if ((use_eab == "ON") || (lpm_hint == "USE_EAB=ON"))
|
|
if (pwe && i_memenab && (i_inclock == 1'b0))
|
|
mem_data[paddress] = pdio;
|
|
end
|
|
|
|
always @(posedge i_inclock)
|
|
begin
|
|
if (lpm_address_control == "REGISTERED")
|
|
if ((use_eab == "OFF") && pwe && i_memenab)
|
|
mem_data[paddress] <= pdio;
|
|
end
|
|
|
|
always @(posedge i_outclock)
|
|
begin
|
|
if (lpm_outdata == "REGISTERED")
|
|
tmp_q <= mem_data[paddress];
|
|
end
|
|
|
|
always @(i_memenab or i_outenab or tmp_q)
|
|
begin
|
|
if (i_memenab && i_outenab)
|
|
tmp_io = tmp_q;
|
|
else if ((!i_memenab) || (i_memenab && (!i_outenab)))
|
|
tmp_io = {lpm_width{1'bz}};
|
|
end
|
|
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign dio = tmp_io;
|
|
assign read_data = mem_data[paddress_tmp];
|
|
|
|
endmodule // lpm_ram_io
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_rom
|
|
//
|
|
// Description : Parameterized ROM megafunction. This megafunction is provided
|
|
// only for backward compatibility in Cyclone, Stratix, and
|
|
// Stratix GX designs; instead, Altera recommends using the
|
|
// altsyncram megafunction.
|
|
//
|
|
// Limitation : This option is available for all Altera devices supported by
|
|
// the Quartus II software except MAX 3000 and MAX 7000 devices.
|
|
//
|
|
// Results expected: Output of memory.
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_rom (
|
|
address, // Address input to the memory. (Required)
|
|
inclock, // Clock for input registers.
|
|
outclock, // Clock for output registers.
|
|
memenab, // Memory enable input.
|
|
q // Output of memory. (Required)
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1; // Width of the q[] port. (Required)
|
|
parameter lpm_widthad = 1; // Width of the address[] port. (Required)
|
|
parameter lpm_numwords = 0; // Number of words stored in memory.
|
|
parameter lpm_address_control = "REGISTERED"; // Indicates whether the address port is registered.
|
|
parameter lpm_outdata = "REGISTERED"; // Indicates whether the q and eq ports are registered.
|
|
parameter lpm_file = ""; // Name of the memory file containing ROM initialization data
|
|
parameter intended_device_family = "Stratix";
|
|
parameter lpm_type = "lpm_rom";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// LOCAL_PARAMETERS_BEGIN
|
|
|
|
parameter NUM_WORDS = (lpm_numwords == 0) ? (1 << lpm_widthad) : lpm_numwords;
|
|
|
|
// LOCAL_PARAMETERS_END
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_widthad-1:0] address;
|
|
input inclock;
|
|
input outclock;
|
|
input memenab;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] mem_data [0:NUM_WORDS-1];
|
|
reg [lpm_widthad-1:0] address_reg;
|
|
reg [lpm_width-1:0] tmp_q_reg;
|
|
`ifdef VERILATOR
|
|
reg [`LPM_MAX_NAME_SZ*8:1] rom_initf;
|
|
`else
|
|
reg [8*256:1] rom_initf;
|
|
`endif
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire [lpm_widthad-1:0] w_address;
|
|
wire [lpm_width-1:0] w_read_data;
|
|
wire i_inclock;
|
|
wire i_outclock;
|
|
wire i_memenab;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 inclock;
|
|
tri0 outclock;
|
|
tri1 memenab;
|
|
|
|
buf (i_inclock, inclock);
|
|
buf (i_outclock, outclock);
|
|
buf (i_memenab, memenab);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_DEVICE_FAMILIES dev ();
|
|
LPM_MEMORY_INITIALIZATION mem ();
|
|
|
|
// FUNCTON DECLARATION
|
|
// Check the validity of the address.
|
|
function ValidAddress;
|
|
input [lpm_widthad-1:0] address;
|
|
begin
|
|
ValidAddress = 1'b0;
|
|
if (^address == {lpm_widthad{1'bx}})
|
|
begin
|
|
$display("%d:Error: Invalid address.", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
else if (address >= NUM_WORDS)
|
|
begin
|
|
$display("%d:Error: Address out of bound on ROM.", $time);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
else
|
|
ValidAddress = 1'b1;
|
|
end
|
|
endfunction
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
// Initialize output
|
|
tmp_q_reg = {lpm_width{1'b0}};
|
|
address_reg = {lpm_widthad{1'b0}};
|
|
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTH parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (lpm_widthad <= 0)
|
|
begin
|
|
$display("Error! LPM_WIDTHAD parameter must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
// check for number of words out of bound
|
|
if ((NUM_WORDS > (1 << lpm_widthad)) ||
|
|
(NUM_WORDS <= (1 << (lpm_widthad-1))))
|
|
begin
|
|
$display("Error! The ceiling of log2(LPM_NUMWORDS) must equal to LPM_WIDTHAD.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_address_control != "REGISTERED") &&
|
|
(lpm_address_control != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_ADDRESS_CONTROL must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if ((lpm_outdata != "REGISTERED") && (lpm_outdata != "UNREGISTERED"))
|
|
begin
|
|
$display("Error! LPM_OUTDATA must be \"REGISTERED\" or \"UNREGISTERED\".");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
|
|
begin
|
|
$display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
if (dev.FEATURE_FAMILY_MAX(intended_device_family) == 1)
|
|
begin
|
|
$display ("Error! LPM_ROM megafunction does not support %s devices.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
|
|
for (i = 0; i < NUM_WORDS; i=i+1)
|
|
mem_data[i] = {lpm_width{1'b0}};
|
|
|
|
// load data to the ROM
|
|
if ((lpm_file == "") || (lpm_file == "UNUSED"))
|
|
begin
|
|
$display("Warning: LPM_ROM must have data file for initialization.\n");
|
|
$display ("Time: %0t Instance: %m", $time);
|
|
end
|
|
else
|
|
begin
|
|
mem.convert_to_ver_file(lpm_file, lpm_width, rom_initf);
|
|
$readmemh(rom_initf, mem_data);
|
|
end
|
|
end
|
|
|
|
always @(posedge i_inclock)
|
|
begin
|
|
if (lpm_address_control == "REGISTERED")
|
|
address_reg <= address; // address port is registered
|
|
end
|
|
|
|
always @(w_address or w_read_data)
|
|
begin
|
|
if (ValidAddress(w_address))
|
|
begin
|
|
if (lpm_outdata == "UNREGISTERED")
|
|
// Load the output register with the contents of the memory location
|
|
// pointed to by address[].
|
|
tmp_q_reg <= w_read_data;
|
|
end
|
|
else
|
|
begin
|
|
if (lpm_outdata == "UNREGISTERED")
|
|
tmp_q_reg <= {lpm_width{1'bx}};
|
|
end
|
|
end
|
|
|
|
always @(posedge i_outclock)
|
|
begin
|
|
if (lpm_outdata == "REGISTERED")
|
|
begin
|
|
if (ValidAddress(w_address))
|
|
tmp_q_reg <= w_read_data;
|
|
else
|
|
tmp_q_reg <= {lpm_width{1'bx}};
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign w_address = (lpm_address_control == "REGISTERED") ? address_reg : address;
|
|
assign w_read_data = mem_data[w_address];
|
|
assign q = (i_memenab) ? tmp_q_reg : {lpm_width{1'bz}};
|
|
|
|
endmodule // lpm_rom
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_fifo
|
|
//
|
|
// Description :
|
|
//
|
|
// Limitation :
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
`timescale 1 ps / 1 ps
|
|
|
|
module lpm_fifo ( data,
|
|
clock,
|
|
wrreq,
|
|
rdreq,
|
|
aclr,
|
|
sclr,
|
|
q,
|
|
usedw,
|
|
full,
|
|
empty );
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_widthu = 1;
|
|
parameter lpm_numwords = 2;
|
|
parameter lpm_showahead = "OFF";
|
|
parameter lpm_type = "lpm_fifo";
|
|
parameter lpm_hint = "";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input clock;
|
|
input wrreq;
|
|
input rdreq;
|
|
input aclr;
|
|
input sclr;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
output [lpm_widthu-1:0] usedw;
|
|
output full;
|
|
output empty;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] mem_data [(1<<lpm_widthu):0];
|
|
reg [lpm_width-1:0] tmp_data;
|
|
reg [lpm_widthu-1:0] count_id;
|
|
reg [lpm_widthu-1:0] read_id;
|
|
reg [lpm_widthu-1:0] write_id;
|
|
reg write_flag;
|
|
reg full_flag;
|
|
reg empty_flag;
|
|
reg [lpm_width-1:0] tmp_q;
|
|
|
|
reg [8*5:1] overflow_checking;
|
|
reg [8*5:1] underflow_checking;
|
|
reg [8*20:1] allow_rwcycle_when_full;
|
|
reg [8*20:1] intended_device_family;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire valid_rreq;
|
|
wire valid_wreq;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_DEVICE_FAMILIES dev ();
|
|
LPM_HINT_EVALUATION eva();
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display ("Error! LPM_WIDTH must be greater than 0.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
if (lpm_numwords <= 1)
|
|
begin
|
|
$display ("Error! LPM_NUMWORDS must be greater than or equal to 2.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
if ((lpm_widthu !=1) && (lpm_numwords > (1 << lpm_widthu)))
|
|
begin
|
|
$display ("Error! LPM_NUMWORDS must equal to the ceiling of log2(LPM_WIDTHU).");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
if (lpm_numwords <= (1 << (lpm_widthu - 1)))
|
|
begin
|
|
$display ("Error! LPM_WIDTHU is too big for the specified LPM_NUMWORDS.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
overflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "OVERFLOW_CHECKING");
|
|
if(overflow_checking == "")
|
|
overflow_checking = "ON";
|
|
else if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! OVERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
underflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "UNDERFLOW_CHECKING");
|
|
if(underflow_checking == "")
|
|
underflow_checking = "ON";
|
|
else if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! UNDERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
allow_rwcycle_when_full = eva.GET_PARAMETER_VALUE(lpm_hint, "ALLOW_RWCYCLE_WHEN_FULL");
|
|
if (allow_rwcycle_when_full == "")
|
|
allow_rwcycle_when_full = "OFF";
|
|
else if ((allow_rwcycle_when_full != "ON") && (allow_rwcycle_when_full != "OFF"))
|
|
begin
|
|
$display ("Error! ALLOW_RWCYCLE_WHEN_FULL must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
intended_device_family = eva.GET_PARAMETER_VALUE(lpm_hint, "INTENDED_DEVICE_FAMILY");
|
|
if (intended_device_family == "")
|
|
intended_device_family = "Stratix II";
|
|
else if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
|
|
begin
|
|
$display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
for (i = 0; i < (1<<lpm_widthu); i = i + 1)
|
|
begin
|
|
if (dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))
|
|
mem_data[i] <= {lpm_width{1'bx}};
|
|
else
|
|
mem_data[i] <= {lpm_width{1'b0}};
|
|
end
|
|
|
|
tmp_data <= 0;
|
|
if (dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family))
|
|
tmp_q <= {lpm_width{1'bx}};
|
|
else
|
|
tmp_q <= {lpm_width{1'b0}};
|
|
write_flag <= 1'b0;
|
|
count_id <= 0;
|
|
read_id <= 0;
|
|
write_id <= 0;
|
|
full_flag <= 1'b0;
|
|
empty_flag <= 1'b1;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge clock or posedge aclr)
|
|
begin
|
|
if (aclr)
|
|
begin
|
|
if (!(dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[0];
|
|
else
|
|
tmp_q <= {lpm_width{1'b0}};
|
|
end
|
|
|
|
read_id <= 0;
|
|
count_id <= 0;
|
|
full_flag <= 1'b0;
|
|
empty_flag <= 1'b1;
|
|
|
|
if (valid_wreq && (dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
begin
|
|
tmp_data <= data;
|
|
write_flag <= 1'b1;
|
|
end
|
|
else
|
|
write_id <= 0;
|
|
end
|
|
else if (sclr)
|
|
begin
|
|
if ((lpm_showahead == "ON") || (dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)))
|
|
tmp_q <= mem_data[0];
|
|
else
|
|
tmp_q <= mem_data[read_id];
|
|
read_id <= 0;
|
|
count_id <= 0;
|
|
full_flag <= 1'b0;
|
|
empty_flag <= 1'b1;
|
|
|
|
if (valid_wreq)
|
|
begin
|
|
tmp_data <= data;
|
|
write_flag <= 1'b1;
|
|
end
|
|
else
|
|
write_id <= 0;
|
|
end
|
|
else
|
|
begin
|
|
// Both WRITE and READ operations
|
|
if (valid_wreq && valid_rreq)
|
|
begin
|
|
tmp_data <= data;
|
|
write_flag <= 1'b1;
|
|
empty_flag <= 1'b0;
|
|
if (allow_rwcycle_when_full == "OFF")
|
|
begin
|
|
full_flag <= 1'b0;
|
|
end
|
|
|
|
if (read_id >= ((1 << lpm_widthu) - 1))
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[0];
|
|
else
|
|
tmp_q <= mem_data[read_id];
|
|
read_id <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[read_id + 1];
|
|
else
|
|
tmp_q <= mem_data[read_id];
|
|
read_id <= read_id + 1;
|
|
end
|
|
end
|
|
// WRITE operation only
|
|
else if (valid_wreq)
|
|
begin
|
|
tmp_data <= data;
|
|
empty_flag <= 1'b0;
|
|
write_flag <= 1'b1;
|
|
|
|
if (count_id >= (1 << lpm_widthu) - 1)
|
|
count_id <= 0;
|
|
else
|
|
count_id <= count_id + 1;
|
|
|
|
if ((count_id == lpm_numwords - 1) && (empty_flag == 1'b0))
|
|
full_flag <= 1'b1;
|
|
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[read_id];
|
|
end
|
|
// READ operation only
|
|
else if (valid_rreq)
|
|
begin
|
|
full_flag <= 1'b0;
|
|
|
|
if (count_id <= 0)
|
|
count_id <= {lpm_widthu{1'b1}};
|
|
else
|
|
count_id <= count_id - 1;
|
|
|
|
if ((count_id == 1) && (full_flag == 1'b0))
|
|
empty_flag <= 1'b1;
|
|
|
|
if (read_id >= ((1<<lpm_widthu) - 1))
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[0];
|
|
else
|
|
tmp_q <= mem_data[read_id];
|
|
read_id <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
tmp_q <= mem_data[read_id + 1];
|
|
else
|
|
tmp_q <= mem_data[read_id];
|
|
read_id <= read_id + 1;
|
|
end
|
|
end // if Both WRITE and READ operations
|
|
|
|
end // if aclr
|
|
end // @(posedge clock)
|
|
|
|
always @(negedge clock)
|
|
begin
|
|
if (write_flag)
|
|
begin
|
|
write_flag <= 1'b0;
|
|
mem_data[write_id] <= tmp_data;
|
|
|
|
if (sclr || aclr || (write_id >= ((1 << lpm_widthu) - 1)))
|
|
write_id <= 0;
|
|
else
|
|
write_id <= write_id + 1;
|
|
end
|
|
|
|
if ((lpm_showahead == "ON") && ($time > 0))
|
|
tmp_q <= ((write_flag == 1'b1) && (write_id == read_id)) ?
|
|
tmp_data : mem_data[read_id];
|
|
|
|
end // @(negedge clock)
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign valid_rreq = (underflow_checking == "OFF") ? rdreq : rdreq && ~empty_flag;
|
|
assign valid_wreq = (overflow_checking == "OFF") ? wrreq :
|
|
(allow_rwcycle_when_full == "ON") ? wrreq && (!full_flag || rdreq) :
|
|
wrreq && !full_flag;
|
|
assign q = tmp_q;
|
|
assign full = full_flag;
|
|
assign empty = empty_flag;
|
|
assign usedw = count_id;
|
|
|
|
endmodule // lpm_fifo
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_fifo_dc_dffpipe
|
|
//
|
|
// Description : Dual Clocks FIFO
|
|
//
|
|
// Limitation :
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_fifo_dc_dffpipe (d,
|
|
clock,
|
|
aclr,
|
|
q);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_delay = 1;
|
|
parameter lpm_width = 64;
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] d;
|
|
input clock;
|
|
input aclr;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] dffpipe [lpm_delay:0];
|
|
reg [lpm_width-1:0] q;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer delay;
|
|
integer i;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
delay <= lpm_delay - 1;
|
|
|
|
for (i = 0; i <= lpm_delay; i = i + 1)
|
|
dffpipe[i] <= 0;
|
|
q <= 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge aclr or posedge clock)
|
|
begin
|
|
if (aclr)
|
|
begin
|
|
for (i = 0; i <= lpm_delay; i = i + 1)
|
|
dffpipe[i] <= 0;
|
|
q <= 0;
|
|
end
|
|
else if (clock)
|
|
begin
|
|
if ((lpm_delay > 0) && ($time > 0))
|
|
begin
|
|
`ifdef VERILATOR
|
|
if (lpm_delay > 0)
|
|
`else
|
|
if (delay > 0)
|
|
`endif
|
|
begin
|
|
`ifdef VERILATOR
|
|
for (i = lpm_delay-1; i > 0; i = i - 1)
|
|
`else
|
|
for (i = delay; i > 0; i = i - 1)
|
|
`endif
|
|
dffpipe[i] <= dffpipe[i - 1];
|
|
q <= dffpipe[delay - 1];
|
|
end
|
|
else
|
|
q <= d;
|
|
|
|
dffpipe[0] <= d;
|
|
end
|
|
end
|
|
end // @(posedge aclr or posedge clock)
|
|
|
|
always @(d)
|
|
begin
|
|
if (lpm_delay == 0)
|
|
q <= d;
|
|
end // @(d)
|
|
|
|
endmodule // lpm_fifo_dc_dffpipe
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_fifo_dc_fefifo
|
|
//
|
|
// Description : Dual Clock FIFO
|
|
//
|
|
// Limitation :
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_fifo_dc_fefifo ( usedw_in,
|
|
wreq,
|
|
rreq,
|
|
clock,
|
|
aclr,
|
|
empty,
|
|
full);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_widthad = 1;
|
|
parameter lpm_numwords = 1;
|
|
parameter underflow_checking = "ON";
|
|
parameter overflow_checking = "ON";
|
|
parameter lpm_mode = "READ";
|
|
parameter lpm_hint = "";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_widthad-1:0] usedw_in;
|
|
input wreq;
|
|
input rreq;
|
|
input clock;
|
|
input aclr;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output empty;
|
|
output full;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [1:0] sm_empty;
|
|
reg lrreq;
|
|
reg i_empty;
|
|
reg i_full;
|
|
reg [8*5:1] i_overflow_checking;
|
|
reg [8*5:1] i_underflow_checking;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer almostfull;
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_HINT_EVALUATION eva();
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if ((lpm_mode != "READ") && (lpm_mode != "WRITE"))
|
|
begin
|
|
$display ("Error! LPM_MODE must be READ or WRITE.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
i_overflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "OVERFLOW_CHECKING");
|
|
if (i_overflow_checking == "")
|
|
begin
|
|
if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! OVERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
else
|
|
i_overflow_checking = overflow_checking;
|
|
end
|
|
else if ((i_overflow_checking != "ON") && (i_overflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! OVERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
i_underflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "UNDERFLOW_CHECKING");
|
|
if(i_underflow_checking == "")
|
|
begin
|
|
if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! UNDERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
else
|
|
i_underflow_checking = underflow_checking;
|
|
end
|
|
else if ((i_underflow_checking != "ON") && (i_underflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! UNDERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
sm_empty <= 2'b00;
|
|
i_empty <= 1'b1;
|
|
i_full <= 1'b0;
|
|
lrreq <= 1'b0;
|
|
|
|
if (lpm_numwords >= 3)
|
|
almostfull <= lpm_numwords - 3;
|
|
else
|
|
almostfull <= 0;
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge aclr)
|
|
begin
|
|
sm_empty <= 2'b00;
|
|
i_empty <= 1'b1;
|
|
i_full <= 1'b0;
|
|
lrreq <= 1'b0;
|
|
end // @(posedge aclr)
|
|
|
|
always @(posedge clock)
|
|
begin
|
|
if (i_underflow_checking == "OFF")
|
|
lrreq <= rreq;
|
|
else
|
|
lrreq <= rreq && ~i_empty;
|
|
|
|
if (~aclr && ($time > 0))
|
|
begin
|
|
if (lpm_mode == "READ")
|
|
begin
|
|
// verilator lint_off CASEX
|
|
casex (sm_empty)
|
|
// verilator lint_on CASEX
|
|
// state_empty
|
|
2'b00:
|
|
if (usedw_in != 0)
|
|
sm_empty <= 2'b01;
|
|
// state_non_empty
|
|
// verilator lint_off CMPCONST
|
|
2'b01:
|
|
if (rreq && (((usedw_in == 1) && !lrreq) || ((usedw_in == 2) && lrreq)))
|
|
sm_empty <= 2'b10;
|
|
// state_emptywait
|
|
2'b10:
|
|
if (usedw_in > 1)
|
|
sm_empty <= 2'b01;
|
|
else
|
|
sm_empty <= 2'b00;
|
|
// verilator lint_on CMPCONST
|
|
default:
|
|
begin
|
|
$display ("Error! Invalid sm_empty state in read mode.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
endcase
|
|
end // if (lpm_mode == "READ")
|
|
else if (lpm_mode == "WRITE")
|
|
begin
|
|
// verilator lint_off CASEX
|
|
casex (sm_empty)
|
|
// verilator lint_on CASEX
|
|
// state_empty
|
|
2'b00:
|
|
if (wreq)
|
|
sm_empty <= 2'b01;
|
|
// state_one
|
|
2'b01:
|
|
if (!wreq)
|
|
sm_empty <= 2'b11;
|
|
// state_non_empty
|
|
2'b11:
|
|
if (wreq)
|
|
sm_empty <= 2'b01;
|
|
else if (usedw_in == 0)
|
|
sm_empty <= 2'b00;
|
|
default:
|
|
begin
|
|
$display ("Error! Invalid sm_empty state in write mode.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
end
|
|
endcase
|
|
end // if (lpm_mode == "WRITE")
|
|
|
|
if (~aclr && (usedw_in >= almostfull) && ($time > 0))
|
|
i_full <= 1'b1;
|
|
else
|
|
i_full <= 1'b0;
|
|
end // if (~aclr && $time > 0)
|
|
end // @(posedge clock)
|
|
|
|
always @(sm_empty)
|
|
begin
|
|
i_empty <= !sm_empty[0];
|
|
end
|
|
// @(sm_empty)
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign empty = i_empty;
|
|
assign full = i_full;
|
|
endmodule // lpm_fifo_dc_fefifo
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_fifo_dc_async
|
|
//
|
|
// Description : Asynchronous Dual Clocks FIFO
|
|
//
|
|
// Limitation :
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_fifo_dc_async ( data,
|
|
rdclk,
|
|
wrclk,
|
|
aclr,
|
|
rdreq,
|
|
wrreq,
|
|
rdfull,
|
|
wrfull,
|
|
rdempty,
|
|
wrempty,
|
|
rdusedw,
|
|
wrusedw,
|
|
q);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_widthu = 1;
|
|
parameter lpm_numwords = 2;
|
|
parameter delay_rdusedw = 1;
|
|
parameter delay_wrusedw = 1;
|
|
parameter rdsync_delaypipe = 3;
|
|
parameter wrsync_delaypipe = 3;
|
|
parameter lpm_showahead = "OFF";
|
|
parameter underflow_checking = "ON";
|
|
parameter overflow_checking = "ON";
|
|
parameter lpm_hint = "INTENDED_DEVICE_FAMILY=Stratix";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input rdclk;
|
|
input wrclk;
|
|
input aclr;
|
|
input wrreq;
|
|
input rdreq;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output rdfull;
|
|
output wrfull;
|
|
output rdempty;
|
|
output wrempty;
|
|
output [lpm_widthu-1:0] rdusedw;
|
|
output [lpm_widthu-1:0] wrusedw;
|
|
output [lpm_width-1:0] q;
|
|
|
|
// INTERNAL REGISTERS DECLARATION
|
|
reg [lpm_width-1:0] mem_data [(1<<lpm_widthu)-1:0];
|
|
reg [lpm_width-1:0] i_data_tmp;
|
|
reg [lpm_widthu-1:0] i_rdptr;
|
|
reg [lpm_widthu-1:0] i_wrptr;
|
|
reg [lpm_widthu-1:0] i_wrptr_tmp;
|
|
reg i_rdenclock;
|
|
reg i_wren_tmp;
|
|
reg [lpm_widthu-1:0] i_wr_udwn;
|
|
reg [lpm_widthu-1:0] i_rd_udwn;
|
|
reg i_showahead_flag;
|
|
reg i_showahead_flag1;
|
|
reg [lpm_widthu:0] i_rdusedw;
|
|
reg [lpm_widthu-1:0] i_wrusedw;
|
|
reg [lpm_width-1:0] i_q_tmp;
|
|
|
|
reg [8*5:1] i_overflow_checking;
|
|
reg [8*5:1] i_underflow_checking;
|
|
reg [8*10:1] use_eab;
|
|
reg [8*20:1] intended_device_family;
|
|
|
|
// INTERNAL WIRE DECLARATION
|
|
wire w_rden;
|
|
wire w_wren;
|
|
wire w_rdempty;
|
|
wire w_wrempty;
|
|
wire w_rdfull;
|
|
wire w_wrfull;
|
|
wire [lpm_widthu-1:0] w_rdptrrg;
|
|
wire [lpm_widthu-1:0] w_wrdelaycycle;
|
|
wire [lpm_widthu-1:0] w_ws_nbrp;
|
|
wire [lpm_widthu-1:0] w_rs_nbwp;
|
|
wire [lpm_widthu-1:0] w_ws_dbrp;
|
|
wire [lpm_widthu-1:0] w_rs_dbwp;
|
|
wire [lpm_widthu-1:0] w_rd_dbuw;
|
|
wire [lpm_widthu-1:0] w_wr_dbuw;
|
|
wire [lpm_widthu-1:0] w_rdusedw;
|
|
wire [lpm_widthu-1:0] w_wrusedw;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
|
|
// LOCAL INTEGER DECLARATION
|
|
integer i;
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
LPM_DEVICE_FAMILIES dev ();
|
|
LPM_HINT_EVALUATION eva();
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if((lpm_showahead != "ON") && (lpm_showahead != "OFF"))
|
|
begin
|
|
$display ("Error! lpm_showahead must be ON or OFF.");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
i_overflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "OVERFLOW_CHECKING");
|
|
if (i_overflow_checking == "")
|
|
begin
|
|
if ((overflow_checking != "ON") && (overflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! OVERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
else
|
|
i_overflow_checking = overflow_checking;
|
|
end
|
|
else if ((i_overflow_checking != "ON") && (i_overflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! OVERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
i_underflow_checking = eva.GET_PARAMETER_VALUE(lpm_hint, "UNDERFLOW_CHECKING");
|
|
if(i_underflow_checking == "")
|
|
begin
|
|
if ((underflow_checking != "ON") && (underflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! UNDERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
else
|
|
i_underflow_checking = underflow_checking;
|
|
end
|
|
else if ((i_underflow_checking != "ON") && (i_underflow_checking != "OFF"))
|
|
begin
|
|
$display ("Error! UNDERFLOW_CHECKING must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
use_eab = eva.GET_PARAMETER_VALUE(lpm_hint, "USE_EAB");
|
|
if(use_eab == "")
|
|
use_eab = "ON";
|
|
else if ((use_eab != "ON") && (use_eab != "OFF"))
|
|
begin
|
|
$display ("Error! USE_EAB must equal to either 'ON' or 'OFF'");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
intended_device_family = eva.GET_PARAMETER_VALUE(lpm_hint, "INTENDED_DEVICE_FAMILY");
|
|
if (intended_device_family == "")
|
|
intended_device_family = "Stratix II";
|
|
else if (dev.IS_VALID_FAMILY(intended_device_family) == 0)
|
|
begin
|
|
$display ("Error! Unknown INTENDED_DEVICE_FAMILY=%s.", intended_device_family);
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$stop;
|
|
end
|
|
|
|
for (i = 0; i < (1 << lpm_widthu); i = i + 1)
|
|
mem_data[i] <= 0;
|
|
i_data_tmp <= 0;
|
|
i_rdptr <= 0;
|
|
i_wrptr <= 0;
|
|
i_wrptr_tmp <= 0;
|
|
i_wren_tmp <= 0;
|
|
i_wr_udwn <= 0;
|
|
i_rd_udwn <= 0;
|
|
|
|
i_rdusedw <= 0;
|
|
i_wrusedw <= 0;
|
|
i_q_tmp <= 0;
|
|
end
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
// Delays & DFF Pipes
|
|
lpm_fifo_dc_dffpipe DP_RDPTR_D (
|
|
.d (i_rdptr),
|
|
.clock (i_rdenclock),
|
|
.aclr (aclr),
|
|
.q (w_rdptrrg));
|
|
lpm_fifo_dc_dffpipe DP_WRPTR_D (
|
|
.d (i_wrptr),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.q (w_wrdelaycycle));
|
|
defparam
|
|
DP_RDPTR_D.lpm_delay = 0,
|
|
DP_RDPTR_D.lpm_width = lpm_widthu,
|
|
DP_WRPTR_D.lpm_delay = 1,
|
|
DP_WRPTR_D.lpm_width = lpm_widthu;
|
|
|
|
lpm_fifo_dc_dffpipe DP_WS_NBRP (
|
|
.d (w_rdptrrg),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.q (w_ws_nbrp));
|
|
lpm_fifo_dc_dffpipe DP_RS_NBWP (
|
|
.d (w_wrdelaycycle),
|
|
.clock (rdclk),
|
|
.aclr (aclr),
|
|
.q (w_rs_nbwp));
|
|
lpm_fifo_dc_dffpipe DP_WS_DBRP (
|
|
.d (w_ws_nbrp),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.q (w_ws_dbrp));
|
|
lpm_fifo_dc_dffpipe DP_RS_DBWP (
|
|
.d (w_rs_nbwp),
|
|
.clock (rdclk),
|
|
.aclr (aclr),
|
|
.q (w_rs_dbwp));
|
|
defparam
|
|
DP_WS_NBRP.lpm_delay = wrsync_delaypipe,
|
|
DP_WS_NBRP.lpm_width = lpm_widthu,
|
|
DP_RS_NBWP.lpm_delay = rdsync_delaypipe,
|
|
DP_RS_NBWP.lpm_width = lpm_widthu,
|
|
DP_WS_DBRP.lpm_delay = 1, // gray_delaypipe
|
|
DP_WS_DBRP.lpm_width = lpm_widthu,
|
|
DP_RS_DBWP.lpm_delay = 1, // gray_delaypipe
|
|
DP_RS_DBWP.lpm_width = lpm_widthu;
|
|
|
|
lpm_fifo_dc_dffpipe DP_WRUSEDW (
|
|
.d (i_wr_udwn),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.q (w_wrusedw));
|
|
lpm_fifo_dc_dffpipe DP_RDUSEDW (
|
|
.d (i_rd_udwn),
|
|
.clock (rdclk),
|
|
.aclr (aclr),
|
|
.q (w_rdusedw));
|
|
lpm_fifo_dc_dffpipe DP_WR_DBUW (
|
|
.d (i_wr_udwn),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.q (w_wr_dbuw));
|
|
lpm_fifo_dc_dffpipe DP_RD_DBUW (
|
|
.d (i_rd_udwn),
|
|
.clock (rdclk),
|
|
.aclr (aclr),
|
|
.q (w_rd_dbuw));
|
|
defparam
|
|
DP_WRUSEDW.lpm_delay = delay_wrusedw,
|
|
DP_WRUSEDW.lpm_width = lpm_widthu,
|
|
DP_RDUSEDW.lpm_delay = delay_rdusedw,
|
|
DP_RDUSEDW.lpm_width = lpm_widthu,
|
|
DP_WR_DBUW.lpm_delay = 1, // wrusedw_delaypipe
|
|
DP_WR_DBUW.lpm_width = lpm_widthu,
|
|
DP_RD_DBUW.lpm_delay = 1, // rdusedw_delaypipe
|
|
DP_RD_DBUW.lpm_width = lpm_widthu;
|
|
|
|
// Empty/Full
|
|
lpm_fifo_dc_fefifo WR_FE (
|
|
.usedw_in (w_wr_dbuw),
|
|
.wreq (wrreq),
|
|
.rreq (rdreq),
|
|
.clock (wrclk),
|
|
.aclr (aclr),
|
|
.empty (w_wrempty),
|
|
.full (w_wrfull));
|
|
lpm_fifo_dc_fefifo RD_FE (
|
|
.usedw_in (w_rd_dbuw),
|
|
.rreq (rdreq),
|
|
.wreq(wrreq),
|
|
.clock (rdclk),
|
|
.aclr (aclr),
|
|
.empty (w_rdempty),
|
|
.full (w_rdfull));
|
|
defparam
|
|
WR_FE.lpm_widthad = lpm_widthu,
|
|
WR_FE.lpm_numwords = lpm_numwords,
|
|
WR_FE.underflow_checking = underflow_checking,
|
|
WR_FE.overflow_checking = overflow_checking,
|
|
WR_FE.lpm_mode = "WRITE",
|
|
WR_FE.lpm_hint = lpm_hint,
|
|
RD_FE.lpm_widthad = lpm_widthu,
|
|
RD_FE.lpm_numwords = lpm_numwords,
|
|
RD_FE.underflow_checking = underflow_checking,
|
|
RD_FE.overflow_checking = overflow_checking,
|
|
RD_FE.lpm_mode = "READ",
|
|
RD_FE.lpm_hint = lpm_hint;
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(posedge aclr)
|
|
begin
|
|
i_rdptr <= 0;
|
|
i_wrptr <= 0;
|
|
if (!(dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) ||
|
|
(use_eab == "OFF"))
|
|
if (lpm_showahead == "ON")
|
|
i_q_tmp <= mem_data[0];
|
|
else
|
|
i_q_tmp <= 0;
|
|
end // @(posedge aclr)
|
|
|
|
// FIFOram
|
|
always @(posedge wrclk)
|
|
begin
|
|
if (aclr && (!(dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) ||
|
|
(use_eab == "OFF")))
|
|
begin
|
|
i_data_tmp <= 0;
|
|
i_wrptr_tmp <= 0;
|
|
i_wren_tmp <= 0;
|
|
end
|
|
else if (wrclk && ($time > 0))
|
|
begin
|
|
i_data_tmp <= data;
|
|
i_wrptr_tmp <= i_wrptr;
|
|
i_wren_tmp <= w_wren;
|
|
|
|
if (w_wren)
|
|
begin
|
|
if (~aclr && ((i_wrptr < (1<<lpm_widthu)-1) || (i_overflow_checking == "OFF")))
|
|
i_wrptr <= i_wrptr + 1;
|
|
else
|
|
i_wrptr <= 0;
|
|
|
|
if (use_eab == "OFF")
|
|
begin
|
|
mem_data[i_wrptr] <= data;
|
|
|
|
if (lpm_showahead == "ON")
|
|
i_showahead_flag1 <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
end // @(posedge wrclk)
|
|
|
|
always @(negedge wrclk)
|
|
begin
|
|
if ((~wrclk && (use_eab == "ON")) && ($time > 0))
|
|
begin
|
|
if (i_wren_tmp)
|
|
begin
|
|
mem_data[i_wrptr_tmp] <= i_data_tmp;
|
|
end
|
|
|
|
if (lpm_showahead == "ON")
|
|
i_showahead_flag1 <= 1'b1;
|
|
end
|
|
end // @(negedge wrclk)
|
|
|
|
always @(posedge rdclk)
|
|
begin
|
|
if (aclr && (!(dev.FEATURE_FAMILY_BASE_STRATIX(intended_device_family) ||
|
|
dev.FEATURE_FAMILY_BASE_CYCLONE(intended_device_family)) ||
|
|
(use_eab == "OFF")))
|
|
begin
|
|
if (lpm_showahead == "ON")
|
|
i_q_tmp <= mem_data[0];
|
|
else
|
|
i_q_tmp <= 0;
|
|
end
|
|
else if (rdclk && w_rden && ($time > 0))
|
|
begin
|
|
if (~aclr && ((i_rdptr < (1<<lpm_widthu)-1) || (i_underflow_checking == "OFF")))
|
|
i_rdptr <= i_rdptr + 1;
|
|
else
|
|
i_rdptr <= 0;
|
|
|
|
if (lpm_showahead == "ON")
|
|
i_showahead_flag1 <= 1'b1;
|
|
else
|
|
i_q_tmp <= mem_data[i_rdptr];
|
|
end
|
|
end // @(rdclk)
|
|
|
|
always @(posedge i_showahead_flag)
|
|
begin
|
|
i_q_tmp <= mem_data[i_rdptr];
|
|
i_showahead_flag1 <= 1'b0;
|
|
end // @(posedge i_showahead_flag)
|
|
|
|
always @(i_showahead_flag1)
|
|
begin
|
|
i_showahead_flag <= i_showahead_flag1;
|
|
end // @(i_showahead_flag1)
|
|
|
|
// Delays & DFF Pipes
|
|
always @(negedge rdclk)
|
|
begin
|
|
i_rdenclock <= 0;
|
|
end // @(negedge rdclk)
|
|
|
|
always @(posedge rdclk)
|
|
begin
|
|
if (w_rden)
|
|
i_rdenclock <= 1;
|
|
end // @(posedge rdclk)
|
|
|
|
always @(i_wrptr or w_ws_dbrp)
|
|
begin
|
|
i_wr_udwn <= i_wrptr - w_ws_dbrp;
|
|
end // @(i_wrptr or w_ws_dbrp)
|
|
|
|
always @(i_rdptr or w_rs_dbwp)
|
|
begin
|
|
i_rd_udwn <= w_rs_dbwp - i_rdptr;
|
|
end // @(i_rdptr or w_rs_dbwp)
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign w_rden = (i_underflow_checking == "OFF") ? rdreq : rdreq && !w_rdempty;
|
|
assign w_wren = (i_overflow_checking == "OFF") ? wrreq : wrreq && !w_wrfull;
|
|
assign q = i_q_tmp;
|
|
assign wrfull = w_wrfull;
|
|
assign rdfull = w_rdfull;
|
|
assign wrempty = w_wrempty;
|
|
assign rdempty = w_rdempty;
|
|
assign wrusedw = w_wrusedw;
|
|
assign rdusedw = w_rdusedw;
|
|
|
|
endmodule // lpm_fifo_dc_async
|
|
// END OF MODULE
|
|
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_fifo_dc
|
|
//
|
|
// Description :
|
|
//
|
|
// Limitation :
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_fifo_dc (data,
|
|
rdclock,
|
|
wrclock,
|
|
aclr,
|
|
rdreq,
|
|
wrreq,
|
|
rdfull,
|
|
wrfull,
|
|
rdempty,
|
|
wrempty,
|
|
rdusedw,
|
|
wrusedw,
|
|
q);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_widthu = 1;
|
|
parameter lpm_numwords = 2;
|
|
parameter lpm_showahead = "OFF";
|
|
parameter underflow_checking = "ON";
|
|
parameter overflow_checking = "ON";
|
|
parameter lpm_hint = "";
|
|
parameter lpm_type = "lpm_fifo_dc";
|
|
|
|
// LOCAL PARAMETER DECLARATION
|
|
parameter delay_rdusedw = 1;
|
|
parameter delay_wrusedw = 1;
|
|
parameter rdsync_delaypipe = 3;
|
|
parameter wrsync_delaypipe = 3;
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input rdclock;
|
|
input wrclock;
|
|
input aclr;
|
|
input rdreq;
|
|
input wrreq;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output rdfull;
|
|
output wrfull;
|
|
output rdempty;
|
|
output wrempty;
|
|
output [lpm_widthu-1:0] rdusedw;
|
|
output [lpm_widthu-1:0] wrusedw;
|
|
output [lpm_width-1:0] q;
|
|
|
|
// internal reg
|
|
wire w_rdfull_s;
|
|
wire w_wrfull_s;
|
|
wire w_rdempty_s;
|
|
wire w_wrempty_s;
|
|
wire w_rdfull_a;
|
|
wire w_wrfull_a;
|
|
wire w_rdempty_a;
|
|
wire w_wrempty_a;
|
|
wire [lpm_widthu-1:0] w_rdusedw_s;
|
|
wire [lpm_widthu-1:0] w_wrusedw_s;
|
|
wire [lpm_widthu-1:0] w_rdusedw_a;
|
|
wire [lpm_widthu-1:0] w_wrusedw_a;
|
|
wire [lpm_width-1:0] w_q_s;
|
|
wire [lpm_width-1:0] w_q_a;
|
|
wire i_aclr;
|
|
|
|
// INTERNAL TRI DECLARATION
|
|
tri0 aclr;
|
|
buf (i_aclr, aclr);
|
|
|
|
// COMPONENT INSTANTIATIONS
|
|
lpm_fifo_dc_async ASYNC (
|
|
.data (data),
|
|
.rdclk (rdclock),
|
|
.wrclk (wrclock),
|
|
.aclr (i_aclr),
|
|
.rdreq (rdreq),
|
|
.wrreq (wrreq),
|
|
.rdfull (w_rdfull_a),
|
|
.wrfull (w_wrfull_a),
|
|
.rdempty (w_rdempty_a),
|
|
.wrempty (w_wrempty_a),
|
|
.rdusedw (w_rdusedw_a),
|
|
.wrusedw (w_wrusedw_a),
|
|
.q (w_q_a) );
|
|
defparam
|
|
ASYNC.lpm_width = lpm_width,
|
|
ASYNC.lpm_widthu = lpm_widthu,
|
|
ASYNC.lpm_numwords = lpm_numwords,
|
|
ASYNC.delay_rdusedw = delay_rdusedw,
|
|
ASYNC.delay_wrusedw = delay_wrusedw,
|
|
ASYNC.rdsync_delaypipe = rdsync_delaypipe,
|
|
ASYNC.wrsync_delaypipe = wrsync_delaypipe,
|
|
ASYNC.lpm_showahead = lpm_showahead,
|
|
ASYNC.underflow_checking = underflow_checking,
|
|
ASYNC.overflow_checking = overflow_checking,
|
|
ASYNC.lpm_hint = lpm_hint;
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign rdfull = w_rdfull_a;
|
|
assign wrfull = w_wrfull_a;
|
|
assign rdempty = w_rdempty_a;
|
|
assign wrempty = w_wrempty_a;
|
|
assign rdusedw = w_rdusedw_a;
|
|
assign wrusedw = w_wrusedw_a;
|
|
assign q = w_q_a;
|
|
endmodule // lpm_fifo_dc
|
|
// END OF MODULE
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_inpad
|
|
//
|
|
// Description :
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_inpad (
|
|
pad,
|
|
result
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_inpad";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] pad;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(pad)
|
|
begin
|
|
result = pad;
|
|
end
|
|
|
|
endmodule // lpm_inpad
|
|
// END OF MODULE
|
|
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_outpad
|
|
//
|
|
// Description :
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_outpad (
|
|
data,
|
|
pad
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_outpad";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] pad;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] pad;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data)
|
|
begin
|
|
pad = data;
|
|
end
|
|
|
|
endmodule // lpm_outpad
|
|
// END OF MODULE
|
|
|
|
|
|
//START_MODULE_NAME------------------------------------------------------------
|
|
//
|
|
// Module Name : lpm_bipad
|
|
//
|
|
// Description :
|
|
//
|
|
// Limitation : n/a
|
|
//
|
|
// Results expected:
|
|
//
|
|
//END_MODULE_NAME--------------------------------------------------------------
|
|
|
|
// BEGINNING OF MODULE
|
|
`timescale 1 ps / 1 ps
|
|
|
|
// MODULE DECLARATION
|
|
module lpm_bipad (
|
|
data,
|
|
enable,
|
|
result,
|
|
pad
|
|
);
|
|
|
|
// GLOBAL PARAMETER DECLARATION
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_bipad";
|
|
parameter lpm_hint = "UNUSED";
|
|
|
|
// INPUT PORT DECLARATION
|
|
input [lpm_width-1:0] data;
|
|
input enable;
|
|
|
|
// OUTPUT PORT DECLARATION
|
|
output [lpm_width-1:0] result;
|
|
|
|
// INPUT/OUTPUT PORT DECLARATION
|
|
inout [lpm_width-1:0] pad;
|
|
|
|
// INTERNAL REGISTER/SIGNAL DECLARATION
|
|
reg [lpm_width-1:0] result;
|
|
|
|
// INITIAL CONSTRUCT BLOCK
|
|
initial
|
|
begin
|
|
if (lpm_width <= 0)
|
|
begin
|
|
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
|
|
$display("Time: %0t Instance: %m", $time);
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
// ALWAYS CONSTRUCT BLOCK
|
|
always @(data or pad or enable)
|
|
begin
|
|
if (enable == 1)
|
|
begin
|
|
result = {lpm_width{1'bz}};
|
|
end
|
|
else if (enable == 0)
|
|
begin
|
|
result = pad;
|
|
end
|
|
end
|
|
|
|
// CONTINOUS ASSIGNMENT
|
|
assign pad = (enable == 1) ? data : {lpm_width{1'bz}};
|
|
|
|
endmodule // lpm_bipad
|
|
// END OF MODULE
|