1.1 常量表示
默认十进制;负数需要用补码且多一个符号位;
基数表示法:8’b001 如果数字位宽多则自动截断或补足
‘haa 不加位宽的话就自动得到位宽
实数可以用十进制也可以用科学计数法 13_2.18e2 表示 13218
1.2 变量
Wire和reg;
凡是在 always 或 initial 语句中被赋值的变量(赋值号左边的变量),不论表达的是组合逻辑还是时序逻辑, 都一定是 reg 型变量;
凡是在 assign 语句中被赋值的变量,一定是 wire 型变量。
1.3 参数
通常出现在 module 内部,常被用于定义状态机的状态、数据位宽和 计数器计数个数大小等,例如:
parameter IDLE = 3'b001;
parameter CNT_1S_WIDTH = 4'd15
可以在调用时配置:
counter
#(
.CNT_MAX (25'd24 ) //实例化时参数可修改
)
counter_inst
(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.led_out (led_out ) //output led_out
);
1.4 赋值语句
“<=”(非阻塞赋值)和“=”(阻塞赋值);阻塞赋值跟C语言一样,非阻塞赋值是几条语句同时执行等式右边再赋值到左边来。
1.5 运算符
关系运算符跟C语言类似,除法是小数,求幂是**
约归运算符:&4’b1111 = 1&1&1&1 = 1’b1 ,“~&”、“^”、“~^”、“|”、“~|”同理。
逻辑运算符输出只有一个位
移位运算跟C语言一样:4'b1000 >> 3 后的结果为 4'b0001,4'b1000 >> 4 的结果为 4'b0000
条件运算符(三目运算符)
a > b ? a : c > d ? c : d
//等价于
a > b ? a : (c > d ? c : d)
相比于if-else能在assign中使用
1.6 优先级
归约运算符 > 算数运算符 > 移位运算符 > 关系运算符 > “= =” 和“!=”> 按位运算符 > “&&”和“||”> 条件运算符
总的来说是一元运算符 > 二元运算符 > 三元运算符
1.7 位拼接
位拼接运算符由一对花括号加逗号组成“{ , }”,拼接的不同数据之间用“,”隔开。位拼接运算符的作用主要有两种,一种是将位宽较短的数据拼接成一个位宽长的数据;另一种是可以通过位拼接实现移位的效果。
{n*{}} 复制拼接
1.8 分支与选择
If-else:跟C语言一样,把花括号换成begin end
always 块中表达组合逻辑时如果没有else,会产生latch,浪费资源,时序逻辑没事
Case需要default,还需要endcase(条件完整时不需要),不需要break;case 分支语句有“case”、 “casez”、“casex”三种形式
1.9 Inout双向接口
例如 IIC 和 SDRAM 的数据线都是双向端口。示例如下:
1 module test
2 (
4 input wire sel , /*输入输出控制信号,sel 为 1 时双向数据总线
5 向外输出数据,sel 为 0 时双向数据总线为高阻态可以向内输入数据*/
7 input wire data_out , /*由内部模块传来要发送给双向数据总线
8 向外输出的数据*/
9 inout wire data_bus , //双向数据总线
10 output wire data_in /*接收双向数据总线从外部输入的数据后
11 输出到其他内部模块*/
13 );
15 //data_in:接收双向数据总线从外部输入的数据
16 assign data_in = data_bus;
17
18 /*data_bus:sel 为 1 时双向数据总线向外输出数据
19 sel 为 0 时双向数据总线为高阻态可以向内输入数据*/
20 assign data_bus = (sel == 1'b1) ? data_out : 1'bz;
21
22 endmodule
1.10 系统函数和系统任务
大多数都是只能在 Testbench 仿真中用于验证。
`timescale 1ns/1ns //时间尺度预编译指令 时间单位/时间精度
仿真中使用“#数字”表示延时相应时间单位的时间,模块中也可以写上,综合时不会执行,但能在仿真时模拟组合逻辑的耗时。
1.11 仿真函数:
$display //打印信息,自动换行 $display("%b+%b=%d",a, b, c);
$strobe //打印信息,自动换行,最后执行 $strobe("%b+%b=%d",a,b,c);
$write //打印信息 $write("%b+%b=%d\n",a, b, c);
$monitor //持续监测变量 写一句就可以一直执行 initial $monitor("%b+%b=%d", a, b, c);
$stop //暂停仿真
$finish //结束仿真
$random //随机函数 返回整数 always #10 a = $random;
$time //时间函数 返回当前仿真用时 initial $monitor("a=%d @time %d",a,$time);
$readmemb //读文件函数
$readmemb("<数据文件名>",<存贮器名>);
$readmemh("<数据文件名>",<存贮器名>);
1 `timescale 1ns/1ns
2 module tb_test ();
3
4 integer i;
5
6 reg [7:0] a [20:0];
7
8 initial begin
9 $readmemb("test.txt", a);
10 for(i=0; i<=20; i=i+1) begin
11 #10;
12 $write("%s", a[i]);
13 end
14 end
15
16 endmodule