第7章 基于EDA的时序电路设计综合及验证7175.docx
《第7章 基于EDA的时序电路设计综合及验证7175.docx》由会员分享,可在线阅读,更多相关《第7章 基于EDA的时序电路设计综合及验证7175.docx(45页珍藏版)》请在冰豆网上搜索。
![第7章 基于EDA的时序电路设计综合及验证7175.docx](https://file1.bdocx.com/fileroot1/2023-3/29/5a79f1d1-802b-4cc7-b073-a6b50c69f6fd/5a79f1d1-802b-4cc7-b073-a6b50c69f6fd1.gif)
第7章基于EDA的时序电路设计综合及验证7175
第7章基于EDA的时序电路设计、综合及验证
学习基础:
(1)第3章介绍了时序逻辑电路的基础知识。
学习本章前,应先掌握第3章的知识。
(2)第4章介绍了VerilogHDL的基本语法及简单设计的建模方法。
(3)5.5~5.7的综合实例,介绍了EDA工具LiberoIDE的使用。
本章所有综合和验证均基于LiberoIDE环境实现。
阅读指南:
●本章讲述内容对应第3章的知识,把相应功能通过VerilogHDL语言进行实现。
●本章多处对同一个设计提供了多种设计思路和实现方法,并不是所有都是最优的方法,只是方便对比和学习。
读者可根据情况选择合适的方法。
●7.4、7.6、7.7中讨论了第3章中没有涉及的理论知识和多个综合例子,这些知识和例子综合性强,较难理解,但却是数字系统实际开发中非常重要和实用的内容,对于想进入数字系统设计实践阶段的读者来说很有实际意义。
7.1锁存器
7.1.1基本RS锁存器
(一)
1.使用Verilog进行描述
modulers_1(R,S,Q,Qn);
inputR,S;
outputQ,Qn;//Qn表示
,而不是时序电路中的现态
。
regQ;
assignQn=~Q;
always@(RorS)//通过case语句,按真值表方式写出程序逻辑。
case({R,S})
2'b01:
Q=1;
2'b10:
Q=0;
2'b11:
Q=1'bx;
endcase
endmodule
读者在一开始看这种程序时很容易产生疑问:
触发器是存放数字电路中基本二进制信号的单元电路,也就是寄存器变量Q的值是需要使用触发器来存放,而触发器是由锁存器所构成,用触发器存放的Q来实现一个锁存器显然是不合理的。
这就需要读者理解在VerilogHDL中,采用行为风格编写代码,是为了让程序编写者可用更趋向行为的方式更方便的编写代码,而不需考虑具体的物理细节。
虽然在程序中指定要使用一个寄存器变量Q,但在使用EDA工具进行综合的时候,是不会也不可能用触发器来实现锁存器的,通过综合结果可看出。
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench();
regr,s;
wireq,qn;
rs_1test_rs(r,s,q,qn);
initial
begin
r=0;s=0;
#10s=1;
#10r=1;
#10s=0;
#10r=0;
#10;
end
endmodule
4.功能验证
综合前仿真
综合后仿真
波形说明:
(1)综合前仿真(功能仿真)的结果中,在0~10ns和20~30ns之间,q和qn都是x态。
0~10ns之间产生的x态是因为r和s的值为0,q保持原态;20~30ns之间产生的x态是因为r和s的值为1,代码中规定了处理为x态。
(2)综合后仿真的结果中,20~30ns之间q和qn并不是x态(都为0),具体状态视20ns时r、s、q的值而定。
7.1.2基本RS锁存器
(二)
1.使用Verilog进行描述
modulers_2(R,S,Q,Qn);
inputR,S;
outputQ,Qn;
nor(Q,R,Qn);
nor(Qn,S,Q);
endmodule
2.综合结果
测试平台与设计一相同。
3.功能验证
波形分析:
对比设计一和设计二的波形,可发现在设计一中,当r,s为1时,Q和Qn均为x,而在设计二中Q和Qn均为0。
由于对RS锁存器来说,R,S同为1是不允许的,故可忽略之。
7.1.3门控D锁存器
1.使用Verilog进行描述
modulelatch_1_a(Clk,D,Q);
inputClk,D;
outputQ;
regQ;
always@(DorClk)
if(Clk)Q<=D;
endmodule
程序说明:
(1)当Clk为高电平时,输出Q的数值会随D输入的数据更新,而当Clk为低电平时将保持其高电平时锁入的数据。
(2)Clk由0变为1时,满足if语句的条件,语句“Q<=D”被执行,将D的数值赋值给Q;Clk由1变为0时(无论D是否变化),都将执行if语句,但此时Clk=0,语句Q<=D不被执行,于是Q保持原值不变。
(3)如果敏感信号D发生变化,但Clk为0,Q保持原值不变;如果敏感信号D发生变化,且Clk为1,则执行语句Q<=D。
2.综合结果
\
3.测试平台设计
`timescale1ns/1ns
moduletestbench_latch;
regclk,D;
wireQ;
initial
begin
clk=0;
#50clk=1;
#100clk=0;
#100clk=1;
end
initial
begin
D=0;
repeat(20)
#20D=$random;
end
latch_1_atestbench_latch(clk,D,Q);
endmodule
4.功能验证
以下设计使用数据流风格,设计思路、综合结果、测试平台、功能验证结果都相同。
modulelatch_1_b(Clk,D,Q);
inputClk,D;
outputQ;
assignQ=Clk?
D:
Q;
endmodule
7.1.4带清零D锁存器
(一)
1.使用Verilog进行描述
modulelatch_1_c(Clk,D,Q,Rst);
inputClk,D,Rst;
outputQ;
regQ;
always@(DorClkorRst)
if(!
Rst)Q<=0;//语句1
elseif(Clk)Q<=D;
endmodule
程序说明:
(1)程序采用具有时序语句特色的进程语句,其中数据信号D、时钟信号Clk和清0(复位)信号Rst都被列于敏感信号表中,实现了Clk的电平触发特性和Rst的异步特性。
(2)异步清0实现的效果,就是当Rst一旦变成0,就马上对输出进行清0,而不需要理会时钟、输入数据等的状态。
也就是Rst是优先级最高的控制信号,在代码(语句1)中,通过“if…elseif…”语句来实现优先级控制。
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench_latch;
regclk,D,rst;
wireQ;
initial
begin
clk=0;
#50clk=1;
#70clk=0;
#80clk=1;
end
initial
begin
D=0;
repeat(20)
#20D=$random;
end
initial
begin
rst=0;
#60rst=1;
#80rst=0;
#40rst=1;
end
latch_1_ctestbench_latch(clk,D,Q,rst);
endmodule
4.功能验证
7.1.5带清零D锁存器
(二)
modulelatch_1_d(Clk,D,Q,Rst);
inputClk,D,Rst;
outputQ;
assignQ=(!
Rst)?
0:
(Clk?
D:
Q);
endmodule
程序采用连续赋值语句,使用了条件操作符的嵌套。
实现思路与设计
(一)相同。
综合结果与设计
(一)基本相同,只有元件名称稍有不同。
测试平台、功能验证结果与设计
(一)相同。
7.2触发器
D触发器是最简单、最常用且最具代表性的时序电路,它是数字系统设计中最基本的底层时序单元,JK和T触发器都由D触发器构建而来。
7.2.1D触发器
1.使用Verilog进行描述
moduled_ff_1(D,Clk,Q);
inputD,Clk;
outputQ;
regQ;
always@(posedgeClk)
Q<=D;
endmodule
程序说明:
(1)当Clk的上升沿到达时,立即将D送往输出Q;若没有Clk的上升沿到达,Q的值保持不变;
(2)该D触发器的设计与门控D锁存器设计非常类似,仅仅是由电平敏感变成了上升沿敏感。
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench;
regD,Clk;
wireQ;
initial
Clk=0;
parameterclock_period=20;
always#(clock_period/2)Clk=~Clk;
initial
begin
D=0;
repeat(20)
#20D=$random;
end
d_ff_1testbench_d(D,Clk,Q);
initial
#300$finish;
endmodule
4.功能验证
7.2.2D触发器(异步清零边沿触发)
1.使用Verilog进行描述
moduled_ff_2(D,Clk,Q,Rst,En);
inputD,Clk,Rst,En;
outputQ;
regQ;
always@(posedgeClkornegedgeRst)
begin
if(!
Rst)Q<=0;
elseif(En)Q<=D;
end
endmodule
程序说明:
(1)所谓“异步”是指独立于时钟控制的复位控制端,即在任何时刻,只要Rst=0,D触发器的输出端即刻被清0,与时钟状态无关;而时钟使能端En的功能是:
只有当En=1时,时钟上升沿才有效。
(2)无论Clk是否有跳变,只要Rst的下降沿到达,即执行Q<=0,此后如果Rst一直保持为0,则无论是否有Clk的边沿跳变信号,Q均输出0;如果Rst一直为1,且Clk有上升沿到达,则会执行赋值操作Q<=D,从而更新Q值。
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench;
regD,Rst,Clk,En;
wireQ;
d_ff_2testbench_dff(D,Clk,Q,Rst,En);
initial
Clk=0;
#400$finish;
parameterclock_period=20;
always#(clock_period/2)Clk=~Clk;
initial
begin
D=0;
repeat(20)
#20D=$random;
end
initial
begin
Rst=0;
repeat(20)
#20Rst=$random;
end
initial
begin
En=0;
repeat(20)
#20En=$random;
end
endmodule
4.功能验证
7.2.3D触发器(同步清零边沿触发)
moduled_ff_3(D,Clk,Q,Rst);
inputD,Clk,Rst;
outputQ;
regQ;
always@(posedgeClk)
if(Rst==1)Q=0;
elseif(Rst==0)Q=D;
endmodule
程序说明:
所谓“同步”是指某控制信号只有在时钟信号有效时才起作用。
信号敏感表列表中只放了对Clk上升沿的敏感表述,即此过程中的所有其它输入信号都相对于时钟Clk而同步。
7.2.4JK触发器
1.使用Verilog进行描述
JK触发器比RS触发器增加了翻转功能,以下设计与RS触发器类似。
modulejk_ff(J,K,Clk,Q,Qn);
inputJ,K,Clk;
outputQ,Qn;
regQ;
assignQn=~Q;
always@(posedgeClk)
case({J,K})
2'b00:
Q<=Q;
2'b01:
Q<=1'b0;
2'b10:
Q<=1'b1;
2'b11:
Q<=~Q;
default:
Q<=1'bx;
endcase
endmodule
2.综合结果
3.测试平台设计
测试平台的设计与RS触发器的方法一致,只需把R,S改成J,K,修改对接模块名称即可。
`timescale1ns/1ns
moduletestbench;
regj,k,Clk;
wireQ,Qn;
initial
Clk=0;
parameterclock_period=20;
always#(clock_period/2)Clk=~Clk;
initial
begin
j=0;
repeat(20)
#20j=$random;
end
initial
begin
k=0;
repeat(20)
#20k=$random;
end
initial
#300$finish;
jk_fftestbench_jk(j,k,Clk,Q,Qn);
endmodule
4.功能验证
7.2.5RS触发器
1.使用Verilog进行描述
以下设计是在RS锁存器设计
(一)的基础上,加入上升沿控制而写成。
加入了时钟信号Clk,改变了敏感事件为Clk上升沿触发。
modulers_ff(R,S,Clk,Q,Qn);
inputR,S,Clk;
outputQ,Qn;
regQ;
assignQn=~Q;
always@(posedgeClk)
case({R,S})
2'b01:
Q<=1;
2'b10:
Q<=0;
2'b11:
Q<=1'bx;
endcase
endmodule
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench;
regR,S,Clk;
wireQ,Qn;
initial
Clk=0;
parameterclock_period=20;
always#(clock_period/2)Clk=~Clk;
initial
begin
R=0;
repeat(20)//语句1
#20R=$random;
end
initial
begin
S=0;
repeat(20)//语句2
#20S=$random;
end
rs_fftestbench_rs(R,S,Clk,Q,Qn);
initial
#300$finish;//语句3
endmodule
程序说明:
语句1和语句2要求生成20个随机的R和S,共需要400个单位时间,但语句3却要求在单位时间300时结束,那么程序会按哪一个要求进行呢?
答案可从以下的功能验证波形中看到,程序会在单位时间300时结束。
4.功能验证
综合前仿真
综合后仿真
波形分析:
从波形图上看,综合前和综合后的Q输出结果不一样,综合前仿真的Q输出有很多的x态。
该现象与RS锁存器设计一中出现的现象是同一原因,请参考前面(RS锁存器设计一)的说明。
7.2.6T触发器(异步清零)
1.使用Verilog进行描述
modulet_ff(T,Clk,Rst,Q,Qn);
inputT,Clk,Rst;
outputQ,Qn;
regQ;
assignQn=~Q;
always@(posedgeClkorposedgeRst)
if(Rst)Q<=0;
elseif(T)Q<=~Q;
endmodule
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench_t;
regT,Clk,Rst;
wireQ,Qn;
parameterclock_period=20;
initial
Clk=0;
always#(clock_period/2)Clk=~Clk;
initial
begin
Rst=0;
#30Rst=1;
#30Rst=0;
#30Rst=1;
#30Rst=0;
end
initial
begin
T=0;
repeat(20)
#20T=$random;
end
t_fftestbench_t(T,Clk,Rst,Q,Qn);
initial
#400$finish;
endmodule
4.功能验证
波形分析:
假设Rst一直不产生上升沿变化,那么会发生什么事情呢?
如果Rst不产生上升沿变化,则程序代码不被执行,无论T和Clk如何变化,Q和Qn将一直保持x值。
故一般应进行数据的初始化处理。
7.3寄存器
7.3.1基本寄存器
以下讨论由4位D触发器构成的4位寄存器。
对于基本寄存器,数据或代码只能并行送入寄存器中,需要时也只能并行输出。
1.使用Verilog进行描述
modulereg4_1(Clr,Clk,D,Q);
output[3:
0]Q;
input[3:
0]D;
inputClk,Clr;
reg[3:
0]Q;
always@(posedgeClkornegedgeClr)
begin
if(!
Clr)Q<=0;
elseQ<=D;
end
endmodule
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench;
regClr,Clk;
reg[3:
0]D;
wire[3:
0]Q;
initialClk=0;
parameterclock_period=20;
always#(clock_period/2)
Clk=~Clk;
initial
begin
D=0;
repeat(20)
#20D=$random;
end
initial
begin
Clr=0;
repeat(20)
#20Clr=$random;
end
reg4_1test_reg(Clr,Clk,D,Q);
initial
#400$finish;
endmodule
4.功能验证
说明:
图中Q的输出有些地方为空白,是由于不够位置显示,放大波形即可看到具体的值。
7.3.2基本寄存器(异步清零异步置1)
1.使用Verilog进行描述
以下的设计具有异步清零端(Aclr)和异步置1端(Aset),异步清零的优先级比异步置1高。
modulereg4_2(Data,Aclr,Aset,Clock,Q);
input[3:
0]Data;
inputAclr;
inputAset;
inputClock;
output[3:
0]Q;
reg[3:
0]Q;
always@(posedgeClockornegedgeAclrorposedgeAset)
if(!
Aclr)
Q<=4'b0000;
elseif(Aset)
Q<=4'b1111;
elseQ<=Data;
endmodule
2.综合结果
3.测试平台设计
`timescale1ns/1ns
moduletestbench;
reg[3:
0]Data;
regAclr,Aset,Clock;
wire[3:
0]Q;
initial
Clock=0;
parameterclock_period=20;
always#(clock_period/2)Clock=~Clock;
initial
begin
Data=0;
repeat(20)
#20Data=$random;
end
initial
begin
Aclr=0;
repeat(20)
#20Aclr=$random;
end
initial
begin
Aset=0;
#200Aset=1;
end
reg4_2test_reg(Data,Aclr,Aset,Clock,Q);
initial
#300$finish;
endmodule
程序说明:
由于加入了多个控制信号,故测试平台中对控制信号的状态进行合理搭配也是很重要的,否则可能会出现某些控制信号组合情况未被测试的情况。
因此在测试平台编写过程中应不断的根据实际情况进行调整。
4.功能验证
7.3.3移位寄存器(并入并出单向左移)
1.使用Verilog进行描述
moduleshift_reg_pipo(Data,Enable,Shiften,Shiftin,Aclr,Clock,Q);
input[3:
0]Data;//4位并行输入数据
inputAclr;//异步清0端
inputEnable;//置数使能端
inputShiften;//移位使能控制
inputShiftin;//串行输入端
inputClock;//时钟信号,上升沿控制
output[3:
0]Q;//并行输出端
reg[3:
0]Qaux;//临时变量
always@(posedgeAclrorposedgeClock)
begin
if(Aclr)
Qaux=0;
elseif(Enable)
Qaux=Data;
elseif(Shiften)
Qaux={Qaux[2:
0],Shiftin};//通过连接运算符实现左移输入
end
assignQ=Qaux;
endmodule
程序说明:
(1)Aclr(异步清0端)的优先级最高,一旦Aclr变为低电平,则输出马上清0。
(2)Enable(并行输入使能控制端)的优先级比Shiften(移位使能控制端)高,当Aclr不为1时,时钟上升沿到来,只要Enable为1,输出Q得到并行输入Data的值。
(3)当Aclr和Enab