马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
本文为明德扬原创及录用文章,转载请注明出处! 作者:轩工 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 [7:0] a; // 定义了 8 位的 wire 型数据 wireb; // 定义了 1 位的 wire 型数据 | reg [3:0]sum ; // 定义了一个 4 位的 reg 型数据 |
1.3.2 常量
类型 | 格式 | 说明 | parameter | parameter 数据名 = 表达式 | 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[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 : assigna = b + a; | 避免出现反馈电路:变为了不可知时序逻辑电路; |
1.5.2 always (过程块)
a、赋值
赋值方式 | 说明 | = ,阻塞赋值 | 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 块内,阻塞赋值:并行执行; |
b、if 语句
条目 | 说明 | 格式 1 | if( 条件 )begin 语句 1; 语句 2 ; end else begin 语句 1 ; 语句 2 ; end | 格式 2 | if( 条件 )begin 语句 1; 语句 2 ; end else if begin 语句 1 ; 语句 2 ; end else begin 语句 1 ; 语句 2 end | 特点 | 分支语句,各个分支条件不同;顺序执行判断; | 注意 | if-else 成对使用; |
c、case 语句
条目 | 说明 | 格式 | case( 表达式 ) 常量表达式 1:begin 语句; end 常量表达式 2:begin 语句; end 常量表达式 3:begin 语句; end default : 语句; endcase | 特点 | 分支语句,各个分支条件相同;并行执行判断; | 注意 | default 语句不可省略; |
d、代码 & 硬件
条目 | 说明 | 映射 | 赋值语句 -> 逻辑函数; // 加法器,减法器等; | 边沿型条件分支 -> D 触发器; | 条件分支 -> 多路选择器; | 示例 | |
1.5.3 模块例化
a、作用
系统设计时,建议遵循以下设计原则:
b、常见的典型错误如下所示:
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 结构
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 begin clk = 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 组合逻辑电路
条目 | 说明 | assign | assign add_cnt = flag==1; // 用于简单的组合逻辑电路; | always | always @(*)begin// 统一采用“ *” 为敏感列表; ( =,if,case )语句; // 只能使用“ =” 赋值 end |
1.7.2 时序逻辑电路
a、计数器模板 1
3 段式模板 | 模板 1 | 1 | 计数段 | 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 | 2 | 加1 条件 | assingadd_cnt = d==1; //d==1 :什么时候开始数脉冲 | 3 | 结束条件 | assing end_cnt = add_cnt&& cnt == X-1; // X: 数多少个脉冲 |
b、计数器模板 2
3 段式模板 | 模板 1 | 1 | 计数段 | 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 | 2 | 加1 条件 | assingadd_cnt = d==1; //d==1 :什么时候开始数脉冲 | 3 | 结束条件 | assing end_cnt = add_cnt&& cnt == X-1; // X: 数多少个脉冲 |
c、 4 段式状态机模板
段号 | 代码 | 1 | // 初始化,次态赋值给现态,明确当前状态; always @(posedge clk or negedge rst_n) begin if(!rst_n) state_c <= S00;// 初始状态 else state_c <= state_n; end | 2 | 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 | 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
a、框架
条目 | 内容 | 模块名 | `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 ) ); | 激励产生 | // 复位,时钟 ,等 | 显示输出结果 | $display // 类似 printf ; |
b、复位
复位 | initial begin rst_n = 1; #2; rst_n = 0; #(CYCLE*RST_TIME); rst_n = 1; end |
c、仿真时钟
仿真时钟 | initial begin clk = 0; forever #(CYCLE/2) clk=~clk; end |
d、激励信号
激励信号 | initial begin #1;// 方便观测 din1 = 0; // 赋初值 #(10*CYCLE); // 开始赋值 end |
以上就是本人总结的 Verilog 语法相关知识点,当然明德扬还有很多比较简便的模板给我们使用,感兴趣的朋友可以进入明德扬论坛进行更多 FPGA 或者语法相关讨论!
|