[转]Quartus和Modelsim仿真ROM模块

Posted tubujia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[转]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

以上是关于[转]Quartus和Modelsim仿真ROM模块的主要内容,如果未能解决你的问题,请参考以下文章

quartus ii 19.4和modelsim的仿真

Quartus系列:Quartus II 调用ModelSim仿真调试

如何在ModelSim中仿真Quartus的bdf文件和IP核

.do文件进行Quartus调用modelSIM仿真设定

quartus调用modelsim仿真每次都要重新打开modelsim吗?联合仿真每次都要关闭modelsim再重新打开吗?

quartus调用modelsim仿真每次都要重新打开modelsim吗?联合仿真每次都要关闭modelsim再重新打开吗?