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

📄 220model.v

📁 FIFO(先进先出队列)通常用于数据的缓存和用于容纳异步信号的频率或相位的差异。本FIFO的实现是利用 双口RAM 和读写地址产生模块来实现的.FIFO的接口信号包括异步的写时钟(wr_clk)和读
💻 V
📖 第 1 页 / 共 5 页
字号:
        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 + -