Quartus和Modelsim仿真ROM模塊


新建一個工程

選擇工程保存路徑,為工程取一個名字

Page 2 of 5 直接點擊next

 

 

Page 4 of 5 直接點擊next

 

下面為工程添加文件

 

需要注意模塊名和模塊所在文件的文件名要一致,下面的代碼保存在Wave.v這個文件中

module Wave(

    input i_clk,

    input i_rst_n,

    output reg[7:0] led

);

 

    parameter Delay500MS = 10;

 

    reg clk_led;

    reg[24:0] cnt;

 

    always@(posedge i_clk)

    if(!i_rst_n)begin

        cnt<=0;

        clk_led<=0;

    end

    else if(cnt==Delay500MS)begin

        cnt<=0;

        clk_led<=~clk_led;

    end

    else begin

        cnt<=cnt+1;

    end

 

    always@(posedge clk_led or negedge i_rst_n)

    if(!i_rst_n)begin

        led<=8'b1111_1110;

    end

    else begin

        led<={led[6:0],led[7]};

    end

 

endmodule

 

管腳設置

編譯

然后分配管腳

打開之后如下圖

在Location列中輸入各個引腳的位置即可。

如果上面一步打開的窗口是下面的樣子

也就是沒有All pins 子窗口,(看上面正常情況的截圖左下角豎着寫有這個窗口的名稱)。

解決辦法是在Pin Planner窗口中View>All Pins List

點擊后All pins子窗口出來了,但是還不是我們想要的,這個窗口中只有name列,沒有location這一列,解決辦法是在該子窗口的空白處右鍵選擇Customize Columms

點擊下面的箭頭添加所有列,然后再點擊ok

現在就有location這一列了。

 

管腳分配之后還需要編譯一次。編譯完成就可以下載了。

下載步驟如下圖:下面演示的是jtag模式

 

下面對上面這個工程做一個簡單的仿真。

工程中需要輸入的信號就是時鍾clk和復位信號rst_n,所以仿真之前我們需要輸入這兩個信號。

新建的波形文件是空白的,我們需要將相關信號添加進去,左鍵雙擊name下面的空白處然后按照下面的步驟添加信號

然后來設置clk信號,先選中這個信號,再點擊左側的overwrite clock圖標,出來的窗口中設置如下,ok

 

編輯好的波形如下圖

Ctrl+S保存,文件名為Wave.vwf

Assignments>Settings打開設置窗口,左側下方選擇Simulator Settings,設置紅框圈出來的部分,如果Simulation input里是空白,點擊右側的選擇按鈕選中剛才保存的波形文件

然后生成仿真網表

然后點擊上圖最下面的Start Simulation,仿真過程可能比較耗時,右下角會提示當前進度。完成后如下圖

如果led波形顯示的不是二進制可以雙擊最左邊的圖標打開屬性對話框,選擇二進制如上圖,或者信號上右鍵選擇最下面的Properites進入上面的對話框進行設置

 

下面在這個工程中添加一個ROM模塊,我們要實現的效果是讓FPGA輸出正弦波的采樣數據,首先需要通過C語言算出正弦波1個周期中128等分點的值,當然這個值也可以用Verilog通過CORDIC算法算出來。下面是用來算正弦值的代碼,代碼的思路很簡單,就是計算sin(x),x的變化范圍是0~2π,因為sin(x)是在-1~1之間變化,所以加1將波形移到X軸上面,此時delta (sin(x))的最大值是2,最小值是0,要將0~2映射到0~255就需要除以2再乘255。這個過程用代碼標示就是下面的樣子

#include<stdio.h>

#include<math.h>

#define pi 3.141592653

int main()

{

    float y;

    unsigned char i,dat;

    printf("這是正弦波采樣值,128點\n");

 

    for(i=0;i<128;i++)

    {

        y=(sin(2*pi*i/127)+1)/2;

        dat=y*255;

        if(i%8==0)printf("\n");

        if(dat<16)printf("0%x ",dat);

        else printf("%x ",dat);

    }

    printf("\n");

    while(1);

    return 0;

}

 

在VC6.0中運行后結果如下:

左上角的圖標上右擊>編輯>標記可以選中生成的數據,回車復制到粘貼板中了,數據如下

7f 85 8c 92 98 9e a4 aa

b0 b6 bc c1 c6 cb d0 d5

da de e2 e6 ea ed f0 f3

f5 f7 f9 fb fc fd fe fe

fe fe fe fd fc fa f8 f6

f4 f1 ee eb e8 e4 e0 dc

d7 d3 ce c9 c4 be b9 b3

ad a7 a1 9b 95 8f 88 82

7c 76 6f 69 63 5d 57 51

4b 45 40 3a 35 30 2b 27

22 1e 1a 16 13 10 0d 0a

08 06 04 02 01 00 00 00

00 00 01 02 03 05 07 09

0b 0e 11 14 18 1c 20 24

29 2e 33 38 3d 42 48 4e

54 5a 60 66 6c 72 79 7f

注意我們上面這些數字一共有128個,每個都是8bit的,數據的形式是十六進制

接着上面的quartus工程,新建一個ROM模塊,步驟如下:

首先建立一個用於初始化ROM的mif(memory initial file)

新建的mif文件為下面的樣子

可以看到這個文件中每個單元都是0,也就是默認的狀態,鼠標放在地址所在的列右鍵,彈出的選項中可以設置地址和內容的顯示形式,比如上圖中地址是十進制顯示的,內容是十六進制顯示的,這里內容的格式和我們之前准備的采樣數據的格式必須一致,我們這里都是十六進制。

復制上面的采樣數據,在地址0處粘貼,結果如下:

然后ctrl+s,我這里是在工程目錄下新建了一個src目錄保存源代碼相關文件,保存文件名為sin,默認格式是mif,結果如上圖紅框所示。

為了使這個數據在modelsim中也能使用,我們需要保存為hex格式(其實以后可以只保存為hex格式,而不必保存為mif格式),步驟是File>Save As,保存類型選擇hex即可

然后我們需要建立一個ROM模塊,步驟如下:

 

因為有128個數,所以ROM的深度為128,每個數的寬度為8bits

在page 5 of 7中點擊browse選擇剛才保存的sin.hex文件

然后page 6和pege7分別點擊next和finish,詢問是否加入工程,點擊yes

此時工程目錄結構如下

我們不妨打開sin.v這個文件看看quartus都寫了什么,代碼36~50行如下,定義了這個模塊的輸入輸出端口,我們看到模塊名為sin,有一個7bit的輸入address端口,有一個clock輸入端口,還有一個8bits的輸出端口q

再往下看,在79行開始有一點需要我們注意的

79和80行指定了這個ROM模塊初始化所需的兩個文件,一個是sin.rif,一個是sin.hex文件,我們剛才新建的hex文件確實就是保持在工程目錄的src目錄下,所以代碼中就是這個樣子,當我們之后需要將文件拿到modelsim中仿真的時候就需要目錄和代碼中的這種對應關系。

下面在Wave.v文件中對sin.v這個模塊實例化,完成之后的代碼如下


module Wave(

    input i_clk,

    input i_rst_n,

    output reg[7:0] led,

    output[7:0] q

);

 

parameter Delay500MS = 10;

 

    reg [6:0] addr;

    reg clk_led;

    reg[24:0] cnt;

 

    always@(posedge i_clk)

    if(!i_rst_n)begin

        cnt<=0;

        clk_led<=0;

    end

    else if(cnt==Delay500MS)begin

        cnt<=0;

        clk_led<=~clk_led;

    end

    else begin

        cnt<=cnt+1;

    end

 

    always@(posedge clk_led or negedge i_rst_n)

    if(!i_rst_n)begin

        led<=8'b1111_1110;

    end

    else begin

        led<={led[6:0],led[7]};

    end

 

    always@(posedge i_clk)

    if(!i_rst_n)begin

        addr<=0;

    end

    else begin

        addr<=addr+1;

    end

 

    sin U_ROM(

        addr,

        i_clk,

        q

    );

 

endmodule

 

保存代碼,然后編譯一下。此時就可以進行仿真了,但是為了看到ROM輸出的波形我們還需要做一點工作,雙擊Wave.vwf文件,此時Name這一列只有我們之前添加的i_clk,i_rst_n以及led這3個信號,我們還需要將新增加的信號addr和q添加進來。添加的辦法和之前介紹的一樣。

信號添加好之后需要執行Processing>Generate Functional Simulation Netlist,然后Processing>Start Simulation

結果如下,下面的圖中已經標注出了地址1~8對應的數值為紅色框框出來的部分,可以對照之前初始化所用的數據進行對比,如果之前的步驟沒有錯誤,這里應該是按之前初始化的順序輸出的。

至於時序為什么是這個樣子的,可以在工程目錄下找sin_waveforms.html這樣一個文件,該文件解釋了這個ROM的時序是如下圖所示的樣子。

仔細對照可以看到地址變化后,間隔一個時鍾輸出該地址對應的內容。

 

現在quartus中的工作就完成了,但這並不過癮,我們這里的ROM輸入的是正弦波的采樣值,那么我們希望輸出的波形當然是正弦波的樣子了,但上面的波形顯然不是。很遺憾quartus中無法以模擬量的形式顯示數據(可能也可以只是我沒找到設置方法,或者后續的版本可以,至少目前我用的版本中沒找到),但是Modelsim中可以以模式量的形式顯示數據。所以下面我們在modelsim中再完成一個簡單的仿真。

 

 

首先復制本文附件中的convert_hex2ver.dll文件到modelsim安裝目錄下,比如就可以放在modelsim_ae這個目錄中。然后在modelsim安裝目錄下找modelsim.ini文件,屬性中去掉只讀屬性,打開,搜索List of dynamically loaded objects for Verilog PLI applications,搜索結果應該是下面的樣子,在這一行后面添加一行Veriuser = xxx,xxx是剛才convert_hex2ver.dll文件的完整路徑

修改之后我的文件變成下面的樣子,需要注意這個路徑中不能包括空格,所以類似Program Files這樣的路徑是不可以的,如果路徑包含空格,在modelsim中仿真時會報錯,提示找不到convert_hex2ver.dll這個文件

然后保存,關閉。

 

打開modelsim,新建一個工程RomSim,添加一個RomSim.v文件,該文件中實例化一個sin.v模塊,並生成clk和addr信號。代碼如下:

`timescale 1ns/1ns

 

module RomSim;

 

reg [6:0] address;

reg clock;

wire [7:0] q;

 

sin U_ROM(

address,

clock,

q);

 

always #10 clock=~clock;

always #10 address=address+1;

 

initial begin

clock<=0;

address<=0;

end

 

endmodule

然后到quartus/eda/sim_lib/目錄下復制220model.v和altera_mf.v這兩個文件到剛才建立的modelsim工程目錄下粘貼,然后再到上一個quartus工程中復制sin.v和sin.hex文件到modelsim工程目錄下,此時需要注意,之前quartus工程中sin.v和sin.hex是放在src目錄下的,所以復制到modelsim工程下也要新建src目錄,然后將這兩個文件復制到src目錄中。然后在modelsim中添加剛才復制的這3個.v文件,此時modelsim的project窗口應該是下面的樣子

執行編譯。

Simulate>Start Simulate啟動仿真,在work庫下往下拉(會有很多文件)找到RomSim這個文件點擊ok

從object窗口中選擇ddress,clock,q信號添加到wave窗口,仿真時長設置為10us,點擊run圖標,結果是下面的樣子

設置q的格式為無符號類型

通過下面的步驟設置q以模擬量的形式顯示

其中Height是波形的高度,Max和Min分別對應ROM中的最大值和最小值

設置之后波形變成下面的樣子

終於大功告成!

保持上面的狀態不要動,在workspace窗口下面點擊左右箭頭,能看到一個Memories選項卡

點擊這個選項卡,可以看到有兩個實例,選中Range為[0:127]Depth為128width為8那一個實例,右鍵選擇View Content,出來一個memory窗口,這個窗口顯示了我們之前設計的ROM中的內容,但是數值是二進制的,我們需要切換為十六進制,在窗口區域內右鍵,選擇屬性

然后就變成了我們熟悉的十六進制形式

當然這里還可以選中一個數值並修改它。

 

---------------------------------------------Quartus 11.0中的仿真問題-------------------------------------------------------

 

Quartus 11.0已經不支持波形仿真功能,此時只能配合Modelsim進行仿真。在Quartus中啟動Modelsim仿真需要在Quartus中設置兩個地方。

1.Tools>options中設置Modelsim的安裝路徑,如下圖

2.設置仿真相關工具和文件,這里特別注意下拉框選擇的Tool name和上一步設置的EDA Tool要對應,Modelsim和Modelsim-Altera是不同的,都需要選擇電腦上實際安裝的版本,這個在Modelsim啟動畫面中一般會顯示,或者Modelsim的安裝文件名上會標注是否是Altera版本

其中設置仿真激勵文件的步驟是選中下圖的Compile test bench,點擊右邊的Test Beanch,打開的對話框中點擊new打開另一個對話框,這個對話框可以選擇文件。

做了上面的設置之后就可以在Quartus中通過下面的命令啟動仿真。

 

本文所用代碼和文件下載地址:http://download.csdn.net/detail/whereyougo/9359311


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM