Verilog语法讲解
模块构成:
端口说明:模块声明的接口类型,主要为input和output
数据类型:net线网类型(wire),variable类型(reg和integer)
在一个模块中,在initial和always中,被赋值的变量一定是variable类型(reg和integer)
assign、模块调用、门原件调用的输出信号是wire类型
定义符号常量:parameter wid=18;
reg[3:0] c; //位宽为4的寄存器向量
reg c[4:0]; //容量为5的存储器
reg[3:0] c[4:0]; //字长为4,容量为5的存储器
==:参与比较的两位操作数逐位相等,结果唯一,若有x或z,结果为x
===:不定态或高阻态也需要全部一致才为真
>>>:算数右移
>>:逻辑右移
条件运算符:signal=condition?true_expression:false_expression;
单向左移a={a,count};// reg[7:0] a是移位存储器; count是待存入数据,可以多位
单向右移a={count,a[3:1]};
循环右移a={a[0],a[3:1]};//注意 循环右移1位,移位数据补在高位,低位拼接部分需要截位处理,否则高位存入不到序列
循环左移 a={a,a[3]}。左移1位,移位数据补在最低位,可以赋值时候自动截位。
过程语句和块语句:
initial:用在仿真代码中,只执行一次
1.begin-end,表示代码块的边界,其中代码为串行关系,先后顺序执行,时间单向累加
-
initial
-
begin
-
#4 x=0;//(1)
-
#8 y=1;//(2)
-
end
上述代码中,先延迟4,再延迟8,共计延迟12个单位
2.fork-join, 代码边界,代码属于并行关系,同时执行
-
initial
-
fork
-
#4 x=0;
-
#8 y=1;
-
join
上述代码中,同时执行,延迟四个时间单位和延迟8个时间单位后分别执行,攻击延迟8个时间单位
always:可用在综合代码中,也可用在仿真代码中
always一般与begin-end一起使用,只要满足触发条件,就会一直执行。
always语句的格式:
-
always @(<敏感信号表达式event-expression>)
-
-
begin//过程赋值
-
-
//if-else,case,casex,casez选择语句
-
-
//while,repeat,for循环
-
-
//task,function调用
-
-
//其他语句
-
-
end
“always”过程语句通常是带有触发条件的,触发条件写在敏感信号表达式中,只有当触发条件满足时, “begin-end”块语句才能被执行。
1.always@(a),当a变化,执行
2.always@(c,d),当c或d变化,执行
3.always@(*),代表所有驱动信号
时序逻辑always:
使用边沿触发,posedge上升沿,negedge下降沿
若时序逻辑中,时钟clk,使能(控制)信号reset、load
always@(posedge clk)//reset、load同步信号
always@(posedge clk,posedge reset)//reset异步(高),load同步
always@(posedge clk,posedge reset,negedge load)
//reset异步(高)、load异步(低)
赋值语句(assign、=、<=)
assign属于持续赋值语句
assign c=ab+cd 等效于 assign c= (a&b)|(c&d)
c数据类型为wire类型
阻塞赋值“=”:可用于assign赋值,也可用于always语句,按步骤执行下去
always@(posedge clk)
begin a=b;//该语句结束“;”,b的值就会覆盖a
c=a;//上一句执行完再执行该句
end
代码执行完:c==a==b,逐步执行
非阻塞赋值“<=”:只能用于always语句中,常用于时序逻辑
always@(posedge clk)
begin
a<=b;//该句执行完,b并未覆盖a
c<=a;//该句执行完,a并未覆盖c
end//遇到快语句结束符,上面改两条语句同时执行
代码执行完:b覆盖a的同时,a覆盖b,因此 c中保存的是a,不是b;a中保存的是b。因此a与b同,c与a同,但b和c未必相同。
case结构中条件的判定为“===”,必须逐位全相等
严格程度:case>casez(忽略z对应位)>casex(忽略z、x对应位)
循环语句:for可综合为电路和用于仿真,forever、repeat、while只能用于仿真
repeat(10) #5 clk=~clk; //循环10次
forever #5 clk=~clk; //循环不停
while(i<10)i=i+1; //循环10次
任务(task)与函数(function)
task ceshi;
在任务(task)中是没有参数列表的
-
always@(....)
-
c=ceshi(a0,b0)*5+20;
任务的调用:只能在intial或者always过程块中,独立成语句
-
always@(*)
-
begin
-
ceshi(a0,b0,c0);
-
end
-
//注意c0在过程块中被赋值,因此是reg/integer类型。
函数的定义:五参数列表,有返回数据位宽
function[1:0] ceshi;
函数的调用:可以参与assign语句:assign c=ceshi(a0,b0)+10;
也可以在过程块中调用
-
always@(....)
-
c=ceshi(a0,b0)*5+20;
assign语句、模块调用、always过程快、门原件调用之间是并发关系,不能嵌套
always块中,begin--end中代码用阻塞赋值=,语句是顺序关系
always块中,begin--end中代码用非阻塞赋值<=,语句是并发关系
initial块中,begin--end中代码用阻塞赋值=,语句是顺序关系,不建议用<=容易混乱
initial块中,fork--jion中代码用阻塞赋值=,语句是并发关系
系统任务和函数
$time 、$realtime是属于显示仿真时间标度的系统函数,time显示整数,realtime显示小数 $finish、$stop是退出仿真器结束仿真、暂停
$random 产生随机数。当函数被调用时返回一个32位的随机数。这是一个带符号的整型数。
一般用法是:$random%b,其中b>0.他给出了一个范围在(-b+1):(b-1)中的随机数。
下面给出例子:
reg [23:0]rand;
rand=$random%60; //生成-59~59之间的随机数
rand={$random}%60; //生成0~59之间的随机数
$display(“格式控制符”,输出变量列表);调用一次显示一次,显示完毕则结束
$monitor(“格式控制符”,输出变量列表);一般单独放在一个initial中,只要输出变量有变化,则多次输出
时间单位和精度:
`timescale <时间单位> /<时间精度> ,其中时间度量的符号有:s、ms、us、ns、ps和fs
例如:
`timescale 1ns/100ps,含义为:时间延迟单位为1ns,时间精度为100ps(即精确到0.1ns,小数点后1位小数)。
`timescale 1ns/1ns,含义为:时间延迟单位为1ns,时间精度为1ns(即精确到1ns,整数值)
FSM有限状态机
由现态逻辑、次态逻辑和输出逻辑组成
摩尔型:输出只与当前状态有关
米粒型:输出与当前状态和输入都有关
三段式:现态(CS)、次态(NS)、输出逻辑(OL)各用一个always过程描述
两段式:CS+NS,OL双过程描述
一段式:在单过程描述方式中,将状态机的现态、次态和输出逻辑放在一个always过程中进行描述
流水线
由多个always实现,每个always对应一级流水线
每一个always中,表达式左侧被赋值变量独立定义(就是中间隔离寄存器),保存当前一级的结果和未被处理的数据。表达式右侧(数据来源),从前一级always中的结果中获取。
-
always @(posedge clk)
-
begin tempa=ina; tempb=inb; tempci=cin; end //输入数据缓存
-
always @(posedge clk)
-
begin {firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci; //第一级加(低2位)
-
firsta=tempa[7:2]; firstb=tempb[7:2]; end//未参加计算的数据缓存
文章来源: blog.csdn.net,作者:渣渣ye,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/yyfloveqcw/article/details/125389230
- 点赞
- 收藏
- 关注作者
评论(0)