forked from github/verilator
47bce4157d
Added a new data-flow graph (DFG) based combinational logic optimizer. The capabilities of this covers a combination of V3Const and V3Gate, but is also more capable of transforming combinational logic into simplified forms and more. This entail adding a new internal representation, `DfgGraph`, and appropriate `astToDfg` and `dfgToAst` conversion functions. The graph represents some of the combinational equations (~continuous assignments) in a module, and for the duration of the DFG passes, it takes over the role of AstModule. A bulk of the Dfg vertices represent expressions. These vertex classes, and the corresponding conversions to/from AST are mostly auto-generated by astgen, together with a DfgVVisitor that can be used for dynamic dispatch based on vertex (operation) types. The resulting combinational logic graph (a `DfgGraph`) is then optimized in various ways. Currently we perform common sub-expression elimination, variable inlining, and some specific peephole optimizations, but there is scope for more optimizations in the future using the same representation. The optimizer is run directly before and after inlining. The pre inline pass can operate on smaller graphs and hence converges faster, but still has a chance of substantially reducing the size of the logic on some designs, making inlining both faster and less memory intensive. The post inline pass can then optimize across the inlined module boundaries. No optimization is performed across a module boundary. For debugging purposes, each peephole optimization can be disabled individually via the -fno-dfg-peepnole-<OPT> option, where <OPT> is one of the optimizations listed in V3DfgPeephole.h, for example -fno-dfg-peephole-remove-not-not. The peephole patterns currently implemented were mostly picked based on the design that inspired this work, and on that design the optimizations yields ~30% single threaded speedup, and ~50% speedup on 4 threads. As you can imagine not having to haul around redundant combinational networks in the rest of the compilation pipeline also helps with memory consumption, and up to 30% peak memory usage of Verilator was observed on the same design. Gains on other arbitrary designs are smaller (and can be improved by analyzing those designs). For example OpenTitan gains between 1-15% speedup depending on build type.
6784 lines
233 KiB
Systemverilog
6784 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 BLKANDNBLK
|
|
// verilator lint_off COMBDLY
|
|
// verilator lint_off INITIALDLY
|
|
// verilator lint_off MULTIDRIVEN
|
|
// verilator lint_off UNSIGNED
|
|
// verilator lint_off WIDTH
|
|
// verilator lint_off LATCH
|
|
|
|
// 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
|