📄 220model.v
字号:
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).
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_type = "lpm_clshift";
parameter lpm_hint = "UNUSED";
// INPUT PORT DECLARATION
input [lpm_width-1:0] data;
input [lpm_widthdist-1:0] distance;
input direction;
// 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] result;
reg underflow;
reg overflow;
// LOCAL INTEGER DECLARATION
integer i;
// INTERNAL TRI DECLARATION
tri0 direction;
wire i_direction;
buf (i_direction, direction);
// 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;
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
$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)
begin
ONES[i] = 1'b1;
ZEROS[i] = 1'b0;
end
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] 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 add_sub;
tri0 aclr;
tri0 clock;
tri1 clken;
wire i_aclr;
wire i_clock;
wire i_clken;
wire i_add_sub;
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+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 =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -