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 [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 结构

 

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 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 语法相关知识点,转自明德扬论坛

 

posted @ 2020-08-21 23:20  小样儿老师  阅读(1569)  评论(0编辑  收藏  举报