📄 220model.v
字号:
integer i;
begin
tmp_buf = data;
overflow = 1'b0;
underflow = 1'b0;
if (dist < lpm_width)
begin
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;
for (i=lpm_width-1; i >= lpm_width-dist; i=i-1)
begin
if(data[i-1] != data[lpm_width-1])
overflow = 1'b1;
end
end
end
else
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 = data << lpm_width;
if (data != 0)
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] dist;
input direction;
reg [lpm_width-1:0] tmp_buf;
begin
tmp_buf = data;
if ((direction) && (dist > 0)) // shift right
tmp_buf = (data >> dist) | (data << (lpm_width - dist));
else if (dist > 0) // shift left
tmp_buf = (data << dist) | (data >> (lpm_width - dist));
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
$display("Error! LPM_SHIFTTYPE value must be \"LOGICAL\", \"ARITHMETIC\", or \"ROTATE\".");
if (lpm_width <= 0)
begin
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
$finish;
end
if (lpm_widthdist <= 0)
begin
$display("Value of lpm_widthdist parameter must be greater than 0(ERROR)");
$finish;
end
for (i=0; i < lpm_width; i=i+1)
ONES[i] = 1'b1;
end
// ALWAYS CONSTRUCT BLOCK
always @(data or i_direction or distance)
begin
if ((lpm_shifttype == "LOGICAL") || (lpm_shifttype == "UNUSED"))
{overflow, underflow, result} = LogicShift(data, distance, i_direction);
else if (lpm_shifttype == "ARITHMETIC")
{overflow, underflow, result} = ArithShift(data, distance, i_direction);
else if (lpm_shifttype == "ROTATE")
{overflow, underflow, result} = RotateShift(data, distance, i_direction);
end
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] tmp_result2 [lpm_pipeline:0];
reg [lpm_pipeline:0] tmp_cout2;
reg [lpm_pipeline:0] tmp_overflow2;
reg [lpm_width-1:0] tmp_result;
reg i_cin;
// LOCAL INTEGER DECLARATION
integer borrow;
integer i;
// INTERNAL TRI DECLARATION
tri1 add_sub;
tri0 aclr;
tri0 clock;
tri1 clken;
buf (i_aclr, aclr);
buf (i_clock, clock);
buf (i_clken, clken);
buf (i_add_sub, add_sub);
// 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");
$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\".");
$finish;
end
if ((lpm_representation != "SIGNED") &&
(lpm_representation != "UNSIGNED"))
begin
$display("Error! LPM_REPRESENTATION value must be \"SIGNED\" or \"UNSIGNED\".");
$finish;
end
if (lpm_pipeline < 0)
begin
$display("Error! LPM_PIPELINE must be greater than or equal to 0.\n");
$finish;
end
for (i = 0; i <= lpm_pipeline; i = i + 1)
begin
tmp_result2[i] = 'b0;
tmp_cout2[i] = 1'b0;
tmp_overflow2[i] = 1'b0;
end
end
// ALWAYS CONSTRUCT BLOCK
always @(cin or dataa or datab or i_add_sub or i_aclr)
begin
if (i_aclr)
for (i = 0; i <= lpm_pipeline; i = i + 1)
begin
tmp_result2[i] = 1'b0;
tmp_cout2[i] = 1'b0;
tmp_overflow2[i] = 1'b0;
end
else
begin
// 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_cout2[lpm_pipeline], tmp_result2[lpm_pipeline]} = dataa + datab + i_cin;
tmp_overflow2[lpm_pipeline] = tmp_cout2[lpm_pipeline];
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_overflow2[lpm_pipeline], tmp_result2[lpm_pipeline]} = dataa - datab - borrow;
tmp_cout2[lpm_pipeline] = (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_overflow2[lpm_pipeline] = ((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_overflow2[lpm_pipeline] = ((dataa[lpm_width-1] != datab[lpm_width-1]) &&
(dataa[lpm_width-1] != tmp_result[lpm_width-1])) ?
1 : 0;
end
tmp_result2[lpm_pipeline] = tmp_result;
end
end
end
always @(posedge i_clock)
begin
if ((!i_aclr) && (i_clken == 1))
for (i = 0; i < lpm_pipeline; i = i + 1)
begin
tmp_result2[i] <= tmp_result2[i+1];
tmp_cout2[i] <= tmp_cout2[i+1];
tmp_overflow2[i] <= tmp_overflow2[i+1];
end
end
// CONTINOUS ASSIGNMENT
assign result = tmp_result2[0];
assign cout = tmp_cout2[0];
assign overflow = tmp_overflow2[0];
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:0] tmp_alb2;
reg [lpm_pipeline:0] tmp_aeb2;
reg [lpm_pipeline:0] tmp_agb2;
reg [lpm_pipeline:0] tmp_aleb2;
reg [lpm_pipeline:0] tmp_aneb2;
reg [lpm_pipeline:0] tmp_ageb2;
// LOCAL INTEGER DECLARATION
integer i;
// INTERNAL TRI DECLARATION
tri0 aclr;
tri0 clock;
tri1 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\".");
$finish;
end
if (lpm_width <= 0)
begin
$display("Value of lpm_width parameter must be greater than 0(ERROR)");
$finish;
end
end
// ALWAYS CONSTRUCT BLOCK
// get the status of comparison
always @(dataa or datab or i_aclr)
begin
if (i_aclr) // reset all variables
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -