目录
文章来源地址https://www.toymoban.com/news/detail-849367.html
Verilog HDL 门级建模
各种逻辑门的表示和使用
门级建模书写实例
Verilog HDL 数据流建模
数据流建模
数据流建模书写实例
组合电路行为级建模
always语句
条件语句
多路分支语句
循环语句
for
while
repeat
forever
行为级建模示例
文章来源:https://www.toymoban.com/news/detail-849367.html
Verilog HDL 门级建模
可以理解为对逻辑电路中各个门依次进行描述二建模成组合逻辑电路
各种逻辑门的表示和使用
- 多输入门(只允许有一个输出端,但可以有多个输入端):and(与门)、nand(与非门)、or(或门)、nor(或非门)、xor(异或门)、xnor(同或门)
- 多输出门(只允许有一个输入端,但可以有多个输出端):buf(缓冲器)、not(反相器,非门)
- 三态门(有一个输出,一个数据输入,一个控制输入):
- bufif1:控制信号为高电平时,输入和输出相同,否则输出高阻态z
- bufif0:控制信号为低电平时,输入和输出相同,否则输出高阻态z
- notif1:控制信号为高电平时,输入和输出相反,否则输出高阻态z
- notif0:控制信号为低电平时,输入和输出相反,否则输出高阻态z
输出的格式
//多输入门
Gate Name(out, in1, in2, ..., inN);//Gate是上述六种多输入门中的一种,Name为自己命名的实例引用名(不需要声明,且可以省略),括号内的是输入输出端口(左边第一个端口必须是输出端口,其他端口均为输入)
//举例
and U1(out, in1, in2, in3);
//多输出门
Gate Name(out1, out2, ..., outN, in);//Gate是buf或者not,Name为自己命名的实例引用名(不需要声明,且可以省略),括号内的是输入输出端口(右边第一个端口必须是输入端口,其他端口均为输出)
//举例
buf B1(out1, out2, out3, in);
//三态门
Gate Name(out, in, ctrl);//Gate是四种三态门中的一种,Name为自己命名的实例引用名(不需要声明,且可以省略),括号内的是输入输出端口(从左到右依次为输出,数据输入,控制输入)
//举例
notif1 N1(out, in, ctrl);
门级建模书写实例
上一篇blog中提到的二选一数据选择器
module TueBitSelector(
input D0, D1, S,
output Y
);
wire Snot, A, B;
not U1(Snot, S);
and U2(A, D0, Snot);
and U3(B, D1, S);
or U4(Y, A, B);
endmodule
仿真出的波形如图
Verilog HDL 数据流建模
数据流建模
数据流建模使用的连续赋值语句由关键词assign开始,后面跟着由操作数和运算符等组成的逻辑表达式
可以简单理解为使用assign语句对输出信号进行赋值
用法如下:
wire [位宽]signal1, signal2, ..., signalN;
assign signal1 = 逻辑表达式1;
assign signal2 = 逻辑表达式2;
assign signal3 = 逻辑表达式3;
...;
assign signalN = 逻辑表达式N;
注意:assign赋值语句只能对wire信号进行赋值,所以signal必须是wire类型的
assign赋值的语句运行时,只要逻辑表达式中的任何逻辑值发生变化,则该逻辑表达式的值就会被计算出来赋值给左边
数据流建模书写实例
该二选一数据选择器Y对应的逻辑表达式为
(D0&(~S))|(D1&S)
故使用数据流建模方式可以将代码改写为
module TueBitSelector(
input D0, D1, S,
output wire Y
);
assign Y = (D0&(~S))|(D1&S);
endmodule
仿真波形仍然如此
组合电路行为级建模
在 Verilog HDL 中,从逻辑电路外部行为的角度对其功能和算法进行描述,称为行为建模。主要使用关键词为 initial 语句或 always 的两种过程化的结构来描述电路的行为
在一个模块的内部可以包含多个 initial 或 always,仿真时这些语句并行执行,即与它们在模块内部排列的顺序无关,都从仿真的 0 时刻开始执行。 initial(初始化)主要在测试模块中使用,通常用来描述激励信号,仿真时仅执行一次
initial 语句主要是面向仿真的过程语句,逻辑综合工具不支持 initial 语句。在这两种结构内部,经常会用到条件语句( if-else)、多路分支语句( case-endcase)和循环语句等比较抽象的编程语句,这些语句也称为过程化语句。
always语句
always 本身是一个无限循环语句,即不停地循环执行其内部的过程语句,直到仿真过程结束。但用它来描述硬件电路的逻辑功能时,通常在 always 后面紧跟着循环的控制条件,所以always 语句的一般用法如下:
always @(敏感信号列表) //敏感信号发生改变时或者条件变为真时,执行该循环
begin:块名 //块名可以省略
块内部局部变量的定义;
过程赋值语句;
end
//begin和end之间只有一条语句时,begin和end可以省略不写
//begin 和 end 将多条过程赋值语句包围起来,组成一个顺序语句块,块内的语句按照排列顺序依次执行,最后一条语句执行完后,执行暂停,然后 always 语句处于等待状态,等待下一个事件的发生。
注意:过程赋值语句中的左边的变量必须被定义成reg类型,右边的变量可以是任意数据类型
条件语句
这里与c语言中大致相同,具体格式如下,不在过多阐述
if (condition_expr1) true_statement1;
else if (condition_expr2) true_statement2;
else if (condition_expr3) true_statement3;
……
else default_statement;
注意:如果判断条件计算出为0,z或者x时,都按假处理
多路分支语句
这与C语言中的switch...case语句相似,但也有不同,具体格式和说明如下
case (case_expr) //整个多路分支由case与endcase包裹
item_expr1: statement1;//每一行由 值:功能 组成,并且只执行该值下的功能
//如果statement中的语句不止一句的话,则需要用begin...end组成一个顺序语句块
item_expr2: statement2;
……
default: default_statement;
endcase
另外, case 语句还有两种变体,即 casez 和 casex。
在 casez 语句中,将 z 视为无关值,如果比较的双方( case_expr 的值与 item_expr 的值)有一方的某一位的值是 z,那么该位的比较就不予考虑,即认为这一位的比较结果永远为“真”,因此只需关注其他位的比较结果。
在 casex语句中,将 z 和 x 都视为无关值,对比较双方( case_expr 的值与 item_expr 的值)出现 z 或 x的相应位均不予考虑。注意,对无关值可以用“?”表示。除了用关键词 casez 或 casex 来代替case 以外, casez 和 casex 的用法与 case 语句的用法相同。但由于综合器对这两个关键字的支持情况略有差异,因此建议使用完整的 case 结构,而不使用 casex 或 casez。
循环语句
for
for是一种条件循环语句,具体表达式如下
for(表达式1;表达式2;表达式3;) 语句块;
与C语言相似
表达式1用来给循环计数变量赋初值,只在第一次循环执行
表达式2是循环所需的条件
表达式3是修改循环变量的值,当修改后的值不满足表达式2时,则退出循环
while
while循环表达式如下
while(条件表达式) 语句块;
当条件表达式为真时,while内语句块执行,为假时,不执行,且0,z,x均视为假
repeat
repeat循环表达式如下
repeat(循环次数表达式) 语句块;
repeat执行循环的次数由循环表达式计算得出,若时0,z,x,则循环0次
可以采用repeat循环产生时钟信号
module Clock;
reg CP;
initial begin
CP=1'b0; //在0时刻, CP=0
repeat(10) //循环次数为10
#10 CP=~CP;
end
endmodule
forever
forever是一种无限循环,其表达式如下
forever 语句块;
forever将不停执行后面的语句块,一般要在语句块中采取时序控制结构,不然后面的语句将永远无法执行
使用forever产生时钟信号的代码如下
`timescale 1ns/1ns //时间单位为ns,精度为1ns
module CP_gen();
reg CP;
initial begin
CP=1'b1; //在0时刻, CP=1
#50 forever
#25 CP=~CP; //每隔25个ns, CP反相一次
end
initial
#300 $stop; //到300ns时,结束循环
endmodule
行为级建模示例
在之前的二选一数据选择器中,测试模块就采用行为级建模
`timescale 1 ns/ 1 ns
module TueBitSelector_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg D0;
reg D1;
reg S;
// wires
wire Y;
// assign statements (if any)
TueBitSelector i1 (
// port map - connection between master ports and signals/registers
.D0(D0),
.D1(D1),
.S(S),
.Y(Y)
);
initial begin
S = 1'b0;
D0 = 1'b0;
D1 = 1'b0;
#1 D0 = 1'b1;
#1 D0 = 1'b0;
#1 D1 = 1'b1;
#1 D0 = 1'b1;
#1 S = 1'b1;
#1 D0 = 1'b0;
#1 D1 = 1'b0;
#1 D0 = 1'b1;
#1 D0 = 1'b0;
#1 D1 = 1'b1;
#1 D0 = 1'b1;
end
initial begin
$monitor($time,":\tS=%b\tD1=%b\tD0=%b\tY=%b", S, D1, D0, Y);
end
endmodule
到了这里,关于【FPGA】组合逻辑电路三种建模方式(Verilog HDL 门级建模、Verilog HDL 数据流建模、组合电路行为级建模)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!