CH01 FPGA设计Verilog基础笔记(一)
CH01 FPGA设计Verilog基础笔记(一)
一、FPGA技术背景
大规模集成电路设计制造技术和数字信号处理技术,近三十年来,各自得到了迅速的发展。这两个表面上看来没有什么关系的技术领域实质上时紧密相关的。因为数字信号处理系统往往要进行一些复杂的数学运算和数据处理,并且又有实时响应的要求,它们通常是由高速专用逻辑系统或专用数字信号处理器所构成,电路是相当复杂的。因此只有在高速大规模集成电路设计制造技术进步的基础上,才有可能实现真正有意义的实时数字信号处理系统。对实时数字信号处理系统的要求不断提高,也推动了高速大规模集成电路设计制造技术的进步。
FPGA的学习需要一定的单片机和C语言基础。对于单片机来说,它的程序代码是一条指令一条指令的执行的。CPU先通过总线,读取第一条指令,然后解析这条指令,再然后执行这条指令。我们写的C代码总是一条一条地执行。如果我们同时要处理10个子程序,那么CPU必须一个个子程序来执行。如果有些实时性较高的,如矩阵键盘的扫描,VGA刷屏都需要中断来实现。如果刷屏时间过长,就会影响到按键的灵敏度。另外还有,单片机在用串口收发数据,同时我们的单片机要处理外部的IO信号,如果我们的IO信号非常快,并且有几百个信号可能在同一时间触发,很可能单片机就没法实现。
针对以上列出的两种情况,如果用FPGA就可以很方便地解决。由于FPGA的并行性,不管是扫描键盘,还是扫描VGA,都可以把它们当作独立的模块,时间上没有冲突,每个模块可以同时进行。
FPGA的并行性是它的优点,但是顺序性控制却是它的缺点。解决办法也有,例如状态机的设计和在FPGA中运行CPU。下面介绍两个概念,软核和硬核。
软核:软核就是用代码就可以实现的CPU核,这种核配置灵活,成本低。但是占用FPGA宝贵的资源。
硬核:硬核就是一块电路,做到FPGA内部,方便使用,性能更高。比如Xilinx的DDR内存控制器,就是一种硬核,其运行速度非常高,我们只需要做配置就可以使用。
二、Verilog基础语法
单片机的开发语言是C语言,FPGA的开发语言是Verilog,两种语言十分相似,对于熟悉C语言的工程师来说,FPGA的开发语言也方便学习。但是切记不可两者混淆。
- 关键字
module()
…
endmodule
//代表一个模块,代码写在两者之间
/***************************************************/
input 关键词,模块的输入信号。
output 关键词,模块的输出信号。
inout 关键词 模块输入输出双向信号
wire 关键词,寄存器
always@()括号里面是敏感信号。这里的always@(posedge Clk)敏感信号是posedge Clk含义是在上升沿的时候有效。还可以用*表示一个符号,如果是*,则表示一直敏感。
assign用来给output,inout以及wire这些类型进行连线。例如:
wire a, b, y;
assign y = a & b;
/****************************************************/
if…else类似于C语言,这不多做介绍
case…endcase作用域用于状态机的编写
begin…end作用域范围,类似于C的大括号{ }。
parameter定义参数的功能。如:parameter a =180;
include和define都是预处理命令,用于常量阈值的阐述,不过用的时候前面都加一个点,例如:`include `define
符号部分大体根C语言类似,主要说明以下两个符号:
“<=”非阻塞赋值,或者赋值符号,在一个always模块中,所有语句一起更新。当然它也可以表示小于等于。
“=”阻塞赋值,或者给信号赋值,如果在always模块中,这条语句被立刻执行。阻塞赋值和非阻塞赋值将在后面进行详细说明。
- 基数表示法
[size]`[signed] base value
size是指该常量用二进制表示的位数(位宽);signed是小写s或者大写S;base为o或O(表示八进制),b或B(表示二进制),d或D(表示十进制),h或H(表示十六进制)之一;value是基于base值的数字序列。例如:
5 `o37 5位八进制数
4 `D2 4位十进制数
4 `B1x_01 4位二进制数
- 阻塞赋值和非阻塞赋值
非阻塞赋值比较常见,如下:
reg A;
reg B;
always @(posedge clk)
begin
A<= 1`b1;
B<= 1`b1;
/****或者**
B<= 1`b1;
A<= 1`b1;
***********/
end
这段程序里,A和B是同时被赋值的,具体是说在时钟的上升沿来的时刻,A和B同时被置1.调换A和B的上下顺序,将得到相同的结果。
接着看另外一段程序:
reg A;
reg B;
always @(posedge clk)
begin
A<=1`b1;
end
always @(posedge clk)
A<=1`b1;
end
这段程序,与上一段程序也是完全等价的,A和B在同一时刻被赋值。两端程序的综合逻辑也是一样的,这就是非阻塞赋值的特点,体现了FPGA的并行性!
接下来看阻塞赋值,它少了一个非,表示会阻塞住,那么体会下这个阻塞:
always @(posedge clk)
begin
A = 1`b1;
B <= 1`b1;
end
这个程序是阻塞和非阻塞的混合使用,一般禁止这么写。程序流程:当时钟上升沿来临时,首先A会被置1,然后B寄存器再被置1.区别就是A和B不会被同时置1,A要比B提前零点几纳秒。这样就出现了先后顺序,但这个过程还是在一个时钟内完成的,只不过A要比B提前零点几纳秒。对于低速时钟来说,这影响不大,但随着时钟速度的提高,这样的语句就要小心了。
- Verilog HDL 代码规范
项目架构设计:
命名规则:
1、 顶层文件
对象+功能+top
比如:video_oneline_top
2、 逻辑控制文件
介于顶层和驱动层文件之间
对象+ctr
比如:ddr_ctr.v
3、 驱动程序命名
对象+功能+dri
比如:lcd_dri.v、uart_rxd_dri.v
4、 参数文件命名
对象+para
比如:lcd_para.v
5、 模块接口命名
文件名+u
比如:lcd_dir lcd_dir_u(……)
特征名+文件名+u
比如:mcb_read c3_mcb_rad_u
6、 程序注释
程序注释根C语言类似,用“//”
7、 信号命名
对象+功能(+极性)+特性
8、 时钟信号
对象+功能+特性
比如:phy_txclk_i、sys_50mhz_i
9、 复位信号
对象+功能+极性+特性
比如:phy_rst_n_i、 sys_rest_n_i
10、 延迟信号
对象+功能+特性1+特征2
比如:fram_sync_i_r0、 fram_sync_r_r1
11、 特定功能计数器
对象+cnt
比如:line_cnt、 div_cnt0、 div_cnt1
功能+cnt
比如:wr_cnt、 rd_rnt
对象+功能+cnt
比如:fifo_wr_cnt、mcb_wr_cnt
对象+对象+cnt
比如:video_line_cnt
12、 一般计数器
cnt+序号
用于不容易混淆的计数器
比如:cnt0、cnt1
13、 时序同步信号
对象+功能+特性
比如:line_sync_i、fram_sync_i
14、 使能信号
功能+en
比如:wr_en、rd_en
对象+功能+en
比如:fifo_wr_en、mcb_wr_en