1、Verilog命名规则
1.1、顶层文件
对象+功能+top
比如:video_oneline_top
1.2、逻辑控制文件
介于顶层和驱动层文件之间
对象+ctr
比如:ddr_ctr.v
1.3、驱动程序命名
对象+功能+dri
比如:lcd_dri.v、uart_rxd_dri.v
1.4、参数文件命名
对象+para
比如:lcd_para.v
1.5、模块接口命名:文件名+u
比如 :lcd_dir lcd_dir_u(........)
1.6、模块接口命名:特征名+文件名+u
比如 :mcb_read c3_mcb_read_u
1.7、程序注释说明:一般出现在新建工程文件内的顶部,或者由//、/* */、**等符号标示出来的地方。
//////////////////////////////////////////////////////////////////////////////////
// Company: milinker corperation
// Engineer:jinry tang
// WEB:www.milinker.com
// BBS:www.osrc.cn
// Create Date: 07:28:50 07/31/2015
// Design Name: FPGA STREAM
// Module Name: FPGA_USB
// Project Name: FPGA STREAM
// Target Devices: XC6SLX16-FTG256/XC6SLX25-FTG256 Mis603
// Tool versions: ISE14.7
// Description: CY7C68013A SLAVE FIFO comunication with fpga
// Revision: V1.0
// Additional Comments:
//1) _i input
//2) _o output
//3) _n activ low
//4) _dg debug signal
//5) _r delay or register
//6) _s state mechine
//////////////////////////////////////////////////////////////////////////////////
1.8、端口注释
input Video_vs_i,//输入场同步入
1.9、信号命名
命名总体规则:对象+功能(+极性)+特性
1.10、时钟信号
对象+功能+特性
比如:phy_txclk_i、sys_50mhz_i
1.11、复位信号
对象+功能+极性+特性
比如:phy_rst_n_i、sys_rst_n_i
1.12、延迟信号
对象+功能+特性 1+特征 2
比如:fram_sync_i_r0、fram_sync_i_r1
1.13、特定功能计数器
对象+cnt
比如:line_cnt、div_cnt0、div_cnt1
功能+cnt
比如:wr_cnt、rd_cnt
对象+功能+cnt
比如:fifo_wr_cnt、mcb_wr_cnt、mem_wr_cnt
对象+对象+cnt
比如:video_line_cnt、video_fram_cnt
1.14、一般计数器
cnt+序号
用于不容易混淆的计数
比如:cnt0、cnt1、cnt2
1.15、 时序同步信号
对象+功能+特性
比如:line_sync_i、fram_sysc_i
1.16、 使能信号
功能+en
比如:wr_en、rd_en
对象+功能+en
比如:fifo_wr_en、mcb_wr_en
2、Verilog基础语法
C 语言和 Verilog 的关键词和结构对比:
C 语言和 Verilog 运算符对比:
3.Verilog 关键字
3.1信号部分:
input 关键词,模块的输入信号,比如 input Clk,Clk 是外面关键输入的时钟信号;
output 关键词,模块的输出信号,属于wire型,比如 output[3:0]Led; 这个地方正好是一组输出信号。其中[3:0]表示 0~3 共 4 路信号。
inout 模块输入输出双向信号。这种类型属于wire型,我们的例子24LC02 中有使用。数总线的通信中,这种信号被广泛应用;
wire 关键词,线信号。例如:wire C1_Clk; 其中 C1_Clk 就是 wire 类型的信号;
线信号,三态类型,我们一般常用的线信号类型有 input,output,inout,wire;
reg 关键词,寄存器。和线信号不同,它可以在 always 中被赋值,经常用于时序逻辑中。比如 reg[3:0]Led;表示了一组寄存器。
3.2 结构部分
module()
…
endmodule
代表一个模块,我们的代码写在这个两个关键字中间。
3.2.1 always@()
always@()括号里面是敏感信号。1、这里的 always@(posedge Clk)敏感信号是 posedge Clk ,含义是在上升沿的时候有效,敏感信号还可以 negedge Clk 含义是下降沿的时候有效,这种形式一般时序逻辑都会用到。
2、还可以是*这个一符号,如果是一个*则表示一直是敏感的,一般用于组合逻辑。
3.2.2 assign
assign用来给 output,inout 以及 wire 这些类型进行连线。assign 相当于一条连线,将表达式右边的电路直接通过 wire(线)连接到左边,左边信号必须是 wire 型(output 和 inout 属于 wire 型)。当右边变化了左边立马变化,方便用来描述简单的组合逻辑。示例:
wire a, b, y;
assign y = a & b;
这些语句含义上都和高级语言一样:
if(...)begin
............
End
if(...)begin
............
end
else begin
............
End
if(...)begin
............
end
else if(...)begin
............
end
case(...)
............
endcase
begin
....
end 块作用域范围类似于C的大括号,用法举例:
always@(posdge clk) begin
.....
end
3.3 符号部分:(我们这里 FALSH 为 0,TRUE 为 1)
“;”分号用于每一句代码的结束,以表示结束,和 C 语言一样。
“:”冒号,用在数组,和条件运算符以及 case 语句结构中。case 结构会在后面讲解。
“<=”赋值符号,非阻塞赋值,在一个 always 模块中,所有语句一起更新。它也可以表示小于等于,具体是什么含义编译环境根据当前编程环境判断,如果“<=”是用在一个 if 判断里如:if(a <= 10);当然就表示小于等于了。
“=”阻塞赋值,或者给信号赋值,如果在 always 模块中,这条语句被立刻执行。阻塞赋值和非阻塞赋值将再后面详细举例说明。
“+,-,*,/,% ”是加、减、乘、除运算符号,这些使用和 C 语言基本是一样的,当你用到这些符号时,编译后会自动生成或者消耗 FPGA 原有的加法器或是乘法器等。其中符号/,%会消耗大量的逻辑,谨慎使用。
“<”小于,比如 A<B 含义就是 A 和 B 比较,如果 A 小于 B 就是 TURE,否则为 FALSE。
“<=”小于等于,比如 A<=B 含义就是 A 和 B 比较,如果 A 小于等于 B 就是 TURE,否则为 FALSE。
“>”大于,比如 A>B 含义就是 A 和 B 比较,如果 A 大于 B 就是 TURE,否则为 FALSE。
“>=”大于等于,比如 A>=B 含义就是 A 和 B 比较,如果大于等于 B 就是 TURE,否则为 FALSE。
“==”等于等于,比如 A==B 含义就是 A 和 B 比较,如果 A 等于 B 就是 TURE,否则为FALSE。
“!=”不等于,A!=B 含义是 A 和 B 比较,如果 A 不等于 B 就是 TURE,否则为 FALSE.
“>>”右移运算符,比如 A>>2 表示把 A 右移 2 位。
“<<”左移运算符,比如 A<<2 表示把 A 左移 2 位。
“~”按位取反运算符,比如 A=8’b1111_0000;则~A 的值为 8’b0000_1111;
“&”按位于与,比如 A=8’b1111_0000;B=8’b1010_1111;则 A&B 结果为 8’b1010_0000;
“^”异或运算符,比如 A=8’b1111_0000;B=8’b1010_1111;则 A^B 结果为 8’b0101_1111;
“&&”逻辑与,比如 A==1,B==2;则 A&&B 结果为 TRUE;如果 A==1,B==0,则 A&&B 结果为 FALSE,一般用于条件判断。
A = B ? C : D 是一个条件运算符,含义是如果 B 为 TRUE 则把 C 连线 A,否则把 D连线 A。B 通常是个条件判断,用小括弧括起:assign C1_Clk = (C1==25'd24999999) ? 1 : 0 ; C1_Clk,是一个 wire 类型的信号,当 C1==25'd24999999 时候,连线到 1,否则连线到 0.
“{}”在 Verilog 中表示拼接符,{a,b}这个的含义是将括号内的数按位并在一起,比如:{1001,1110}表示的是 10011110。拼接是 Verilog 相对于其他语言的一大优势,在以后的编程中请慢慢体会。
3.4 参数部分
parameter 定义一个符号 a 为常数(十进制 180 找个常量的定义等效方式):
parameter a = 180;//十进制,默认分配长度 32bit(编译器默认)
parameter a = 8’d180;//十进制
parameter a = 8’haa; //十六进制
parameter a = 8’b1010_1010; //二进制
预处理命令
//--------------------------------
`include file1.v
//--------------------------------
`define X = 1;
//--------------------------------
`deine Y;
`ifdef Y
Z=1;
`else
Z=0;
`endif
//--------------------------------
有的时候我们一些公共的宏参数,我们可以放在一个文件中,比如这个文件名字为xx.v 那么`include xx.v 就可以包含这个文件中定义的一些宏参数。我还是来详细说明下吧!
话说 Verilog 的`include 和 C 语言的 include 用法是一样一样的,要说区别可能就在于那个点吧。
include 一般就是包含一个文件,对于 Verilog 这个文件里的内容无非是一些参数定义,所以这里再提几个关键字:`ifdef、 `define、 `endif(他们都带个点,呵呵)。
他们联合起来使用,确实能让你的程序多样化,就拿 VGA 程序说事吧。
首先,你可以新建一个.v 文件(可以直接新建一个 TXT,让后将后缀换成.v)其实这个后缀没所谓,.v 也是可以的,我觉得,写成.v 更能体现出这个文件的意义。
假设有个 lcd_para.v 文件,内容如下:
// 640 * 480
`ifdef VGA_640_480_60FPS_25MHz
`define H_FRONT 11'd16
`define H_SYNC 11'd96
`define H_BACK 11'd48
`define H_DISP 11'd640
`define H_TOTAL 11'd800
`define V_FRONT 11'd10
`define V_SYNC 11'd2
`define V_BACK 11'd33
`define V_DISP 11'd480
`define V_TOTAL 11'd525
`endif
// 800 * 600
`ifdef VGA_800_600_72FPS_50MHz
`define H_FRONT 11'd56
`define H_SYNC 11'd120
`define H_BACK 11'd64
`define H_DISP 11'd800
`define H_TOTAL 11'd1040
`define V_FRONT 11'd37
`define V_SYNC 11'd6
`define V_BACK 11'd23
`define V_DISP 11'd600
`define V_TOTAL 11'd666
`endif
//---------------------------------
`define H_Start (`H_SYNC + `H_BACK)
`define H_END (`H_SYNC + `H_BACK + `H_DISP)
`define V_Start (`V_SYNC + `V_BACK)
`define V_END (`V_SYNC + `V_BACK + `V_DISP)
这 里 为 VGA 定 义 了 两 种 分 辨 率 , 通 过 `define VGA_800_600_60MHz 或`define VGA_640_480_60FPS_25MHz或`define VGA_800_600_72FPS_50MHz 来决定使用哪种分辨率。
比如,我的 xxx.v 文件想调用 lcd_para.h,那么 xxx.v 我可以写到:
<span style="color:#ff0000">`define VGA_800_600_60MHz //这句要放在"lcd_para.h"的上面,不然编译不通过
`include "lcd_para.h"
</span>
那么 xxx.v 文件中就可以用 lcd_para.v 中的参数了,且对应是 VGA_800_600_60MHz下的参数。
其次`include "lcd_para.v" 这个路径也有一点讲究,xxx.v 作为引用 lcd_para.v 的文件,它和 lcd_para.v 在同一文件夹下才能这么写,就是相对路径一说了。也就是以xxx.v 为当前路径去引索 lcd_para.v 文件的位子。所以如果他们不再一个文件夹那么请写出更详细(正确)的路径。顺便说一句,lcd_para.v 添不添加到工程是无所谓的,只要路径对了即可,当然我还是建议添加到工程,且和.v 文件放在同一文件夹下,以方便观察和管理。
4、Verilog 中数值表示的方式
如果我们要表示一个十进制是 180 的数值,在 Verilog 中的表示方法如下:
二进制:8’b1010_1010; //其中“_”是为了容易观察位数,可有可无。
十进制:8’d180;
16 进制:8’h AA;