【原创】你必须要掌握的 Verilog语法知识点 | Verilog语法笔记私人总结版
作者:轩工本文为明德扬原创及录用文章,转载请注明出处!
1.1 概述
条目说明
分类1>>面向设计的语句;//可综合。2>>面向测试的语句; //testbench,不可综合。
特点设计语句assign, always,模块例化,都对应实际电路,并行执行。
构造
1.2 模块Module
条目说明
模块名(端口列表)整个电路的外特性,抽象为黑盒子;
端口方向input,output;inout;
端口类型wire,reg;端口类型是wire时可以省略。例:input a; //端口方向为输入,类型默认为wire;
1.3 数据类型1.3.1 wire/reg线网wire和reg都是线类型,工程上没区别;只是always/initial模块中输出定义需要为reg型;注意:不要将reg类型与D触发器混淆,reg理解为因为代码所产生的。例如:
wire a;//定义了8位的wire型数据wireb; // 定义了1位的wire型数据
reg sum;//定义了一个4位的reg型数据
1.3.2 常量
类型格式说明
parameterparameter数据名= 表达式parameterMSB = 7;
//定义参数MSB为常量7;推荐大写;
常量<位宽><进制><数字>二进制:B或b;十进制:D或d;八进制:O或o;
十六进制:H或h;8’b1010_1100 (‘b表示二进制)
下画线“_”,提高阅读性。
<数字>默认十进制;
4值逻辑0:Logic Low低电平;
1:Logic High高电平;
x:Unknow;不确定;
z:High Impedance;高阻态; //三态门
1.4 运算符1.4.1 概述
运算符说明
算术运算符+(加),-(减),*(乘),/(除),%(取模);
每个运算符在电路中都是个模块,如加法器,减法器;!注意:除法,除2^n,是移位运算,浮点运算就复杂了,因此浮点运算要专用除法器;
关系运算符>, <, >=, <=,==(相等), !=(不相等);
逻辑运算符&&(逻辑与). ||(逻辑或), !(逻辑非);条件判断语句中,为避免歧义,逻辑运算符二边推荐为1bit;
位运算符&(与),|(或), ~(非), ^(异或); ~^(同或);
移位运算符<<(左移),>>(右移);
归约操作&,~&, |, ~|,^, ~^;//unary reduction;
条件运算符?:
拼接运算符{}//{3{a}}:代表3根同样的a线,{a,a,a}
1.5 设计语句1.5.1 assign(连续赋值)
实例说明
assigny = ~ b;assign out = a==1 && c==1;assign f = sel?a:b;>>实现可以用布尔函数描述的组合逻辑电路;
>>“=”后面可以是任何布尔函数;>>并行执行;
典型错误1:assigna = b + a;避免出现反馈电路:变为了不可知时序逻辑电路;
1.5.2 always(过程块)赋值
赋值方式说明
=,阻塞赋值always @(a or b or C or …)begin语句块(=, if语句, case语句)end
实现:组合逻辑电路;(注意!禁止用于时序逻辑电路)always块内,阻塞赋值:是顺序执行(类似C);
敏感表:@(*) //“*”自动添加相关输入信号;
避免出现Latch(锁存器)分支语句(if语句,case语句)条件不满时,会在电路中自动生成锁存器来保存不满足条件的值,因此要补全if-else,和case的defalut语句;
<=,非阻塞赋值always @(posedge clk or negedge rst_n)begin语句块(<=, if语句, case语句)end
实现:时序逻辑电路;(注意!禁止用于组合逻辑电路)always块内,阻塞赋值:并行执行;
if语句
条目说明
格式1if(条件)begin 语句1; 语句2;endelse begin 语句1; 语句2;end
格式2if(条件)begin 语句1; 语句2;endelse if begin 语句1; 语句2;endelse begin 语句1; 语句2end
特点分支语句,各个分支条件不同;顺序执行判断;
注意if-else成对使用;
case语句
条目说明
格式case(表达式)常量表达式1:begin语句; end常量表达式2:begin语句; end常量表达式3:begin语句; end default:语句;endcase
特点分支语句,各个分支条件相同;并行执行判断;
注意default语句不可省略;
代码&硬件
条目说明
映射赋值语句 ->逻辑函数; //加法器,减法器等;
边沿型条件分支 -> D触发器;
条件分支 ->多路选择器;
示例
1.5.3 模块例化作用系统设计时,建议遵循以下设计原则:
常见的典型错误如下所示:
1.5.4 全加器
全加器顶层:w1,w2,w3:模块之间连线;
半加强:2种描述方法,如下:
描述方式
描述方式说明
位置关联AND u1(a, b, and_out);
名字关联AND u1(.a(a), .b(b), .o(and_out)); //推荐使用
1.6 测试语句1.6.1 结构
Testbench
1.6.2 特殊符号
语句说明
`<标识符>表示:编译引导语,用于指导仿真编译器在编译时采取一些特殊处理;编译引导语句一直保持有效,直到被取消或重写;
`timescale`timescale <时间单位>/<时间精度>例1:`timescale 1ns/1ns//时间单位1ns;时间精度1ns;#2 //延时2 ×1=2ns;#2.1//延时2.1 × 1 = 2.1ns,精确到1ns,为2ns;例2:`timescale 1ns/100ps//时间单位1ns;时间精度100ps;#2 //延时2 ×1= 2ns;#2.1//延时2.1 × 1 = 2.1ns,精确到100s,为2.1ns;
`define
`include`include “global.v”包含另一个文件,完整拷贝过来;
`restall把所有设置的编译引导恢复到缺省状态;
#<num>;#10; //延迟10个时间单位
1.6.3 语句
语句说明
initial块语句:只执行一次,always循环执行;不可综合;
作用:产生激励信号;检查输出波形;赋初值;
forever//产生周期信号:intial beginclk = 0;forever #10 clk = ~clk;//时钟信号end
1.6.4 系统任务和函数
条目说明
$<标识符>表示Verilg的系统任务和函数
$time当前的仿真时间
$display显示信号值变化:只执行一次,打印当前时刻;$display($time, “b% %b %b”, rst,clk,dout);
$monitor监视信号值变化:所有过程时刻;$monitor($time, “b% %b %b”, rst,clk,dout);
$stop暂停仿真
$finish结束仿真,释放电脑资源;
1.7 代码模板1.7.1 组合逻辑电路
条目说明
assignassign add_cnt = flag==1; //用于简单的组合逻辑电路;
alwaysalways@(*)begin//统一采用“*”为敏感列表;(=,if,case)语句;//只能使用“=”赋值end
1.7.2 时序逻辑电路计数器模板1
3段式模板模板1
1计数段always @( posedge cllk or negedge rst_n) beginif (!rst_n) cnt <= 0; //初值规定为0else if (add_cnt)begin//【位置1】if(end_cnt) cnt <= 0;else cnt <= cnt + 1; endend
2加1条件assingadd_cnt = d==1; //d==1: 什么时候开始数脉冲
3结束条件assing end_cnt = add_cnt&& cnt == X-1; // X:数多少个脉冲
计数器模板2
3段式模板模板1
1计数段always @( posedge cllk or negedge rst_n) beginif (!rst_n) cnt <= 0; //初值规定为0else if (add_cnt)begin//【位置1】if(end_cnt) cnt <= 0;else cnt <= cnt + 1; endelse cnt <= 0; //不连续,需要清0时,使用模板2;end
2加1条件assingadd_cnt = d==1; //d==1: 什么时候开始数脉冲
3结束条件assing end_cnt = add_cnt&& cnt == X-1; // X:数多少个脉冲
模板4段式状态机
段号代码
1// 初始化,次态赋值给现态,明确当前状态;always @(posedge clk or negedge rst_n) begin if(!rst_n) state_c <= S00;//初始状态 else state_c <= state_n;end
2always @( * ) begin//组合逻辑,描述状态转换目标 case(state_c)S00: begin if(s00_s20_start)// 条件名 S00->S20 state_n = S20; else state_n = state_c; // 方便拷贝 endS20: begin if(s20_s21_start) state_n = S21; else state_n = state_c; endS21: begin if(s21_s00_start) state_n = S00; else state_n = state_c; enddefault: begin state_n = S00; end endcaseend
3//具体的转换条件内容assign s00_s20_start = state_c==S00&& (条件);assign s20_s21_start = state_c==S20&& (条件);assign s21_s20_start = state_c==S21&& (条件);
4根据转态设计输出:1个 always 设计1个输出信号;
1.7.3 Testbench框架
条目内容
模块名`timescale 1 ns/1 nsmodule testbench_name();
信号定义reg clk;//时钟reg rst_n;//复位regdin0; //uut的输入信号 ,定义为reg型,在initial中reg din1;wire dout0;//uut的输出信号, 定义为wire型wire dout1;parameter CYCLE = 20; //参数定义,方便修改;parameter RST_TIME = 3 ;
待测模块例化module_name uut( //统一采用名字关联 .clk (clk ), .rst_n (rst_n ), .din0 (din0 ), .din1 (din1 ), .dout0 (dout0 ), .dout1 (dout1 ));
激励产生//复位,时钟 ,等
显示输出结果$display //类似printf;
复位
复位
initial begin rst_n = 1; #2; rst_n = 0; #(CYCLE*RST_TIME); rst_n = 1; end
仿真时钟
仿真时钟
initial begin clk = 0; forever #(CYCLE/2) clk=~clk; end
激励信号
激励信号
initial begin #1;//方便观测 din1 = 0; //赋初值 #(10*CYCLE);//开始赋值 end
以上就是本人总结的Verilog语法相关知识点,当然明德扬还有很多比较简便的模板给我们使用,感兴趣的朋友可以进入明德扬论坛(http://www.fpgabbs.cn/)进行更多FPGA 或者语法相关讨论!
对学习有帮助 非常不错,谢谢
页:
[1]