锁存器与触发器的FPGA实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
摘要 (1)
1.锁存器与触发器概述 (2)
1.1什么是锁存器、触发器 (2)
1.2锁存器与触发器的区别 (2)
2锁存器的电路结构及工作原理 (3)
2.1 SR锁存器 (3)
2.1.1基本SR锁存器 (3)
2.1.2逻辑门控SR锁存器 (4)
2.2 D锁存器 (5)
3触发器的电路结构及工作原理 (7)
3.1 触发器的分类 (7)
3.1.1主从触发器 (7)
3.1.2维持阻塞触发器 (8)
3.2 触发器的逻辑功能 (9)
3.2.1逻辑功能转换 (9)
3.2.2D触发器功能的转换 (9)
4锁存器与触发器的FPGA实现 (11)
4.1 锁存器的FPGA实现 (11)
4.1.1基本SR锁存器 (11)
4.1.2D锁存器 (17)
4.2 触发器的FPGA实现 (22)
4.2.1D触发器 (22)
4.2.2JK触发器 (28)
4.2.3JK触发器转换的D触发器 (32)
5总结 (38)
摘要
大多数数字系统,除了需要具有逻辑运算和算术运算功能的组合逻辑电路输出信号外,还需要具有存储功能的电路保存这些数字二进制数码信息,这就要用到存储电路,它是构成时序逻辑电路的基本单元。
组合电路与存储电路结合可构成时序逻辑电路,简称时序电路。
本报告将介绍实现存储功能的两种逻辑单元电路,即锁存器和触发器。
着重介绍它们的电路结构、工作原理以及所实现的不同逻辑功能;同时还将讨论用V erilog HDL描述锁存器与触发器的方法。
1锁存器与触发器概述
1.1什么是锁存器、触发器
锁存器和触发器是构成各种时序电路的存储单元电路,其共同特点是都具有0和1两种稳定状态,一旦稳定状态被确定,就能自行保持,即长期存储1位二进制码,直到有外部信号作用时才有可能改变。
锁存器是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。
触发器是一种对脉冲边缘敏感的存储电路,它们只能在作为触发信号的时钟脉冲上升沿或下降沿的变化瞬间才能改变状态。
1.2锁存器与触发器的区别
用一句话简单概括就是:锁存器是用电平使能来锁存数据的,而触发器是在时钟边沿进行数据的锁存的。
目前我们学习的由康华光主编的《数字电子技术基础(数字部分)》第五版将锁存器与触发器分开单独讲解,并强调了二者的区别。
事实上,就康华光教授以前编写的第一至第四版数电书上,都未对这两个概念分开讲解,而是统一定义为触发器。
值得强调的一点,在V erilog中,对脉冲电平敏感的锁存器和对脉冲边沿敏感的触发器的描述语句是不同的。
我个人猜测,正是目前FPGA的快速发展以及越来越多的人开始学习并使用V erilog语言,才让康华光教授在书中强调锁存器与触发器的区别。
当然,以上仅仅是我个人的猜测,未得到专业人士的认可,仅供参考!
2锁存器的电路结构及工作原理
2.1 SR锁存器
2.1.1基本SR锁存器
(1)电路结构
基本SR 锁存器是一种具有简单功能的双稳态存储器,其逻辑图和逻辑符号如图1所示。
图1:用与非门构成基本SR锁存器
(2)工作原理
按照上述逻辑图,可以列出输出端Q和的逻辑表达式
Q=~(~S·~Q)
~Q=~(~R·Q)
由此得出基本SR锁存器的功能表,如表1所示。
表1:用与非门构成基本SR锁存器的功能表
由逻辑表达式和功能表可以看出,基本SR锁存器的一些特点:
①触发器的次态不仅与输入信号状态有关,而且与触发器的现态有关。
②电路具有两个稳定状态(0和1),在无外来触发信号作用时,电路将保
持原状态不变。
③输入信号~S和~R以逻辑0作为有效作用信号。
当~S为0时,Q=1,触发器置1;当~R为0时,Q=0,触发器清0。
所以~S又称置位端,~R又称清零端。
④当~S=~R=1时,输入信号对输出Q和~Q不起作用,电路状态保持不变,此时电路可存储1位二进制数据。
⑤当输入为~S=~R=0时,锁存器处于不确定状态。
因此,此锁存器工作时应受到SR=0的条件约束。
当然,还可以用或非门的输入、输出端交叉耦合连接构成SR触发器,在此就不再重复,有兴趣可以翻阅康华光主编的《数字电子技术基础(数字部分)》第五版中第五章第二节的相关内容。
2.1.2逻辑门控SR锁存器
前面讨论的基本SR锁存器的输出状态是由输入信号S或R直接控制的,而在实际应用中,常需要用一个控制信号来控制同一电路中各个触发器的翻转时刻,这就要求再增加一个控制端。
因此,我们在基本SR锁存器前增加了一对逻辑门(与非门),用时钟脉冲信号CP控制锁存器在某一时刻根据S、R输入信号确定输出状态。
这种锁存器称为逻辑门控SR锁存器。
与基本SR锁存器相比,逻辑门控SR锁存器增加了所存使能输入端CP。
通过控制CP端电平,可以实现多个锁存器同步进行数据锁存。
(1)电路结构
图2:用与非门构成逻辑门控SR锁存器
用与非门构成的逻辑门控SR锁存器如图2所示。
(2)工作原理
逻辑门控SR锁存器由R、S和CP控制。
它比基本SR锁存器多了一个CP控制端。
由逻辑图可知,当CP=1时,此逻辑门控SR锁存器可等价为基本SR锁存器,其工作原理与上面讲解的相同,在此不再累赘;当CP=0时,等价于基本SR 锁存器输入~S=~R=1,由上面解释可知,此时输入信号对输出Q和~Q不起作用,电路状态保持不变。
综上所述,对逻辑门控SR锁存器而言,R、S控制状态转换的方向,即转换为何种次态;CP控制状态转换的时刻,即何时发生转换。
2.2 D锁存器
消除逻辑门控SR锁存器不确定状态最简单的方法,就是将逻辑门控SR锁存器接成D 锁存器的形式,其逻辑电路图如下。
图3:D锁存器
它只有两个输入端:数据输入端D和使能输入端CP。
当CP=0时,G3、G4输出均为1,使G1、G2构成的基本SR锁存器处于保持状态,即无论D信号怎
样变化,输出Q和~Q均保持不变。
当需要更新状态时,可将控制信号CP置1,此时,根据送到D端新的二值信息将锁存器置为新的状态:如果D=0,则Q=0,~Q=1,及锁存器清0;如果D=1,则Q=1,~Q=0,及锁存器置。
D锁存器的功能表由下表所示。
表2:D锁存器的功能表
3触发器的电路结构及工作原理
3.1 触发器的分类
目前应用的触发器主要有两种电路结构:主从触发器、维持阻塞触发器。
3.1.1主从触发器
主从触发器由两级触发器构成,其中一级直接接收输入信号,称为主触发器,另一级接收主触发器的输出信号,称为从触发器。
主锁存器的锁存使能信号正好与从锁存器相反,利用两个锁存器的交互锁存,则可以实现存储数据和输入信号之间的间隔。
(1)电路结构
如图4 所示为主从JK触发器的逻辑电路图。
图4:主从JK触发器
(2)工作原理
触发器的状态转换分两步完成:CP=1 期间接受输入信号,而状态的翻转只在CP 下降沿发生。
由图4所示的逻辑电路图分析可得:
J=0,K=0时,触发器保持原态不变;
J=0,K=1时,触发器置0;
J=1,K=0时,触发器置1;
J=1,K=1时,触发器翻转。
3.1.2维持阻塞触发器
(1)电路结构
图4.10 D触发器的逻辑图
(2)工作原理
当CP=0时,由分析易得G3、G4被封锁,对于G1、G2组成的SR锁存器相当于~R=~S=1,信号保持,同时D信号通过反馈进入触发器。
当CP由0变为1,G3、G4被打开,此时D信号被输入,由于~R和~S输入端一定是一个输入D,一个输入~D,由基本SR锁存器的逻辑功能知,这时Q=D。
当CP=1时,G3、G5和G4、G6分别构成两个基本SR锁存器,保证Q3、Q4的状态不变,是触发器状态不受输入信号D变化的影响。
综上所述,该触发器是在CP上升沿前接受输入信号,上升沿时触发翻转,上升沿后输入即被封锁,即该触发器接受输入数据和改变输出状态均发生在CP 的上升沿,因此称其为边沿触发方式。
由于其完成的是D型触发器的逻辑功能,因而称边沿触发的D触发器。
3.2 触发器的逻辑功能
脉冲触发沿到来之前的状态称为现态,而在此之后的状态称为次态。
所谓触发器的逻辑功能,是指次态与现态、输入信号之间的逻辑关系。
按照触发器状态转换规则不同,通常分为D触发器、JK触发器、T(T’)触发器、SR触发器等多种逻辑功能类型。
在此就不详细讲解各种触发器的特性,有兴趣可以翻阅康华光主编的《数字电子技术基础(数字部分)》第五版中第五章第四节的相关内容。
虽然触发器按功能分有多种类型,但最常见的集成触发器是JK触发器和D 触发器。
在基于FPGA的数字电路中我们所采用的触发器一般都是D触发器和JK 触发器,在需要使用其他触发器时,一般选择由它们转化而成。
同时,JK触发器与D触发器之间的功能也是可以互相转换的。
而前面已经讲解了D触发器和JK触发器的相关内容,所以在此主要介绍D触发器功能的转换。
3.2.1逻辑功能转换
逻辑功能的转换是将一种类型的触发器,通过外接一定的逻辑电路后转换成另一类型的触发器。
一般转换步骤为:
①写出已有触发器和待求触发器的特性方程。
②变换待求触发器的特性方程,使之形式与已有触发器的特性方程一致。
③比较已有触发器和待求触发器的特性方程,根据两个方程相等的原则求出转换逻辑。
④根据转换逻辑画出逻辑电路图。
3.2.2D触发器功能的转换
实际在FPGA的设计中D触发器是最多的,需要其他触发器可以用D触发器转换。
(1)从D型到JK型的转换 (例:由特性方程知D=J·~Q+~K·Q)
(2)从D型到T型的转换
(3)从D型到T′型的转换
图4.22 D触发器转换成其他功能的触发器
4锁存器与触发器的FPGA实现
4.1 锁存器的FPGA实现
4.1.1基本SR锁存器
以基本SR锁存器为例,介绍FPGA实现的实验流程。
1). 创建工程及设计输入
1.在D:\01.ISE9.1\目录下,新建名为srsuocun的新工程;
器件族类型(Device Family)选择“Virtex2P”,
器件型号(Device)选“XC2VP30 ff896 -7”,
综合工具(Synthesis Tool)选“XST (VHDL/V erilog)”,
仿真器(Simulator)选“ISE Simulator”
2、设计输入,在源代码窗口中单击右键,在弹出的菜单中选择New Source,在弹出的对话框中选择V erilog Moudle ,在右端的File name 中输入源文件名srsuocun,下面各步点next,然后在弹出的源代码编辑框内输源代码并保存即可。
SR锁存器V erilog HDL代码如下
module srsuocun(Q1,Q2,R,S); //端口声明
input R,S;
output Q1,Q2;
reg Q1,Q2; //寄存器型变量的关键字是reg。
由于输出Q1,Q2是在过程语句中被赋值,而在“always”块内被赋值的每一个信号都必须定义成reg
型,所以此处声明Q1,Q2为reg型的变量。
always@(R or S) //此处括号内的“事件控制表达式”使用了电平敏感事件,说
明如果输入信号R或S发生变化,就会执行一次后面的if
语句。
这里就体现了前面强调过的,在V erilog语言中,锁存
器与触发器的描述语句不同。
触发器的具体描述在后面会讲
到。
begin
if(R==1&&S==0)
Q1=0;
Q2=1;
end
if(R==0&&S==1)
begin
Q1=1;
Q2=0;
end
end
endmodule
2). 功能仿真
1.在sources窗口sources for中选择Behavioral Simulation。
2. 由Test Bench WaveForm添加激励源,如下图所示:
波形分析:
开始在0到200ns内的是R,S均为零为不确定状态,其为RS锁存器的不允许状态。
有波形可以观察到Q1,Q2是两个互为相反变量。
当R为1,S为0时,输出Q1为0,Q2为1,其实现置0功能。
当R为0,S为1时输出的Q1为1,验证了电路的置1功能。
当R,S均为1的时候电路输出保持原状态不变。
电路功能得以验证和设计的一样,设计成功。
3).生成核并添加核
1. 首先对生成的工程进行综合;
在ISE窗口中,点击project/new source,出现下图所示对话框,选择IP,在File name里填入icon,其他选项选择默认,点击next。
对于新出现的如上所示的对话框,选择ICON,点击next,再点击finish。
再出现如下所示的对话框中,由于本实验还会添加一个ILA核和一个VIO核,所以Number of Control Ports选择2。
点击Finish,则完成了对ICON核的添加。
对于ILA核和VIO核的添加于此类似,此处不再重复。
然后分别把例化icon,ila和vio核的代码添加到源程序中,并对源代码做相应的修改。
最后的代码如下:
module rs(Q1,Q2,clk);
input clk;
wire R,S;
output Q1,Q2;
reg Q1,Q2;
wire [35:0] control0;
wire [35:0] control1;
wire [0:0] trig0;
wire [1:0] async_in;
wire [1:0] async_out;
assign trig0=Q1;
assign R = async_out[0];
assign S = async_out[1];
assign async_in[0] = Q1; assign async_in[1] = Q2; always@ (R or S)
begin
if(R==1&&S==0)
begin
Q1=0;
Q2=1;
end
if(R==0&&S==1)
begin
Q1=1;
Q2=0;
end
end
icon m_icon
(
.CONTROL0(control0), .CONTROL1(control1) );
ila m_ila
(
.CONTROL(control0), .CLK(clk),
.TRIG0(trig0)
);
vio m_vio
(
.CONTROL(control1), .ASYNC_IN(async_in), .ASYNC_OUT(async_out) );
endmodule
module ICON
(
control0,
control1
);
output [35:0] control0; output [35:0] control1; endmodule
module ILA
(
control,
clk,
trig0
);
input [35:0] control;
input clk;
input [0:0] trig0; endmodule
module VIO
(
control,
async_in,
async_out
);
input [35:0] control;
input [1:0] async_in;
output [1:0] async_out;
endmodule
4).在线调试
1. 设计实现。
在工程的资源操作窗(Processes),双击 Implement Design。
2. 在实现步骤成功后,点击Generate Programming Files ,生成bit流文件。
3.运行chipscope,然后加载bit文件并观察结果。
观察符合设计,调试成功。
4.1.2D锁存器
通过SR锁存器的介绍,相信已经对实验流程有所了解,此后就不再重复,只强调代码的设计与实现。
1)功能仿真
D锁存器V erilog HDL代码如下
module dsuocun(Q1,Q2,cp,D);
input cp,D;
output Q1,Q2;
reg Q1,Q2;
always@(cp or D)
begin
if(cp) //只有控制信号有效时(cp=1),输入D的变化才能传送给输出Q begin
Q1<=D; //“<=”非阻塞型赋值语句。
它的执行过程是:首先计算语句块内部所有右边表达式的值,然后完成对左边寄存器变量的赋值
操作,这些操作是并行执行的。
Q2<=~D;
end
end
endmodule
功能仿真图如下:
2)板上调试
源代码如下
module dsuocun(Q1,Q2,cp);
input cp;
wire D;
output Q1,Q2;
reg Q1,Q2;
wire [35:0] control0;
wire [35:0] control1;
wire clk;
wire [0:0] trig0;
wire [1:0] trig1;
wire [1:0] async_in;
wire [0:0] async_out;
assign trig0=D;
assign trig1[0]=Q1;
assign trig1[1]=Q2;
assign D = async_out[0]; assign async_in[0] = Q1; assign async_in[1] = Q2; always@(cp or D)
begin
if(cp)
begin
Q1<=D;
Q2<=~D;
end
end
icon n_icon
(
.CONTROL0(control0), .CONTROL1(control1) );
ila n_ila
(
.CONTROL(control0), .CLK(cp),
.TRIG0(trig0)
);
vio n_vio
(
.CONTROL(control1), .ASYNC_IN(async_in), .ASYNC_OUT(async_out) );
endmodule
module ICON
(
control0,
control1
);
output [35:0] control0; output [35:0] control1; endmodule
module ILA
(
control,
clk,
trig0,
trig1
);
input [35:0] control; input clk;
input [0:0] trig0;
input [1:0] trig1; endmodule
module VIO
(
control,
async_in,
async_out
);
input [35:0] control; input [1:0] async_in; output [0:0] async_out; endmodule
观察结果如下:
观察符合设计,调试成功。
4.2 触发器的FPGA实现
4.2.1D触发器
1)基本D触发器
1.功能仿真
V erilog HDL代码如下
module DFF(Q,D,CP);
output Q;
input D,CP;
reg Q;
always @ (posedge CP) //在“时间控制表达式”中使用了边沿触发事件(posedge
CP),使其后的语句(Q1<=D;Q2<=~D;)仅在CP上升
沿期间将D的值赋给Q,而在其他任何时间,无论D
信号如何变化,都不能改变Q的状态。
这就是V erilog
语言中锁存器与触发器描述语句的区别。
Q<=D;
endmodule
功能仿真图如下:
2.板上调试
源代码如下
module DFF( Q,CP);
output Q;
input CP;
wire D;
reg Q;
wire [35:0] control0;
wire [35:0] control1;
wire [0:0] trig0;
wire [1:0] async_in;
wire async_out;
icon m_icon
(
.CONTROL0(control0), .CONTROL1(control1) );
ila m_ila
(
.CONTROL(control0), .CLK(CP),
.TRIG0(trig0)
);
vio m_vio
(
.CONTROL(control1), .ASYNC_IN(async_in), .ASYNC_OUT(async_out) );
assign trig0=Q;
assign D = async_out;
assign async_in[0] = Q;
assign async_in[1] = D;
always@(posedge CP)
Q<=D;
Endmodule
2)具有异步直接置1、置0功能的D触发器
1.功能仿真
V erilog HDL代码如下
module DFF(Q,QN,D,CP,Sd,Rd);
output Q,QN;
input D,CP,Sd,Rd;
reg Q,QN;
always @ (posedge CP or negedge Sd or negedge Rd) // “negedge Sd “和“negedge Rd”是两个异步触发事件。
这个模块中的触发事件表示,在输入信号CP的上升沿到来时,或Sd或Rd跳变为低电平时,后面的if-else语句就会被执行一次。
if(~Sd) begin //~Sd为置1端,则~Sd=1时,Q=1
Q<=1'b1; //1'b1表示位宽为1的二进制表示1
QN<=1'b0; //1'b0表示位宽为1的二进制表示0
end
else if(~Rd) //~Rd为清0端,则~Rd=1时,Q=0
begin
Q<=1'b0;
QN<=1'b1;
end
else begin //~Sd=~Rd=0且在CP上升沿到来时,输入D传送到输出Q Q<=D;
QN<=~D;
end
endmodule
功能仿真图如下:
2.板上调试
源代码如下
module async_set_rst_DFF(Q,QN,CP); output Q,QN;
wire D,Sd,Rd;
input CP;
reg Q,QN;
wire [35:0] control0;
wire [35:0] control1;
wire [4:0]async_in;
wire [2:0]async_out;
icon i_icon(
.CONTROL0(control0),
.CONTROL1(control1)
);
ila i_ila(
.CONTROL(control0),
.CLK(CP),
.TRIG0(trig0)
);
vio i_vio(
.CONTROL(control1),
.ASYNC_IN(async_in),
.ASYNC_OUT(async_out)
);
assign D=async_out[0];
assign Sd=async_out[1];
assign Rd=async_out[2];
assign async_in[0]=D;
assign async_in[1]=Sd;
assign async_in[2]=Rd;
assign async_in[3]=Q;
assign async_in[4]=QN;
always@(posedge CP or negedge Sd or negedge Rd) //if ((~Sd||~Rd))
if (~Sd)
begin
Q<=1'b1;
QN<=1'b0;
end
else if(~Rd)
begin
Q<=1'b0;
QN<=1'b1;
end
else begin
Q<=D;
QN<=~D;
end
endmodule
3)具有同步置0功能的D触发器
1.功能仿真
V erilog HDL代码如下
module sync_rst_DFF(Q,D,CP,Rd);
output Q;
input D,CP,Rd;
reg Q;
always @ (posedge CP) //“时间控制表达式”中只有一个时钟事件,它表示只
有在CP上升沿到来时,后面的if-else语句才会被执
行
if(~Rd)Q<=1'b0; //检查Rd信号,如果置0端为逻辑0(Rd=0),则将输出Q
置0;否则,将输入D传输给Q
else Q<=D;
endmodule
功能仿真图如下:
2.板上调试
源代码如下
module DFF(Q,CP);
output Q;
wire D,Rd;
input CP;
reg Q;
wire [35:0] control0;
wire [35:0] control1;
wire [3:0]async_in;
wire [0:0]async_out;
icon i_icon(
.CONTROL0(control0)
);
vio i_vio(
.CONTROL(control1),
.ASYNC_IN(async_in),
.ASYNC_OUT(async_out)
);
assign D=async_out[0];
assign Rd=async_out[1];
assign async_in[0]=D;
assign async_in[1]=Rd;
assign async_in[2]=Q;
always @ (posedge CP)
if(~Rd)Q<=1'b0;
else Q<=D;
endmodule
4.2.2JK触发器
1.功能仿真
V erilog代码如下:
module jktrigger(Q,QB,J,K,clk); input J,K,clk;
output Q,QB;
reg Q;
assign QB=~Q;
always@(negedge clk)
begin
case({J,K}) //这里将输入变量J、K拼接起来成为一个2位二进制变量({J,K}),它的值可能是二进制数00、01、10、11,case语句后面
的4条分语句正好说明了在时钟信号CP下降沿作用后,触发器
的次态。
2'b00 : Q <= Q;
2'b01 : Q <= 1'b0;
2'b10 : Q <= 1'b1;
2'b11 : Q <= ~Q;
default: Q<= 1'bx;
endcase
end
endmodule
功能仿真图如下:
2.板上调试
源代码如下
module jktrigger(Q,QB,clk);
input clk;
output Q,QB;
reg Q;
wire K;
wire [35:0]control0;
wire [3:0]async_in;
wire [1:0]async_out;
icon i_icon
(
.CONTROL0(control0)
);
vio i_vio
(
. CONTROL (control0),
.ASYNC_IN(async_in),
. ASYNC _OUT(async_out)
);
assign async_in[0]=J;
assign async_in[1]=K;
assign async_in[2]=Q;
assign async_in[3]=QB;
assign J=async_out[0];
assign K=async_out[1];
assign QB=~Q;
always@(negedge clk)
begin
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;
end
endmodule
module ICON
(
control0
);
output [35:0] control0; endmodule
module VIO
(
control,
async_in,
async_out
);
input [35:0] control; input [3:0] async_in; output [1:0] async_out; endmodule
观察结果如下:
J=1,K=0时,将Q置1。
J=0,K=0时,Q保持不变。
J=0,K=1时,将Q置0
J=1,K=1时可以看到Q和QB不断地翻转。
4.2.3JK触发器转换的D触发器1.功能仿真
V erilog代码如下:
module jkdtrigger(cp,D,Qn,Qnb);
input cp, D;
output Qn,Qnb;
wire J,K;
jktrigger a2(Qn,Qnb,J,K,cp);
not a1(K,D); //经过一个非门,将~D赋值给K
assign J=D;
endmodule
module jktrigger(Q,QB,J,K,clk); //以下与JK触发器的程序定义一样input J,K,clk;
output Q,QB;
reg Q;
assign QB=~Q;
always@(negedge clk)
begin
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; //如果出现上面case语句以外的情况,则Q为不定值endcase
end
endmodule
功能仿真图如下:
2.板上调试
源代码如下
module jktrigger(Q,QB,J,K,clk); input J,K,clk;
output Q,QB;
reg Q;
assign QB=~Q;
always@(negedge clk)
begin
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
end
endmodule
module jkdtrigger(cp,Qn,Qnb);
input cp;
output Qn,Qnb;
wire D;
wire J,K;
wire [35:0]control0;
wire [4:0]async_in;
wire async_out;
assign async_in[0]=D;
assign async_in[1]=J;
assign async_in[2]=K;
assign async_in[3]=Qn;
assign async_in[4]=Qnb;
assign D=async_out;
icon i_icon
(
.CONTROL0(control0)
);
vio i_vio
(
. CONTROL (control0),
.ASYNC_IN(async_in),
. ASYNC _OUT(async_out)
);
jktrigger a2(Qn,Qnb,J,K,cp);
not a1(K,D);
assign J=D;
endmodule
module jktrigger(Q,QB,J,K,clk); input J,K,clk;
output Q,QB;
reg Q;
assign QB=~Q;
always@(negedge clk)
begin
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
end
endmodule
module icon
(
control0
);
output [35:0] control0;
endmodule
module vio
(
control,
async_in,
async_out
);
input [35:0] control;
input [4:0] async_in;
output [0:0] async_out;
endmodule
观察结果如下:
从图中可以看出此触发器的设计是正确的。
5总结
这段时间内主要针对FPGA的数字电路功能与实现这一块进行了学习,让我对实验流程有了一个大致的了解。
数字电路部分是我们已经学习过的知识,但经过本次实验后,才让我认识到当初学习不是很扎实。
就像锁存器和触发器这一章,当初在学习的时候,基本就只是背了几个公式,对于不同的锁存器和触发器的内部结构并不清楚,更不清楚它们有什么联系。
这次重新把这一部分的知识学习了一下,才终于明白为什么课本上会按照这个顺序介绍相关知识,明白他们内部的联系性。
例如,为了实现多个锁存器同步进行数据锁存,才将基本SR锁存器改进为逻辑门控SR锁存器;为了消除逻辑门控SR锁存器的不确定状态,才将其进行改进形成了D锁存器。
明白这些不同逻辑器件的内在联系,对于它们的理解和区别才有了更加深刻的认识,也就避免了完全把理科公式当做文科的知识来进行背诵,也会使记忆更加牢固。
对于这个报告,是我第一份比较系统的报告,还有很多不完善的部分。
比如在锁存器和触发器的FPGA实现部分,应该要分析自己编写代码的思路,然后分块写出,最后综合成一份完整的代码。
但是由于我目前的Verilog HDL的能力还只能停留在读懂别人已经写好的程序,然后根据别人原有的程序,自己进行部分改变的层次,无法自己编写程序,所以我没有按规范的格式进行编写,只是将已有的程序加上注释,以表明自己对这个程序的理解。
这也说明,在未来的一段时间内,对于语言的学习,将是我的一个新的学习方向。