Verilog语法讲解

举报
nimo的小舔狗 发表于 2022/06/23 00:55:13 2022/06/23
【摘要】 模块构成: 端口说明:模块声明的接口类型,主要为input和output 数据类型:net线网类型(wire),variable类型(reg和integer) 在一个模块中,在initial和always中,被赋值的变量一定是variable类型(reg和integer) assign、模块调用、门原件调用的输出信号是w...

模块构成:

端口说明:模块声明的接口类型,主要为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,表示代码块的边界,其中代码为串行关系,先后顺序执行,时间单向累加


  
  1. initial
  2. begin
  3. #4 x=0;//(1)
  4. #8 y=1;//(2)
  5. end

上述代码中,先延迟4,再延迟8,共计延迟12个单位

2.fork-join, 代码边界,代码属于并行关系,同时执行


  
  1. initial
  2. fork
  3. #4 x=0;
  4. #8 y=1;
  5. join

上述代码中,同时执行,延迟四个时间单位和延迟8个时间单位后分别执行,攻击延迟8个时间单位

always:可用在综合代码中,也可用在仿真代码中

always一般与begin-end一起使用,只要满足触发条件,就会一直执行。

always语句的格式
 


  
  1. always @(<敏感信号表达式event-expression>)
  2. begin//过程赋值
  3. //if-else,case,casex,casez选择语句
  4. //while,repeat,for循环
  5. //task,function调用
  6. //其他语句
  7. 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)中是没有参数列表的


  
  1. always@(....)
  2. c=ceshi(a0,b0)*5+20;

任务的调用:只能在intial或者always过程块中,独立成语句


  
  1. always@(*)
  2. begin
  3. ceshi(a0,b0,c0);
  4. end
  5. //注意c0在过程块中被赋值,因此是reg/integer类型。

函数的定义:五参数列表,有返回数据位宽

function[1:0] ceshi;

函数的调用:可以参与assign语句:assign c=ceshi(a0,b0)+10;

也可以在过程块中调用


  
  1. always@(....)
  2. 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中的结果中获取。


  
  1. always @(posedge clk)
  2. begin tempa=ina; tempb=inb; tempci=cin; end //输入数据缓存
  3. always @(posedge clk)
  4. begin {firstco,firsts}=tempa[1:0]+tempb[1:0]+tempci; //第一级加(低2位)
  5. firsta=tempa[7:2]; firstb=tempb[7:2]; end//未参加计算的数据缓存

文章来源: blog.csdn.net,作者:渣渣ye,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/yyfloveqcw/article/details/125389230

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。