官方一点:
组合逻辑电路:简称组合电路,它由最基本的逻辑门电路组合而成。特点是:输出值只与当时的输入值有关,即输出惟一地由当时的输入值决定。电路没有记忆功能,输出状态随着输入状态的变化而变化,类似于电阻性电路,如加法器、译码器、编码器、数据选择器等都属于此类。
时序逻辑电路:简称时序电路,它是由最基本的逻辑门电路加上反馈逻辑回路(输出到输入)或器件组合而成的电路,与组合电路最本质的区别在于时序电路具有记忆功能。时序电路的特点是:输出不仅取决于当时的输入值,而且还与电路过去的状态有关。它类似于含储能元件的电感或电容的电路,如触发器、锁存器、计数器、移位寄存器、储存器等电路都是时序电路的典型器件。
人话:(做题够用就行)
全是基础门电路的叫组合逻辑电路,它没有clk, 只看输出、输入端就行,中间的变量都不用声明,常用于:3-8译码器、加法器、选择器啥的
有clk的一定是时序逻辑电路, 像什么触发器、锁存器啥的都算
什么样的是组合逻辑?
什么样的是时序逻辑?
1: 高电平 定义上讲>=电源电压的70%都叫高电平 取极值就是直接接电
0:低电平 <=电源电压的30%都叫低电平 取极值就是没接电
串行可理解为顺序执行,
并行是同一时间全执行。多用于流水线。
从仿真的角度来说,HDL语言面对的是编译器(如Modelsim等),相当于软件思路。
这时:
wire对应于连续赋值,如assign
reg对应于过程赋值,如always,initial
*********************************************************************************
从综合的角度来说,HDL语言面对的是综合器(如DC等),要从电路的角度来考虑。
这时:
1、wire型的变量综合出来一般是一根导线;
2、reg变量在always块中有两种情况:
(1)、always后的敏感表中是(a or b or c)形式的,也就是不带时钟边沿的,综合出来还是组合逻辑
(2)、always后的敏感表中是(posedge clk)形式的,也就是带边沿的,综合出来一般是时序逻辑,会包含触发器(Flip-Flop)
在设计中,输入信号一般来说你是不知道上一级是寄存器输出还是组合逻辑输出,那么对于本级来说就是一根导线,也就是wire型。而输出信号则由你自己来决定是寄存器输出还是组合逻辑输出,wire型、reg型都可以。但一般的,整个设计的外部输出(即最顶层模块的输出),要求是寄存器输出,较稳定、扇出能力也较好。
有几种情况变量需要定义成wire。
第一。assign 语句
例如:
reg a,b;
wire and_result;
...
assign and_result =a&&b;
你可以试试把wire定义成reg。综合器会报错。
第二。元件例化时候的输出必须用wire
例如:
wire dout;
ram u_ram
(
...
.out(dout)
...
);
【Mos管的工作原理】 https://www.bilibili.com/video/BV1344y167qm/?share_source=copy_web&vd_source=8b70f9233f14fa0e3233bf1868c76822
输入信号从组合逻辑电路传到输出时类似数据流动,而不存储。可通过连续赋值语句建模的方式叫数据流建模。
得用wire 声明 、assign赋值
assign #(延时多少) 变量名=啥啥啥
assign a=1'b0; int a=1;
assign a=1'b1;
只有wire类型能用
//各语句之间都是并行的关系,没有延时的情况下都是一起出结果的。
module in4_out_3(x1,x2,x3,x4,g,h,f);
input wire x1,x2,x3,x4;
output reg g,h,f;
assign g=(x1&&x3)||(x2&&x4);
assign h=(x1||x3)&&(x2||x4);
assign f=h||g;
endmodule
Verilog HDL支持设计者从电路外部行为的角度对其进
行描述,因此行为级建模是从一个层次很高的抽象角度来
表示电路的。其目标不是对电路的具体硬件结构进行说明,
它是为了综合以及仿真的目的而进行的。
跟时序电路有关系,像写c语言的函数、java的方法
module 名字(输出输出列表)+ ;
这个列表声不声明数据类型都行。这里没声明就下面声明一下
数据/变量类型声明
变量类型常用: wire reg(无符号) integer(有符号)
过程语句/赋值语句
过程:用initial/always写的
赋值:assign/<=/=
逻辑部分
endmodule
initial+语句块
+begin end
initial
begin
a=0;b=1;c=0;
#100 a=1,b=0;
#100 a=0;c=1;
#100 b=1;
#100 b=0;c=0;
end
+fork join
initial
fork
a=0;b=1;c=0;
#100 a=1,b=0;
#200 a=0;c=1;
#300 b=1;
#400 b=0;c=0;
join
always @(敏感列表)+xxx
对组合电路,敏感列表把全部输入信号写入
input in0,in1,in2,in3;
xxxx;
reg out;
always@(in0 or in1 or in2 or in3)
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
2'b11: out=in3;
default: out=2'bx;
endcase
endmodule
对时序电路,需要把关键信号(时间/rst为多)和部分输入信号放入列表里面
module mux4_1(out,in0,in1,in2,in3,sel);
input in0,in1,in2,in3;
ouput out;
input [1:0]sel;
reg out;
always@(in0 or in1 or in2 or in3 or sel)
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
2'b11: out=in3;
default: out=2'bx;
endcase
endmodule
敏感列表如何使用?
always@(in0 or in1) //当in0或in1值改变是 走下面的语句
always@(posedge clock) //当clock的上升沿到来时 走下面的语句
always@(negedge clock) //当clock的下降沿到来时 走下面的语句
always@(posedge clock or negedge reset ) //当clock的上升沿到来或reset下降沿到来时 走下面的语句
精准空降☞【【电子】Verilog硬件描述语言 西安电子科技大学 蔡觉平等主讲】 【精准空降到 14:07】 空降
你看前面说的应该会很懵,(1.5倍速)蔡老师讲到补充时序电路和组合电路结构 、流水线的思想那里应该就恍然大悟了。
最大区别:
一个不用等延时之间给,一个得等延时才能给
阻塞赋值语句:
b=a;
d=c;
在串行中b=a;必须执行完之后才能进行d=c
在并行中没啥影响。
非阻塞赋值语句:
b<=a;
在串行中也没有先后之分了。
先计算a的值,然后等待延迟时间的结束,再将计算的值赋给左边的变量。
D触发器:
//阻塞
module D_block(din,clk,out1,out2);
input wire din,clk;
output reg out1,out2;
always@(posedge clk or din or clk )
begin
out1=din;
out2=out1;
end
endmodule
/*
等效于
out1=din;
out2=din;
*/
//阻塞tb
module D_touchtb();
reg din,clk;
wire out1,out2;
initial
begin
din=0;clk=0;
#50 clk=1;
#50 din=1;
#50 clk=0;
#50 din=0;
end
D_block d0(din,clk,out1,out2);
endmodule
//非阻塞
module D_unblock1(din,clk,out1,out2);
input wire din,clk;
output reg out1,out2;
always@(posedge clk or din or clk )
begin
out1<=din;
out2<=out1;//out1 out2 kaishi doushi h,out2=h,out 1=din;
end
endmodule
//非阻塞tb
module D_unblocktb();
reg din,clk;
wire out1,out2;
initial
begin
din=0;clk=0;
#50 clk=1;
#50 din=1;
#50 clk=0;
#50 din=0;
end
D_unblock1 d0(din,clk,out1,out2);
endmodule
module D_unblock1(din,clk,out1,out2);
input wire din,clk;
output reg out1,out2;
always@(posedge clk )
begin
out1<=din;
out2<=out1;//out1 out2开始都是h,上升沿一到out2=h的同时out1=din;
end
endmodule
![在这里插入图片描述](https://img-blog.csdnimg.cn/4922b8d4dcfe4cd195a3cc01a60d3c67.png#pic_center)
##### 例题1:
根据不同的代码,画不同的电路图
~~~verilog
//代码1
module block3(a,b,c,clk,sel,out);
input a,b,c,clk,sel;
output out;
reg out,temp;
always@(posedge clk)
begin
temp=a&b;
if(sel) out=temp|c;
else out=c;
end
endmodule
//代码2
module block4(a,b,c,clk,sel,out);
input a,b,c,clk,sel;
output out;
reg out,temp;
always@(posedge clk)
begin
temp<=a&b;
if(sel) out<=temp|c;
else out<=c;
end
endmodule
//阻塞语句
always@(posedge clk)
begin
out3=out2;
out2=out1;
out1=out0;
out0=din;
end
//非阻塞语句
always@(posedge clk)
begin
out0<=din;
out1<=out0;
out2<=out1;
out3<=out2;
end
always @(posedge clk)
if(!reset) out = 8'h00; //同步清 零,低电平有效
else if(load) out = data; //同步置数
always @(posedge clk or negedge clear) //clk上升 沿和clear低电平清零有效
if(!clear) //异步清零 out=0;
else out=out+1;-->
assign在行为级建模是给reg用的,wire用不了的,
重复赋值会保存这个新值在reg中
对于deassign语句,
是一条撤销连续赋值的语句。执行后,原来由assign语句对
变量进行的连续赋值操作将失效,恢复原来的值
也是赋值,reg和wire都能用;
优先级比assign、deassign高
对某种信号进行临时性的赋值和测试时常用
长什么样啊?
force out=a|b;
#5;
release out
跟c java中的差不多,不用刻意记
格式:
case(控制表达式)
值1:语句块1
值2:语句块2
...
值n:语句块n
default:语句块n+1
endcase
注意点:
forever
forever 语句一般用在initial过程语句中,如果在forever语句中没有 加入时延控制,forever语句将在0时延后无限循环下去
initial
begin
clock=0;
forever #50 clock=~clock;
end
repeat
先计算出循环次数表达 式的值,并将它作为循环次数保存起来;接着执行后面的 语句块(循环体),语句块执行结束后,将重复执行次数减 去一次,再接着重新执行下一次的语句块操作,如此重复, 直至循环执行次数被减为0时,结束整个循环过程
//等效于java或者c里面的 while(n-->0;)
initial
begin
clock=0;
repeat(8) clock=~clock;//循环体所预先制定的循环次数为8次,相应产生
4个时钟周期信号
end
while
先判断条件表 达式是否为真,如果是,则执行后面的语句,接着再回来 判断条件表达式是否仍为真,只要是真,再执行语句,直 至某一次执行完语句后,判断出条件表达式的值为非真时, 结束循环过程。为保证循环过程的正常结束,通常在循环 体内部必定有一条语句用以改变条件表达式的值
//同java 和c
initial
begin
clock=0;
while(1)
#50 clock=~clock;
end
for
同java c
initial
begin
clk=0;
for(i=0;i>=0;i=i+1)
#50 clk=~clk;
end
module shift_regist2(Q,D,rst,clk);
output [7:0] Q;
input D,rst,clk;
reg [7:0] Q;
integer i;
always @(posedge clk)
if (!rst) Q<=8'b000000;
else
for (i=7;i>0;i=i-1)
begin
Q[i]<=Q[i-1];
Q[0]<=D;
end
endmodule
D_unblock1 d0 (din,clk,out1,out2);
D_unblocl1 d[15:0](din,clk,out1,out2);
dff U1(.q(out[0]),.d(din),.clk(clock),.clr(clear));
module para1(C,D);
parameter a=1;
parameter b=1; ...
endmodule
module para2; ...
para1 #(4,3) U1(C1,D1) ;
para1 #(.b(6),.a(5)) U2(C2,D2); //语句2 ...
endmodule
怎么写呢?
and A1 (out1, in1, in2);
or O2 (a, b, c, d);
xor X1(x_out, p1, p2);
基本的nmos开关电路
module aNMOS(din,ctr,out);
input din,ctr;
output out;
nmos U1(out,din,ctr);
endmodule
ff U1(.q(out[0]),.d(din),.clk(clock),.clr(clear));
~~~verilog
module para1(C,D);
parameter a=1;
parameter b=1; ...
endmodule
module para2; ...
para1 #(4,3) U1(C1,D1) ;
para1 #(.b(6),.a(5)) U2(C2,D2); //语句2 ...
endmodule
怎么写呢?
and A1 (out1, in1, in2);
or O2 (a, b, c, d);
xor X1(x_out, p1, p2);
基本的nmos开关电路
module aNMOS(din,ctr,out);
input din,ctr;
output out;
nmos U1(out,din,ctr);
endmodule