Line 1... |
Line 1... |
|
//------------------------------------------------------------------------
|
|
// 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.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Imported to Opencores directory. Date Sept 10, 2001
|
|
// Split related modules into separate files, as the manual splits them.
|
|
// Added example instantiations to the beginning of each file.
|
|
//
|
|
/* EXAMPLE INSTANTIATIONS:
|
|
|
|
lpm_constant
|
|
#( 1, // lpm_width
|
|
0, // lpm_cvalue
|
|
"UNUSED" // lpm_strength, optional, {UNUSED, WEAK}
|
|
) lpm_constant_example (
|
|
.result (const_out[lpm_width-1:0])
|
|
);
|
|
|
|
lpm_inv
|
|
#( 1 // lpm_width
|
|
) lpm_inv_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.data (data_in[lpm_width-1:0])
|
|
);
|
|
|
|
// NOTE: Bits data[lpm_size-1:0] are ANDed together to make result[0]
|
|
lpm_and
|
|
#( 1, // lpm_width (output width)
|
|
1 // lpm_size (inputs to each gate)
|
|
) lpm_and_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.data (data_in[(lpm_size*lpm_width)-1:0])
|
|
);
|
|
|
|
// NOTE: Bits data[lpm_size-1:0] are ORed together to make result[0]
|
|
lpm_or
|
|
#( 1, // lpm_width (output width)
|
|
1 // lpm_size (inputs to each gate)
|
|
) lpm_or_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.data (data_in[(lpm_size*lpm_width)-1:0])
|
|
);
|
|
|
|
// NOTE: Bits data_[lpm_size-1:0] are XORed together to make result[0]
|
|
lpm_xor
|
|
#( 1, // lpm_width (output width)
|
|
1 // lpm_size (inputs to each gate)
|
|
) lpm_xor_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.data (data_in[(lpm_size*lpm_width)-1:0])
|
|
);
|
|
|
|
lpm_bustri
|
|
#( 1 // lpm_width
|
|
) lpm_bustri_example (
|
|
.tridata (data_tristate[lpm_width-1:0]),
|
|
.data (data_to_tristate[lpm_width-1:0]), // CHOICE
|
|
.enabledt (enable_data_to_tristate_bus_HIGH), // OPTIONAL
|
|
.result (data_from_tristate[lpm_width-1:0]), // CHOICE
|
|
.enabletr (enable_data_to_result_bus_HIGH), // OPTIONAL
|
|
);
|
|
|
|
// NOTE: Bits data[lpm_size-1:0] are SELECTED to make result[0]
|
|
lpm_mux
|
|
#( 1, // lpm_width (output width)
|
|
1, // lpm_size (inputs to each mux)
|
|
1, // lpm_widths (number of bits in output select bus)
|
|
0 // lpm_pipeline, optional, {0, 1}
|
|
) lpm_mux_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.data (data_in[(lpm_size*lpm_width)-1:0]),
|
|
.sel (data_sel[lpm_widths-1:0]),
|
|
.clock (clock_if_pipelined), // OPTIONAL
|
|
.clken (clock_enable_HIGH_if_pipelined), // OPTIONAL
|
|
.aclr (async_clear_if_pipelined) // OPTIONAL
|
|
);
|
|
|
|
lpm_decode
|
|
#( 1, // lpm_width (number of bits in input to be decoded)
|
|
1, // lpm_decodes (number of actual outputs decoded)
|
|
0 // lpm_pipeline, optional, {0, 1}
|
|
) lpm_decode_example (
|
|
.eq (decodes_out[lpm_decodes-1:0]),
|
|
.data (data_in[lpm_width:0]),
|
|
.enable (force_all_outputs_LOW_when_LOW), // OPTIONAL
|
|
.clock (clock_if_pipelined), // OPTIONAL
|
|
.clken (clock_enable_HIGH_if_pipelined), // OPTIONAL
|
|
.aclr (async_clear_if_pipelined) // OPTIONAL
|
|
);
|
|
|
|
lpm_clshift
|
|
#( 1, // lpm_width (width of input vector)
|
|
1, // lpm_widthdist (width of shift distance port)
|
|
"LOGICAL" // lpm_shifttype, optional, {LOGICAL, ROTATE, ARITHMETIC}
|
|
) lpm_clshift_example (
|
|
.result (data_out[lpm_width-1:0]),
|
|
.overflow (overflow_means_arith_bit_lost_or_result_became_0), // OPTIONAL
|
|
.underflow (underflow_means_result_became_0), // OPTIONAL
|
|
.data (data_in[lpm_width-1:0]),
|
|
.direction (low_means_towards_LSB), // OPTIONAL
|
|
.distance (shift_distance[lpm_widthdist-1:0])
|
|
);
|
|
*/
|
|
|
|
//------------------------------------------------------------------------
|
|
// LPM Synthesizable Models
|
|
//------------------------------------------------------------------------
|
|
// Version 1.5 (lpm 220) Date 12/17/99
|
|
//
|
|
// Modified LPM_ADD_SUB and LPM_MULT to accomodate LPM_WIDTH = 1.
|
|
// Default values for LPM_WIDTH* are changed back to 1.
|
|
// Added LPM_HINT to LPM_DIVIDE.
|
|
// Rewritten LPM_FIFO_DC to output correctly.
|
|
// Modified LPM_FIFO to output 0s before first read, output correct
|
|
// values after aclr and sclr, and output LPM_NUMWORDS mod
|
|
// exp(2, LPM_WIDTHU) when FIFO is full.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.4.1 (lpm 220) Date 10/29/99
|
|
//
|
|
// Default values for LPM_WIDTH* of LPM_ADD_SUB and LPM_MULT are changed
|
|
// from 1 to 2.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.4 (lpm 220) Date 10/18/99
|
|
//
|
|
// Default values for each optional inputs for ALL modules are added.
|
|
// Some LPM_PVALUE implementations were missing, and now implemented.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.3 (lpm 220) Date 06/23/99
|
|
//
|
|
// Corrected LPM_FIFO and LPM_FIFO_DC cout and empty/full flags.
|
|
// Implemented LPM_COUNTER cin/cout, and LPM_MODULUS is now working.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.2 (lpm 220) Date 06/16/99
|
|
//
|
|
// Added LPM_RAM_DP, LPM_RAM_DQ, LPM_IO, LPM_ROM, LPM_FIFO, LPM_FIFO_DC.
|
|
// Parameters and ports are added/discarded according to the spec.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.1 (lpm 220) Date 02/05/99
|
|
//
|
|
// Added LPM_DIVIDE module.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Version 1.0 Date 07/09/97
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Excluded Functions:
|
|
//
|
|
// LPM_FSM and LPM_TTABLE.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Assumptions:
|
|
//
|
|
// 1. LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, and LPM_NUMWORDS,
|
|
// LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE default value 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.
|
|
//
|
|
//------------------------------------------------------------------------
|
|
// Synthesis Issues:
|
|
//
|
|
// 1. LPM_COUNTER
|
|
//
|
|
// Currently synthesis tools do not allow mixing of level and edge
|
|
// sensetive signals. To overcome that problem the "data" signal is
|
|
// removed from the clock always block of lpm_counter, however the
|
|
// synthesis result is accurate. For correct simulation add the "data"
|
|
// pin to the sensetivity list as follows:
|
|
//
|
|
// always @(posedge clock or posedge aclr or posedge aset or
|
|
// posedge aload or data)
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_constant ( result );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_cvalue = 0;
|
|
parameter lpm_strength = "UNUSED";
|
|
parameter lpm_type = "lpm_constant";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
output [lpm_width-1:0] result;
|
|
|
|
assign result = lpm_cvalue;
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_constant") || (lpm_type !== "lpm_constant"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_constant
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_inv ( result, data );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_inv";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [lpm_width-1:0] data;
|
|
output [lpm_width-1:0] result;
|
|
|
|
reg [lpm_width-1:0] result;
|
|
|
|
always @(data)
|
|
begin
|
|
result = ~data;
|
|
end
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_inv") || (lpm_type !== "lpm_inv"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_inv
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_and ( result, data );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_and";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
output [lpm_width-1:0] result;
|
|
|
|
reg [lpm_width-1:0] result;
|
|
integer i, j, k;
|
|
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result[i] = data[i];
|
|
for (j=1; j<lpm_size; j=j+1)
|
|
begin
|
|
k = j * lpm_width + i;
|
|
result[i] = result[i] & data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_and") || (lpm_type !== "lpm_and"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_and
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_or ( result, data );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_or";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
output [lpm_width-1:0] result;
|
|
|
|
reg [lpm_width-1:0] result;
|
|
integer i, j, k;
|
|
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result[i] = data[i];
|
|
for (j=1; j<lpm_size; j=j+1)
|
|
begin
|
|
k = j * lpm_width + i;
|
|
result[i] = result[i] | data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_or") || (lpm_type !== "lpm_or"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_or
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_xor ( result, data );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_size = 1;
|
|
parameter lpm_type = "lpm_xor";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
output [lpm_width-1:0] result;
|
|
|
|
reg [lpm_width-1:0] result;
|
|
integer i, j, k;
|
|
|
|
always @(data)
|
|
begin
|
|
for (i=0; i<lpm_width; i=i+1)
|
|
begin
|
|
result[i] = data[i];
|
|
for (j=1; j<lpm_size; j=j+1)
|
|
begin
|
|
k = j * lpm_width + i;
|
|
result[i] = result[i] ^ data[k];
|
|
end
|
|
end
|
|
end
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_xor") || (lpm_type !== "lpm_xor"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_xor
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_bustri ( result, tridata, data, enabledt, enabletr );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_type = "lpm_bustri";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [lpm_width-1:0] data;
|
|
input enabledt;
|
|
input enabletr;
|
|
output [lpm_width-1:0] result;
|
|
inout [lpm_width-1:0] tridata;
|
|
|
|
reg [lpm_width-1:0] result;
|
|
reg [lpm_width-1:0] tmp_tridata;
|
|
|
|
tri0 enabledt;
|
|
tri0 enabletr;
|
|
buf (i_enabledt, enabledt);
|
|
buf (i_enabletr, enabletr);
|
|
|
|
always @(data or tridata or i_enabletr or i_enabledt)
|
|
begin
|
|
if (i_enabledt == 0 && i_enabletr == 1)
|
|
begin
|
|
result = tridata;
|
|
tmp_tridata = 'bz;
|
|
end
|
|
else if (i_enabledt == 1 && i_enabletr == 0)
|
|
begin
|
|
result = 'bz;
|
|
tmp_tridata = data;
|
|
end
|
|
else if (i_enabledt == 1 && i_enabletr == 1)
|
|
begin
|
|
result = data;
|
|
tmp_tridata = data;
|
|
end
|
|
else
|
|
begin
|
|
result = 'bz;
|
|
tmp_tridata = 'bz;
|
|
end
|
|
end
|
|
|
|
assign tridata = tmp_tridata;
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_bustri") || (lpm_type !== "lpm_bustri"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_bustri
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_mux ( result, clock, clken, data, aclr, sel );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_size = 1;
|
|
parameter lpm_widths = 1;
|
|
parameter lpm_pipeline = 0;
|
|
parameter lpm_type = "lpm_mux";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [(lpm_size * lpm_width)-1:0] data;
|
|
input aclr;
|
|
input clock;
|
|
input clken;
|
|
input [lpm_widths-1:0] sel;
|
|
output [lpm_width-1:0] result;
|
|
|
|
integer i, j, m, n;
|
|
reg [lpm_width-1:0] tmp_result;
|
|
reg [lpm_width-1:0] tmp_result2 [lpm_pipeline:0];
|
|
|
|
tri0 aclr;
|
|
tri0 clock;
|
|
tri1 clken;
|
|
|
|
buf (i_aclr, aclr);
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
|
|
always @(data or sel)
|
|
begin
|
|
tmp_result = 0;
|
|
for (m=0; m<lpm_width; m=m+1)
|
|
begin
|
|
n = sel * lpm_width + m;
|
|
tmp_result[m] = data[n];
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= lpm_pipeline; i = i + 1)
|
|
tmp_result2[i] = 'b0;
|
|
end
|
|
else if (i_clken == 1)
|
|
begin
|
|
tmp_result2[lpm_pipeline] = tmp_result;
|
|
for (j = 0; j < lpm_pipeline; j = j +1)
|
|
tmp_result2[j] = tmp_result2[j+1];
|
|
end
|
|
end
|
|
|
|
assign result = (lpm_pipeline > 0) ? tmp_result2[0] : tmp_result;
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_mux") || (lpm_type !== "lpm_mux"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_mux
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_decode ( eq, data, enable, clock, clken, aclr );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_decodes = 1 << lpm_width;
|
|
parameter lpm_pipeline = 0;
|
|
parameter lpm_type = "lpm_decode";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [lpm_width-1:0] data;
|
|
input enable;
|
|
input clock;
|
|
input clken;
|
|
input aclr;
|
|
output [lpm_decodes-1:0] eq;
|
|
|
|
reg [lpm_decodes-1:0] tmp_eq2 [lpm_pipeline:0];
|
|
reg [lpm_decodes-1:0] tmp_eq;
|
|
integer i, j;
|
|
|
|
tri0 clock;
|
|
tri1 clken;
|
|
tri0 aclr;
|
|
tri1 enable;
|
|
|
|
buf (i_clock, clock);
|
|
buf (i_clken, clken);
|
|
buf (i_aclr, aclr);
|
|
buf (i_enable, enable);
|
|
|
|
|
|
always @(data or i_enable)
|
|
begin
|
|
tmp_eq = 0;
|
|
if (i_enable)
|
|
begin
|
|
if ((data < lpm_decodes))
|
|
begin
|
|
tmp_eq[data] = 1'b1;
|
|
end
|
|
else
|
|
tmp_eq = 0;
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clock or posedge i_aclr)
|
|
begin
|
|
if (i_aclr)
|
|
begin
|
|
for (i = 0; i <= lpm_pipeline; i = i + 1)
|
|
tmp_eq2[i] = 'b0;
|
|
end
|
|
else if (clken == 1)
|
|
begin
|
|
tmp_eq2[lpm_pipeline] = tmp_eq;
|
|
for (j = 0; j < lpm_pipeline; j = j +1)
|
|
tmp_eq2[j] = tmp_eq2[j+1];
|
|
end
|
|
end
|
|
|
|
assign eq = (lpm_pipeline > 0) ? tmp_eq2[0] : tmp_eq;
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_decode") || (lpm_type !== "lpm_decode"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_decode
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
module lpm_clshift ( result, overflow, underflow, data, direction, distance );
|
|
|
|
// NOTE: Parameters must be declared in the same order as the Properties
|
|
// are specified in the Cell Specification document.
|
|
parameter lpm_width = 1;
|
|
parameter lpm_widthdist = 1;
|
|
parameter lpm_shifttype = "LOGICAL";
|
|
parameter lpm_type = "lpm_clshift";
|
|
parameter lpm_hint = "UNUSED";
|
|
parameter lpm_source_version = "lpm 220 version 1.6";
|
|
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] distance;
|
|
input direction;
|
|
output [lpm_width-1:0] result;
|
|
output overflow;
|
|
output underflow;
|
|
|
|
reg [lpm_width-1:0] ONES;
|
|
reg [lpm_width-1:0] result;
|
|
reg overflow, underflow;
|
|
integer i;
|
|
|
|
tri0 direction;
|
|
|
|
buf (i_direction, direction);
|
|
|
|
//---------------------------------------------------------------//
|
|
function [lpm_width+1:0] LogicShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] dist;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
reg overflow, underflow;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
if ((direction) && (dist > 0)) // shift right
|
|
begin
|
|
tmp_buf = data >> dist;
|
|
if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
|
|
underflow = 1'b1;
|
|
end
|
|
else if (dist > 0) // shift left
|
|
begin
|
|
tmp_buf = data << dist;
|
|
if ((data != 0) && ((dist >= lpm_width)
|
|
|| ((data >> (lpm_width-dist)) != 0)))
|
|
overflow = 1'b1;
|
|
end
|
|
LogicShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
|
|
end
|
|
endfunction
|
|
|
|
//---------------------------------------------------------------//
|
|
function [lpm_width+1:0] ArithShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] dist;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
reg overflow, underflow;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
|
|
if (direction && (dist > 0)) // shift right
|
|
begin
|
|
if (data[lpm_width-1] == 0) // positive number
|
|
begin
|
|
tmp_buf = data >> dist;
|
|
if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
|
|
underflow = 1'b1;
|
|
end
|
|
else // negative number
|
|
begin
|
|
tmp_buf = (data >> dist) | (ONES << (lpm_width - dist));
|
|
if ((data != ONES) && ((dist >= lpm_width-1) || (tmp_buf == ONES)))
|
|
underflow = 1'b1;
|
|
end
|
|
end
|
|
else if (dist > 0) // shift left
|
|
begin
|
|
tmp_buf = data << dist;
|
|
if (data[lpm_width-1] == 0) // positive number
|
|
begin
|
|
if ((data != 0) && ((dist >= lpm_width-1)
|
|
|| ((data >> (lpm_width-dist-1)) != 0)))
|
|
overflow = 1'b1;
|
|
end
|
|
else // negative number
|
|
begin
|
|
if ((data != ONES) && ((dist >= lpm_width)
|
|
|| (((data >> (lpm_width-dist-1))|(ONES << (dist+1))) != ONES)))
|
|
overflow = 1'b1;
|
|
end
|
|
end
|
|
ArithShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
|
|
end
|
|
endfunction
|
|
|
|
//---------------------------------------------------------------//
|
|
function [lpm_width-1:0] RotateShift;
|
|
input [lpm_width-1:0] data;
|
|
input [lpm_widthdist-1:0] dist;
|
|
input direction;
|
|
reg [lpm_width-1:0] tmp_buf;
|
|
|
|
begin
|
|
tmp_buf = data;
|
|
if ((direction) && (dist > 0)) // shift right
|
|
begin
|
|
tmp_buf = (data >> dist) | (data << (lpm_width - dist));
|
|
end
|
|
else if (dist > 0) // shift left
|
|
begin
|
|
tmp_buf = (data << dist) | (data >> (lpm_width - dist));
|
|
end
|
|
RotateShift = tmp_buf[lpm_width-1:0];
|
|
end
|
|
endfunction
|
|
//---------------------------------------------------------------//
|
|
|
|
initial
|
|
begin
|
|
for (i=0; i < lpm_width; i=i+1)
|
|
ONES[i] = 1'b1;
|
|
end
|
|
|
|
always @(data or i_direction or distance)
|
|
begin
|
|
// lpm_shifttype is optional and default to LOGICAL
|
|
if ((lpm_shifttype == "LOGICAL"))
|
|
begin
|
|
{overflow,underflow,result} = LogicShift(data,distance,i_direction);
|
|
end
|
|
else if (lpm_shifttype == "ARITHMETIC")
|
|
begin
|
|
{overflow,underflow,result} = ArithShift(data,distance,i_direction);
|
|
end
|
|
else if (lpm_shifttype == "ROTATE")
|
|
begin
|
|
result = RotateShift(data, distance, i_direction);
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
result = 'bx;
|
|
overflow = 1'b0;
|
|
underflow = 1'b0;
|
|
end
|
|
end
|
|
|
|
// Check for previous Parameter declaration order
|
|
initial if ((lpm_width === "lpm_clshift") || (lpm_type !== "lpm_clshift"))
|
|
begin
|
|
$display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
|
|
$finish;
|
|
end
|
|
endmodule // lpm_clshift
|
|
|
No newline at end of file
|
No newline at end of file
|