马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
作者:轩工
本文为明德扬原创及录用文章,转载请注明出处!
1.1 概述 | | | 1>>面向设计的语句;//可综合。 2>>面向测试的语句; //testbench,不可综合。 | | 设计语句assign, always,模块例化,都对应实际电路,并行执行。 | | |
1.2 模块Module | | | | | | | wire,reg; 端口类型是wire时可以省略。 例:input a; //端口方向为输入,类型默认为wire; | |
1.3 数据类型1.3.1 wire/reg线网wire和reg都是线类型,工程上没区别;只是always/initial模块中输出定义需要为reg型; 注意:不要将reg类型与D触发器混淆,reg理解为因为代码所产生的。例如:
wire [7:0] a; //定义了8位的wire型数据 wireb; // 定义了1位的wire型数据 | reg [3:0]sum;//定义了一个4位的reg型数据 |
1.3.2 常量 | | | | | parameterMSB = 7;
//定义参数MSB为常量7;推荐大写; | | | 二进制:B或b; 十进制:D或d; 八进制:O或o;
十六进制:H或h; 8’b1010_1100 (‘b表示二进制)
下画线“_”,提高阅读性。 | | | | | | | | | | | |
1.4 运算符1.4.1 概述运算符 | | | +(加),-(减),*(乘),/(除),%(取模); | 每个运算符在电路中都是个模块,如加法器,减法器; !注意:除法,除2^n,是移位运算, 浮点运算就复杂了,因此浮点运算要专用除法器; | | >, <, >=, <=,==(相等), !=(不相等); | | &&(逻辑与). ||(逻辑或), !(逻辑非); 条件判断语句中,为避免歧义,逻辑运算符二边推荐为1bit; | | &(与),|(或), ~(非), ^(异或); ~^(同或); | | | | &,~&, |, ~|,^, ~^;//unary reduction; | | | | {} //{3{a[0]}}:代表3根同样的a[0]线,{a[0],a[0],a[0]} |
1.5 设计语句1.5.1 assign(连续赋值)实例 | | assigny = ~ b; assign out = a==1 && c==1; assign f = sel?a:b; | | | | |
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语句条目 | | | if(条件)begin 语句1; 语句2; end else begin 语句1; 语句2; end | | if(条件)begin 语句1; 语句2; end else if begin 语句1; 语句2; end else begin 语句1; 语句2 end | | | | |
case语句条目 | | | case(表达式) 常量表达式1:begin 语句; end 常量表达式2:begin 语句; end 常量表达式3:begin 语句; end default: 语句; endcase | | | | |
代码&硬件
1.5.3 模块例化作用系统设计时,建议遵循以下设计原则:
常见的典型错误如下所示:
1.5.4 全加器
描述方式描述方式 | | | | | AND u1(.a(a), .b(b), .o(and_out)); //推荐使用 |
1.6 测试语句1.6.1 结构
1.6.2 特殊符号 | | | 表示: 编译引导语,用于指导仿真编译器在编译时采取一些特殊处理; 编译引导语句一直保持有效,直到被取消或重写; | | `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; | |
| | `include “global.v” 包含另一个文件,完整拷贝过来; | | |
| | |
1.6.3 语句 | | | 块语句:只执行一次,always循环执行;不可综合; | | | //产生周期信号: intial begin clk = 0; forever #10 clk = ~clk; //时钟信号 end |
1.6.4 系统任务和函数条目 | | | | | | | 显示信号值变化:只执行一次,打印当前时刻; $display($time, “b% %b %b”, rst,clk,dout); | | 监视信号值变化:所有过程时刻; $monitor($time, “b% %b %b”, rst,clk,dout); | | | | |
1.7 代码模板1.7.1 组合逻辑电路 | | | assign add_cnt = flag==1; //用于简单的组合逻辑电路; | | always @(*)begin//统一采用“*”为敏感列表; (=,if,case)语句;//只能使用“=”赋值 end |
1.7.2 时序逻辑电路计数器模板13段式模板 | | | | always @( posedge cllk or negedge rst_n) begin if (!rst_n) cnt <= 0; //初值规定为0 else if (add_cnt)begin//【位置1】 if(end_cnt) cnt <= 0; else cnt <= cnt + 1; end end | | | assingadd_cnt = d==1; //d==1: 什么时候开始数脉冲 | | | assing end_cnt = add_cnt&& cnt == X-1; // X:数多少个脉冲 |
计数器模板23段式模板 | | | | always @( posedge cllk or negedge rst_n) begin if (!rst_n) cnt <= 0; //初值规定为0 else if (add_cnt) begin//【位置1】 if(end_cnt) cnt <= 0; else cnt <= cnt + 1; end else cnt <= 0; //不连续,需要清0时,使用模板2; end | | | assingadd_cnt = d==1; //d==1: 什么时候开始数脉冲 | | | assing end_cnt = add_cnt&& cnt == X-1; // X:数多少个脉冲 |
模板4段式状态机 | | | // 初始化,次态赋值给现态,明确当前状态; always @(posedge clk or negedge rst_n) begin if(!rst_n) state_c <= S00;//初始状态 else state_c <= state_n; end | | always @( * ) begin //组合逻辑,描述状态转换目标 case(state_c) S00: begin if(s00_s20_start) // 条件名 S00->S20 state_n = S20; else state_n = state_c; // 方便拷贝 end S20: begin if(s20_s21_start) state_n = S21; else state_n = state_c; end S21: begin if(s21_s00_start) state_n = S00; else state_n = state_c; end default: begin state_n = S00; end endcase end | | //具体的转换条件内容 assign s00_s20_start = state_c==S00&& (条件); assign s20_s21_start = state_c==S20&& (条件); assign s21_s20_start = state_c==S21&& (条件); | | 根据转态设计输出: 1个 always 设计1个输出信号; |
1.7.3 Testbench框架 | | | `timescale 1 ns/1 ns module testbench_name(); | | reg clk ; //时钟 reg rst_n; //复位 reg[3:0] din0 ; //uut的输入信号 ,定义为reg型,在initial中 reg din1 ; wire dout0;//uut的输出信号, 定义为wire型 wire[4:0] 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 ) ); | | | | |
复位复位 | 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 或者语法相关讨论!
|