⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 220model.v

📁 实现一个FIR滤波器
💻 V
📖 第 1 页 / 共 5 页
字号:
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 + -