关于赋值的一些说明
<=
与=
<=在不同的情况下可以表达不同的意思
在条件判断的时候即(a <= 5)中是小于等于的意思
在()之外的是非阻塞型赋值语句例如 a <= 5是赋值的含义
且表示为赋值的时候是非阻塞赋值语
即后面的相关语句同时执行,可以理解为并行执行。
=为阻塞赋值语句,是在这句之后所有语句执行之前执行的
也就是这句没有执行的话后面的语句就无法执行,这也是“阻塞”的意思。
可以理解为为顺序执行
举个例子初始值a=0,b=1,c=1
begin a=b;b=c;c=aend结果是a=1;b=1;c=a=1
(此时a=1已经有效了)
begin a<=b;b<=C;c<=a;end 结果是a=1;b=1;c=O
(a=1在当前begin-end内是无效的,整体执行完后,才有效)
组合逻辑用=,时序逻辑用<=
关于一些符号的含义
命名规则: reg[n-1:0] 存储器名[m-1:0]
说明: 这是m个n位的存储器 该存储器的地址范围是0- (m-1)
举例: reg[7:0] DiG[3:0];
说明: 这是16个8位存储器,该存储器地址范围是0-15
命名规则: n'hm n位十六进制值为m
说明: 这是 n位十六进制值为m的一个数据值,其中h可换位b标志二进制,换为o为八进制。
举例: 1’b1
说明: 这是1位二进制值为1的数
举例: 4’h12
说明: 这是4位十六进制值为12的数
初始化一些设定
-
在有输出端口的时候,为了能把一个输出信号赋给输出端口,必须要设定一个和输出端口名一样的reg寄存器,这样才能够将输出信号输出到端口
reg[1:0] Key_Value; output[1:0] Key_Value;
不然就会报错的:
Error (10137): Verilog HDL Procedural Assignment error at TimeSystem.v(121): object “Key_Value” on left-hand side of assignment must have a variable data type
(输入端口没有这个问题) -
可以将初始化的值直接写在寄存器后面
reg [12:0] CNT_R0 = 5;
分频
分为两种方式,一种是分屏数刚好为2的次方,还有一种不是2的次方
- 为2的次方
reg [5:0] Cnt_R0;
always @(posedge Clk) //64分频
begin
if(Cnt_R0 < 32)
begin
Clk_1M <= 0;
end
else
begin
Clk_1M <= 1;
end
Cnt_R0 <= Cnt_R0 + 1;
end
- 不是2的次方
reg [6:0] Cnt_R0;//128 = 31 + 97
always @(posedge Clk)
begin
if(Cnt_R0 < 31) //31分频
begin
Cnt_R0 = Cnt_R0 + 1;
Clk_1M = 0;
end
else
begin
Cnt_R0 = Cnt_R0 + 97;
Clk_1M = 1;
end
end
制作mif表
mif_Maker下载
下载完后
首先选择全局参数,根据需要设定宽度以及长度等,然后选定波形
最后点击另存为即可
然后添加到quartus中
如果是在别人已有的代码下更改一定要注意更改代码中
地址的宽度,不然可能你的波形明明点的是正弦波结果出来的是方波等…
always语句的使用
always语句其实就是一个敏感函数,只要其后的敏感型号量符合其特性,即可调用此函数
posedge
上升沿
negedge
下降沿
比如:
//Clk上升沿即可激活
lways @(posedge Clk) //分频创建Clk_Scan信号
begin
CNT_R0 <= CNT_R0 + 1'b1;
if(CNT_R0 < 4095)
begin
Clk_Scan <= 1;
end
else
begin
Clk_Scan <= 0;
end
end
并且还可以通过or来添加其可以激活的敏感信号量
always @(posedge Clk_Scan or negedge nRST)
begin
if(nRST == 0)
begin
Key_Flag_Clear <= 1'b0;
end
else
begin
if((Key_Flag == 1) && (Key_Flag_Clear == 0))
begin
SEG_M[0] <= SEG_M[0] +1'b1;
Key_Flag_Clear <= 1'b1;
end
else if(Key_Flag == 2'h0)
begin
Key_Flag_Clear <= 1'b0;
end
end
end
但是其敏感信号量不能超过三个!
否则会报错
always语句中,已经被赋值的寄存器是不能够在其他always语句中再次使用赋值语句的!
否则,会报错:
Error (10028): Can't resolve multiple constant drivers for net "K_freq[3]" at DDS.v(196)
不过可以使用其寄存器进行逻辑的判断等,也就是说不能写,只能读
只有再使用一个寄存器作为中间量来进行赋值。
当有两个及以上的敏感量的时候,一定要在程序后面处理当中用if以及else等去判断到底是哪个敏感量来了做什么事情,才是正确的做法,而不是想当然的直接将处理程序写在后面,不做处理
如果不做处理,其报错如下:
Error (12153): Can't elaborate top-level user hierarchy
错误程序如下
正确如下
注释和宏定义
- 注释:
Verilog有两种注释方式,一种以/*开始 */结束 ,还有一种就是双反斜杠// - 宏定义:
宏定义方式为
define on 1'b1
define OFF 1'b0
软核
QSYS集成开发工具创建使用的软核(CPU)
软核资源确定
首先要确定软核需要使用到哪些资源的外设,才方便从FPGA开发板上面给软核进行资源分配。
软核类型选择
点击Tools→Qsys,创建Qsys模块。
进入后,点击右方Library子框中的Embedded Processors项,然后点击此项目中的Nios II Processor创建软核处理器,然后会弹出窗口让我们选择软核的一些属性
首先要选择内核的类型,这里提供了三种类型,需要用户根据设计的需求和设计所用到的芯片资源来决定,这里选择Nios II/f。
系统ID选择
在Library子窗口中选择Peripherals -> Debug and Performance -> System ID Peripheral设定系统ID,点击后选择Finish结束选择
添加On-Chip ROM和RAM
点击Library子窗口中Memories and Memory Controllers -> On-Chip -> On-Chip Memory (RAM or ROM)
RAM:
ROM:
同时在创建完一个需要点击System Contents子窗口中的onchip_memory2_0选中刚才创建的rom or ram右键rename修改名字,方便后面的使用不至于混乱,如果设置的rom就修改为onchip_rom,如果设置的ram就修改为onchip_ram
添加定时器
在Library子窗口点击Peripherals -> Microcontroller Peripherals -> Interval Timer添加定时器模块,定时时间设置为1ms
自动生成中断号以及基地址
点击QSYS栏上方菜单栏System -> Assign Base Addresses自动生成基地址
点击System -> Assign Interrupt Numbers自动生成中断号
数据端口添加
按键数据端口:
根据设计方案,数据端口选择1个2bit输入数据口,点击Peripherals -> Microcontroller Peripherals -> PIO进行IO的选择
数码管数据端口选择:
根据分析数码管数据端口需要6个4bit的数据输出IO。
蜂鸣器数据端口选择:
根据分析需要1个1bit输出IO即可。
模块连接
将各个模块之间的线连接起来
确定复位源以及IO外部连接号
点击reset_n确定复位输入
将其中的Reset vectir memory 以及 Exception vector memory 确定为rom
在所有IO选择完毕后,选择IO中的external_connection确定其号,每个IO根据其名字更改即可
保存并编译
将其保存后,点击菜单栏Generate,编译软核CPU
FPGA设计部分
FPGA设计部分即为底层驱动部分,其中包含数码管驱动、蜂鸣器驱动以及按键的驱动,设计需要使用Verilog语言来完成这三个部分的程序编写。
5.2.1 创建工程
点击Home子窗口中的New Project Wizard创建工程
将其保存在工程文件夹中,并Next,添加设备
然后点击Finish的完成添加工程。
编写FPGA部分代码
点击File -> New
点击创建Verilog程序,编写数码管驱动、蜂鸣器驱动以及按键驱动程序。
然后分配引脚
完成后,点击Processing -> Start Compilation,编译。
编译通过后,点击Files ->Create Symbol Files for Current File生成原理图文件
连接软核CPU以及所生成的底层模块
新建一个原理图文件File -> New->Block Diagram/Schematic File
点击文件夹,添加刚才的软核cpu_info.qsys
在原理图中添加TimeSystem以及cpu_info两个模块,并相连,连接完成后进行编译。
完成后,连接开发板,将FPGA端程序烧录进去。