目录
数字逻辑实验报告(2)
一、Verilog HDL设计数字逻辑电路
1、实验名称
Verilog HDL设计数字逻辑电路。
2、实验目的
要求同学用Verilog HDL设计数字逻辑电路,通过3个逻辑电路实验,并利用“Vivado 2015.2”软件进行“前、后”仿真检查电路设计,然后在“Xilinx NEXYS 4开发板”上操作、记录实验结果,最后验证设计是否达到要求。
通过以上设计、仿真、验证3个训练过程使同学们掌握Verilog HDL设计数字逻辑电路的基本方法,同时掌握如何避免锁存器的产生以及电路设计中的一致性问题的处理方法。
3、实验所用设备
Xilinx NEXYS 4开发板(芯片为XC7A100TCSG324-1,封装为CSG324,软件为Vivado 2015.2)1套。
4、实验内容
(1)组合、时序逻辑电路的“always”设计
(A)用“always块”设计纯组合逻辑电路
组合电路的一个特性是它的输出永远受输入变化的影响。也就是说组合电路绝不会保持它们以前的值,即输出不会出现锁存。
在使用always块中的case,if-else等语句设计纯组合逻辑电路时,要保证所有输入条件,其输出均有输出值,否则有可能会产生锁存器,导致“综合”出错。
例如:某题目要求使用Verilog设计实现一个纯组合逻辑电路的选择器,某同学设计了一个带“flag”标识的4选1的多路选择器,参见程序1-1所示,但是在“综合”时,报3个错误,即:“Place 30-574、Place 30-99、Common 17-69”。
具体要求:
(a)验证程序1-1在“综合”时,是否会出现上述问题;
(b)如果存在上述问题,请更正程序1-1,帮这位同学完成设计。
程序1-1 带“flag”标识的4选1的多路选择器
module mux_latch(
input [3:0] data,
input [1:0] valid,
input flag,
output reg valid_data);
initial begin
valid_data=1'b0;
end
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];end
2'b01 : begin if(flag) valid_data = data[1];end
2'b10 : begin if(flag) valid_data = data[2];end
2'b11 : begin if(flag) valid_data = data[3];end
endcase
end
endmodule
///*.xdc文件//
set_property PACKAGE_PIN T16 [get_ports flag]
set_property IOSTANDARD LVCMOS33 [get_ports flag]
set_property PACKAGE_PIN U8 [get_ports {valid[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {valid[0]}]
set_property PACKAGE_PIN R7 [get_ports {valid[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {valid[1]}]
set_property PACKAGE_PIN V7 [get_ports {data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[0]}]
set_property PACKAGE_PIN V6 [get_ports {data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[1]}]
set_property PACKAGE_PIN V5 [get_ports {data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[2]}]
set_property PACKAGE_PIN U4 [get_ports {data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[3]}]
set_property PACKAGE_PIN T8 [get_ports valid_data]
set_property IOSTANDARD LVCMOS33 [get_ports valid_data]
(B)用“always块”设计一个同步时序逻辑电路
参见图1-1所示电路。
图1-1同步时序逻辑电路
具体要求:
利用Verilog HDL的“always块”设计该电路并进行仿真。
(注意:阻塞与非阻塞赋值的不同,这种组合和时序的混合电路建议使用非阻塞赋值)
(2)脉冲异步计数器的设计
分析如图1-2所示的脉冲异步计数器电路,完成如下内容:
图1-2 脉冲异步计数器电路
(A)说明该计数器的模是多少?
(B)用Verilog DHL实现该电路,并通过仿真和在开发板上验证设计。
(3)Verilog数字电路设计中一致性问题
分析如图1-3所示的电路,完成如下内容:
(A)程序1-2是对图1-3所示电路的描述,请用“Behavior Simulation-它可以称为前仿真”和“非Behavior Simulation-它可以称为后仿真”对程序1-2分别进行仿真,如果有错误,请更正程序1-2,并给出修正后的仿真结果。
(这就是:所谓前仿真和后仿真是否一致的问题)
q1 |
q2 |
图1-3 3位移位寄存器电路
(B)NEXYS 4开发板提供了一个100Mhz的同步时钟,引脚绑定为“E3”,在更正后的程序1-2中添加一个时钟分频部分,并将降频后的时钟信号接到图1-3中的“clk”,编译成功后再下载到开发板上测试它。
结论:在今后的设计中要保持:“前仿真和后仿真以及下载验证都正确”哟。
程序1-2 3位移位寄存器电路
module pipe3b(
input sig_nsyn,
input clk,
output q1,
output q2,
output sig_syn
);
reg q1;
reg q2;
reg sig_syn;
always@(posedge clk) q2=q1;
always@(posedge clk) sig_syn=q2;
always@(posedge clk) q1=sig_nsyn;
endmodule
5、实验方案设计
(1)组合、时序逻辑电路的“always”设计方案
(A)用“always块”设计纯组合逻辑电路
(a)验证程序1-1在“综合”时,是否会出现上述问题;
`timescale 1ns / 1ps
//
// Module Name: lab1
//
module mux_latch1(
input [3:0] data,
input [1:0] valid,
input flag,
output reg valid_data);
initial begin
valid_data=1'b0;
end
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];else valid_data = 1'bx; end
2'b01 : begin if(flag) valid_data = data[1];else valid_data = 1'bx; end
2'b10 : begin if(flag) valid_data = data[2];else valid_data = 1'bx; end
2'b11 : begin if(flag) valid_data = data[3];else valid_data = 1'bx; end
default: valid_data = 1'bx;
endcase
end
endmodule
(B)用“always块”设计实现一个同步时序逻辑电路
(a)源程序
module lab1_2(
input CP,
input X,
output Y);
reg T1;
reg Y;
wire T0,CP0,CP1,Q0,Q1;
T_trigger t0(.Q(Q0),.CP(CP0),.T(T0));
T_trigger t1(.Q(Q1),.CP(CP1),.T(T1));
assign T=1'b1;
assign CP0=CP;
assign CP1=CP;
always @ (CP)
begin
T1<= Q0^X;
Y<= ~(X&(~Q1));
end
endmodule
module T_trigger(Q,CP,T);
output Q;
reg Q;
input CP,T;
initial begin
Q=1'b0;
end
always @(negedge CP) begin
if(T)Q<=~Q;
(b)仿真程序
module test_lab1_2;
// Inputs
reg CP;
reg X;
// Outputs
wire Y;
// Instantiate the Unit Under Test (UUT)
lab1_2 uut ( .CP(CP),.X(X), .Y(Y));
// Initialize Inputs
initial begin
X=1'b0;
CP=1'b0;
#20;
end
always begin
#25 CP=~CP;
end
always begin
#200 X<=1;
#200 X<=0;
end
endmodule
(2)脉冲异步计数器的分析和设计方案
(A)源程序
module lab1_3(
input X,
output Z,
output Q1,Q2,Q3,Q4
);
wire J1,J2,J3,J4,K1,K2,K3,K4,CP1,CP2,CP3,CP4;
JK_trigger jk1(J1,K1,CP1,Q1);
JK_trigger jk2(J2,K2,CP2,Q2);
JK_trigger jk3(J3,K3,CP3,Q3);
JK_trigger jk4(J4,K4,CP4,Q4);
assign J1=1;
assign J2=~Q4;
assign J3=1;
assign J4=Q2&Q3;
assign K1=1;
assign K2=1;
assign K3=1;
assign K4=1;
assign CP1=X;
assign CP2=Q1;
assign CP3=Q2;
assign CP4=Q1;
assign Z=Q4&Q1&X;
endmodule
module JK_trigger(J,K,CP,Q);
input J,K,CP;
output Q;
reg Q;
initial begin
Q=0;
end
always @(negedge CP)
begin
case({J,K})
2'b00:Q<=Q;
2'b01:Q<=0;
2'b10:Q<=1;
2'b11:Q<=~Q;
endcase
end
endmodul
(B)仿真程序
module test_lab1_3();
reg X;
wire Z;
wire Q1,Q2,Q3,Q4;
lab1_3 test(.X(X),.Z(Z),.Q1(Q1),.Q2(Q2),.Q3(Q3),.Q4(Q4));
initial begin
X=0;
#20;
end
always #20 X=~X;
endmodule
(C)引脚约束(绑定)程序
set_property PACKAGE_PIN P17 [get_ports X]
set_property IOSTANDARD LVCMOS33 [get_ports X]
set_property PACKAGE_PIN R18 [get_ports {Z}]
set_property IOSTANDARD LVCMOS33 [get_ports {Z}]
set_property PACKAGE_PIN H17 [get_ports {Q1}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1}]
set_property PACKAGE_PIN K15 [get_ports {Q2}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q2}]
set_property PACKAGE_PIN J13 [get_ports {Q3}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q3}]
set_property PACKAGE_PIN N14 [get_ports {Q4}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q4}]
(3)Verilog设计中一致性问题的解决方案
(A)源程序
①更改后源程序:
module lab1_5(
input sig_nsyn,
input clk,
output q1,
output q2,
output sig_syn
);
reg q1;
reg q2;
reg sig_syn;
always@(posedge clk) begin
sig_syn<=q2;
q2<=q1;
q1<=sig_nsyn;
end
endmodule
(2)添加时钟分频后的源程序
module clk_device(clk,clk_N);
input clk; // 系统时钟 );
output reg clk_N; // 分频后的时钟endmodule
parameter N = 100_000_000; // 1kHz的时钟,N=fclk/fclk_N
reg [31:0] counter; //计数器变量,通过计数实现分频。
always @(posedge clk) begin
if(counter==((N/2-1)))counter=0;
else
counter= counter + 1;
end
always @(posedge clk) begin
if(counter==((N/2-1))) clk_N = !clk_N;
end
endmodule
module lab(clk,sig_nsyn,clk1,q1,q2,sig_syn);
input clk; // 系统时钟
input sig_nsyn;
output clk1; // 分频后的时钟
output q1,q2,sig_syn;
wire devide_clk;
clk_device #(100_000_000) divice(.clk(clk), .clk1(clk1));
lab1_5 lab(.sig_nsyn(sig_nsyn),.clk(clk1),.q1(q1),.q2(q2),.sig_syn(sig_syn));
endmodule
(B)仿真程序
module test_lab();
reg sig_nsyn;
reg clk;
wire clk1;
wire q1;
wire q2;
wire sig_syn;
lab test(.sig_nsyn(sig_nsyn),.clk(clk),.q1(q1),.q2(q2),.sig_syn(sig_syn),.clk1(clk1));
initial begin
sig_nsyn=1'b0;
clk=1'b0;
#10;
end
always begin
#25 clk=~clk;
end
always begin
#100 sig_nsyn<=1;
#100 sig_nsyn<=0;
end
endmodule
6、实验结果记录
(1)组合、时序逻辑电路的“always”设计
(A)用“always块”设计纯组合逻辑电路
(a)验证程序1-1在“综合”时,是否会出现上述问题;
综合时不会出现上述错误,而在run implementation时会出现。
(b)如果存在上述问题,请更正程序1-1,帮这位同学完成设计。
(B)用“always块”设计一个同步时序逻辑电路
参见图1-1所示电路。
图1-1同步时序逻辑电路
利用Verilog HDL的“always块”设计该电路并进行仿真。
仿真结果如下:
(2)脉冲异步计数器的设计
分析如图1-2所示的脉冲异步计数器电路,完成如下内容:
图1-2 脉冲异步计数器电路
- 说明该计数器的模是多少?
该计数器的模为十。计数序列(Q4Q3Q2Q1)为:
0000—>0001—>0010—>0011—>0100—>0101—>0110—>0111—>
1000—>1001—>0000。由1001—>0000时Z输出1。
(B)用Verilog DHL实现该电路,并通过仿真和在开发板上验证设计。
①仿真结果如下:
②开发板上验证通过。检查时缺少状态,现已添加。
(3)Verilog数字电路设计中一致性问题
分析如图1-3所示的电路,完成如下内容:
(A)程序1-2是对图1-3所示电路的描述,请用“Behavior Simulation-它可以称为前仿真”和“非Behavior Simulation-它可以称为后仿真”对程序1-2分别进行仿真,如果有错误,请更正程序1-2,并给出修正后的仿真结果。
(这就是:所谓前仿真和后仿真是否一致的问题)
q1 |
q2 |
图1-3 3位移位寄存器电路
- 更改前:由下图可知,原程序前后仿真不一致。
前仿真
后仿真
②更改后
前仿真:
后仿真
(B)NEXYS 4开发板提供了一个100Mhz的同步时钟,引脚绑定为“E3”,在更正后的程序1-2中添加一个时钟分频部分,并将降频后的时钟信号接到图1-3中的“clk”,编译成功后再下载到开发板上测试它。
- 仿真结果如下:
- 编译成功,下载失败:
原因:程序run implementation时出现placer错误,实验后经修改后可生成比特流文件,但无板子,无法验证。
二、Verilog HDL设计较复杂数字逻辑电路
1、实验名称
Verilog HDL设计较复杂数字逻辑电路。
2、实验目的
要求同学用Verilog HDL设计较复杂的数字逻辑电路,通过3个逻辑电路实验,并利用“Vivado 2015.2”软件进行“前、后”仿真检查电路设计,然后在“Xilinx NEXYS 4开发板”上操作、记录实验结果,最后验证设计是否达到要求。
通过以上设计、仿真、验证3个训练过程使同学们掌握Verilog HDL设计较复杂数字逻辑电路的基本方法,同时掌握“电路例化”、“模块化”的使用、异步时序逻辑电路的同步化处理以及用状态机设计控制电路。
3、实验所用组件
Xilinx NEXYS 4开发板(芯片为XC7A100TCSG324-1,封装为CSG324,软件为Vivado 2015.2)1套。
4、实验内容
(1)4位二进制加法/减法计数器的设计
设计一个能清零、置数和进位/借位输出的加1/减1的4位二进制计数器,其结构框图如图2-1所示。
图2-1 4位二进制加法/减法计数器
电路输入为计数脉冲CP、工作模式选择M、预制初值D,C,B,A(其中D为高位,A为低位)和预制控制 ,清零端 ;
输出为计数值QD,QC,QB,QA(QD为高位,QA为低位)和进位/借位输出 ;
当 为0时,电路输出清零;
预制控制 =0时,将D、C、B、A的输入值送到计数器中,并立即在QD,QC,QB,QA中输出;
模式选择端M=1时加1计数;
当M=0时减1计数;
当CP端输入一个上升沿信号时进行一次计数;
计数有进位/借位时 端输出一个负脉冲。
注意:用Verilog设计电路时,经常会遇到这样一些问题,例如:
(A)用两个always块对一个寄存器进行赋值,无论其中经过了怎样的条件判断,最终结果毫无疑问是将两个相独立的触发信号连在了寄存器的CLK端上,一个端口接入两信号,所以这样的语句是无法被综合成电路的。
(B)某电路如果有多个输入都可能引起输出值的改变,在使用“always”时,如果其触发条件为电路的“多个输入”时,如果语句的“并发性”处理不好,会造成系统编译成功、“行为仿真”也成功,但是系统生成不了“bit”文件。
解决方法:采用所谓“异步时序逻辑电路的同步化处理”,即:减少“always”的触发条件。
具体要求:
(A)用Verilog HDL实现该计数器,将之下载到开发板中进行验证;
(B)用已实现了的“4位二进制计数器”,采用“电路例化”或者“模块化”实现一个初值为2的模8计数器,并下载到开发板中进行验证;
(C)给出设计占用FPGA芯片的资源情况(希望越少越好)。
(2)采用有限状态机(FSM) 实现序列检测器
设计一个简单的状态机,其功能是检测一个串行的5位不可重叠的“10110”二进制序列检测器,当输入值出现“10110”时,给出输出标志。
具体要求如下:
(A)给出不可重叠的“10110”二进制序列的状态转移图;
(B)采用有限状态机“标准模板”来设计“10110”二进制序列检测器,在仿真正确后再下载到开发板中进行验证;
(C)给出设计占用FPGA芯片的资源情况(希望越少越好)。
(所谓有限状态机“标准模板”请参考教材:夏雨闻。Verilog数字系统设计教程第3版。北京:北京航空航天大学出版社,2013.)
(3)3位二进制数值比较器的设计
设计一个3位二进制数值比较器。当A>B时,F1=1,F2=F3=0;当A=B时, F2=1,F1=F3=0;当A<B时,F3=1,F1=F2=0。
具体要求:
(A)用Verilog HDL设计一个一位二进制数值比较器;
(B)用已实现了的一位二进制数值比较器,采用“电路例化”或者“模块化”实现一个3位二进制数值比较器;
(C)将所设计的电路下载到开发板上进行验证;
(D)给出设计占用FPGA芯片的资源情况(希望越少越好)。
5、实验方案设计
(1)4位二进制加法/减法计数器的设计方案
(A)模16加1/减1计数器
(a)源程序
module lab2(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
initial begin
Q1=4'b0000;
end
always @(posedge CP,posedge CLR,posedge LD) begin
if(CLR|LD)begin
if(CLR)Q1=0;
else if(LD)Q1=Q;
else
Q1=Q1;
end
else begin
if(M) begin
Q1<=Q1+1;
if(Q1==15)Qcc<=1;
else
Qcc=0;
end
else begin
Q1<=Q1-1;
if(!Q1)Qcc<=1;
else
Qcc<=0;
end
end
end
endmodule
(b)仿真程序
module test_lab2();
reg [3:0]Q;
reg CP,LD,M,CLR;
wire [3:0]Q1;
wire Qcc;
lab2 test(.Q1(Q1),.Q(Q),.CP(CP),.LD(LD),.CLR(CLR),.M(M),.Qcc(Qcc));
initial begin
Q=4'b1010;
CP=1'b0;
CLR=1'b0;
LD=1'b0;
M=1'b1;
#20;
end
always begin
#50 CP=~CP;
end
always begin
#1500 M=~M;
end;
always begin
#2475 CLR=1;
#25 CLR=0;
end
always begin
#1975 LD=1;
#25 LD=0;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports {Q[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[0]}]
set_property PACKAGE_PIN L16 [get_ports {Q[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[1]}]
set_property PACKAGE_PIN M13 [get_ports {Q[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[2]}]
set_property PACKAGE_PIN R15 [get_ports {Q[3}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[3]}]
set_property PACKAGE_PIN P17 [get_ports CP]
set_property IOSTANDARD LVCMOS33 [get_ports CP]
set_property PACKAGE_PIN T18 [get_ports CLR]
set_property IOSTANDARD LVCMOS33 [get_ports CLR]
set_property PACKAGE_PIN U18 [get_ports LD]
set_property IOSTANDARD LVCMOS33 [get_ports LD]
set_property PACKAGE_PIN R13 [get_ports M]
set_property IOSTANDARD LVCMOS33 [get_ports M]
set_property PACKAGE_PIN H17 [get_ports {Q1[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[0]}]
set_property PACKAGE_PIN K15 [get_ports {Q1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[1]}]
set_property PACKAGE_PIN J13 [get_ports {Q1[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[2]}]
set_property PACKAGE_PIN N14 [get_ports {Q1[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[3]}]
set_property PACKAGE_PIN V17 [get_ports {Qcc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qcc}]
(B)初值为2的模8计数器,要求:通过例化A【调用(A)实现的计数器】来实现。
(a)源程序
module counter1_4bit(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
initial begin
Q1=4'b0010;
end
always @(posedge CP,posedge CLR,posedge LD) begin
if(CLR|LD)begin
if(CLR)Q1<=4'b0010;
else if(LD)Q1<=Q;
else
Q1<=Q1;
end
else begin
if(M)begin
if(Q1>8||Q1<2)begin
Q1<=4'b0010;
Qcc<=1;
end
else begin
Q1<=Q1+1;
Qcc<=0;
end
end
else begin
if(Q1>9||Q1<3)begin
Q1<=4'b1001;
Qcc<=1;
end
else begin
Q1=Q1-1;
Qcc<=0;
end
end
end
end
endmodule
module model8_counter1(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
wire [3:0]Qt;
wire Qcc0;
counter1_4bit model_count(.Q(Q),.Q1(Qt),.CP(CP),.M(M),.LD(LD),.CLR(CLR),.Qcc(Qcc0));
always @(posedge CP)
begin
Q1=Qt;
Qcc=Qcc0;
end
endmodule
(b)仿真程序
module test_lab2_2();
reg [3:0]Q;
reg CP,M,LD,CLR;
wire [3:0]Q1;
wire Qcc;
model8_counter1 test(.Q(Q),.LD(LD),.CLR(CLR),.Q1(Q1),.CP(CP),.M(M),.Qcc(Qcc));
initial begin
Q=4'b0110;
CP=1'b0;
LD=1'b0;
CLR=1'b0;
M=1'b1;
#20;
end
always begin
#50 CP=~CP;
end
always begin
#1500 M=~M;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports A]
set_property IOSTANDARD LVCMOS33 [get_ports A]
set_property PACKAGE_PIN L16 [get_ports B]
set_property IOSTANDARD LVCMOS33 [get_ports B]
set_property PACKAGE_PIN M13 [get_ports C]
set_property IOSTANDARD LVCMOS33 [get_ports C]
set_property PACKAGE_PIN R15 [get_ports D]
set_property IOSTANDARD LVCMOS33 [get_ports D]
set_property PACKAGE_PIN P17 [get_ports CP]
set_property IOSTANDARD LVCMOS33 [get_ports CP]
set_property PACKAGE_PIN T18 [get_ports CLR]
set_property IOSTANDARD LVCMOS33 [get_ports CLR]
set_property PACKAGE_PIN U18 [get_ports LD]
set_property IOSTANDARD LVCMOS33 [get_ports LD]
set_property PACKAGE_PIN R13 [get_ports M]
set_property IOSTANDARD LVCMOS33 [get_ports M]
set_property PACKAGE_PIN H17 [get_ports {Qa}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qa}]
set_property PACKAGE_PIN K15 [get_ports {Qb}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qb}]
set_property PACKAGE_PIN J13 [get_ports {Qc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qc}]
set_property PACKAGE_PIN N14 [get_ports {Qd}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qd}]
set_property PACKAGE_PIN V17 [get_ports {Qcc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qcc}]
(2)采用有限状态机(FSM) 实现序列检测器的设计方案
(A)串行5位不可重叠的“10110”二进制序列检测器的状态图
(B)源程序
module lab2_3(in,clk,reset,flag,state);
input in,clk,reset;
output flag;
output reg [2:0]state;
wire flag;
parameter IDLE=3'd0,
A=3'd1,
B=3'd2,
C=3'd3,
D=3'd4,
E=3'd5,
F=3'd6,
G=3'd7;
assign flag=(state==D&&in==0)?1:0;
always @ (posedge clk or negedge reset)
if(!reset) begin
state<=IDLE;
end
else
casex(state)
IDLE:if(in==1)state<=A;
else
state<=IDLE;
A: if(in==0)state<=B;
else
state<=A;
B: if(in==1)state<=C;
else
state<=F;
C: if(in==1)state<=D;
else
state<=G;
D: if(in==0)state<=E;
else
state<=A;
E: if(in==1)state<=C;
else
state<=IDLE;
F: if(in==1)state<=A;
else
state<=IDLE;
G: if(in==1)state<=C;
else
state<=IDLE;
default: state<=IDLE;
endcase
endmodule
(C)仿真程序
module test_lab2_3();
reg clk,reset;
reg [23:0]data;
wire flag,in;
wire [2:0]state;
assign in=data[23];
initial
begin
clk=0;
reset=1;
#2 reset=0;
#30 reset=1;
data=20'b1011_0001_0110_1101_0110;
#(`halfperiod*1000)$stop;
end
always #(`halfperiod)clk=~clk;
always @(posedge clk)
#2 data={data[22:0],data[23]};
lab2_3 test(.in(in),.flag(flag),.clk(clk),.reset(reset),.state(state));
endmodule
(D)引脚约束(绑定)程序
set_property PACKAGE_PIN P17 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN J15 [get_ports in]
set_property IOSTANDARD LVCMOS33 [get_ports in]
set_property PACKAGE_PIN R17 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN H17 [get_ports flag]
set_property IOSTANDARD LVCMOS33 [get_ports flag]
set_property PACKAGE_PIN K15 [get_ports {state[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[0]}]
set_property PACKAGE_PIN J13 [get_ports {state[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[1]}]
set_property PACKAGE_PIN N14 [get_ports {state[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[2]}]
(3)3位二进制数值比较器的设计方案
(A)一位二进制数值比较器
(a)源程序
module lab2_4(
input A,B,
output F1,F2,F3
);
reg F1,F2,F3;
always @(A or B)begin
F1<=A&(~B);
F2<=~(A^B);
F3<=~A&B;
end
endmodule
(b)仿真程序
module test_lab2_4();
reg A,B;
wire F1,F2,F3;
initial begin
A=1'b0;
B=1'b0;
#10;
end
lab2_4 test(.A(A),.B(B),.F1(F1),.F2(F2),.F3(F3));
always begin
#50 A=~A;
#50 B=~B;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports A]
set_property IOSTAND LVCMOS33 [get_ports A]
set_property PACKAGE_PIN R17 [get_ports B]
set_property IOSTAND LVCMOS33 [get_ports B]
set_property PACKAGE_PIN H17 [get_ports F1]
set_property IOSTAND LVCMOS33 [get_ports F1]
set_property PACKAGE_PIN K15 [get_ports F2]
set_property IOSTAND LVCMOS33 [get_ports F2]
set_property PACKAGE_PIN J13 [get_ports F3]
set_property IOSTAND LVCMOS33 [get_ports F3]
(B)3位二进制数值比较器,要求:通过例化A【调用(A)实现的一位二进制数值比较器】来实现。
(a)源程序
module lab2_5(
input [2:0]A,B,
output reg F1,F2,F3
);
wire [2:0]A_F1_B,A_F2_B,A_F3_B;
lab2_4 lab(.A(A[2]),.B(B[2]),.F1(A_F1_B[2]),.F2(A_F2_B[2]),.F3(A_F3_B[2]));
lab2_4 lab1(.A(A[1]),.B(B[1]),.F1(A_F1_B[1]),.F2(A_F2_B[1]),.F3(A_F3_B[1]));
lab2_4 lab2(.A(A[0]),.B(B[0]),.F1(A_F1_B[0]),.F2(A_F2_B[0]),.F3(A_F3_B[0]));
always @ (A or B) begin
if(!A_F2_B[2])begin
F1=A_F1_B[2];
F2=A_F2_B[2];
F3=A_F3_B[2];
end
else begin
if(!A_F2_B[1])begin
F1=A_F1_B[1];
F2=A_F2_B[1];
F3=A_F3_B[1];
end
else begin
F1=A_F1_B[0];
F2=A_F2_B[0];
F3=A_F3_B[0];
end
end
end
endmodule
(b)仿真程序
module test_lab2_5();
reg [2:0]A,B;
wire F1,F2,F3;
initial begin
A=3'b000;
B=3'b000;
#10;
end
lab2_5 test(.A(A),.B(B),.F1(F1),.F2(F2),.F3(F3));
always begin
#50 A=3'b001;
#50 A=3'b010;
#50 B=3'b011;
#50 A=3'b011;
#50 A=3'b111;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports {A[0]}]
set_property IOSTAND LVCMOS33 [get_ports {A[0]}]
set_property PACKAGE_PIN L16 [get_ports {A[1]}]
set_property IOSTAND LVCMOS33 [get_ports {A[1]}]
set_property PACKAGE_PIN M13 [get_ports {A[2]}]
set_property IOSTAND LVCMOS33 [get_ports {A[2]}]
set_property PACKAGE_PIN R17 [get_ports {B[0]}]
set_property IOSTAND LVCMOS33 [get_ports {B[0]}]
set_property PACKAGE_PIN T18 [get_ports {B[1]}]
set_property IOSTAND LVCMOS33 [get_ports {B[1]}]
set_property PACKAGE_PIN U18 [get_ports {B[2]}]
set_property IOSTAND LVCMOS33 [get_ports {B[2]}]
set_property PACKAGE_PIN H17 [get_ports F1]
set_property IOSTAND LVCMOS33 [get_ports F1]
set_property PACKAGE_PIN K15 [get_ports F2]
set_property IOSTAND LVCMOS33 [get_ports F2]
set_property PACKAGE_PIN J13 [get_ports F3]
set_property IOSTAND LVCMOS33 [get_ports F3]
6、实验结果记录
(1)4位二进制加法/减法计数器的实验结果记录
(A)给出Verilog设计的模16加1/减1计数器的电路图
图2-2 4位二进制加法/减法计数器
(B)初值为2的模8计数器仿真结果截图(波形含CP,M,Qa,Qb,Qc,Qd,Q模8等)
图2-3 初值为2的模8计数器仿真
仿真对象:Q[3:0]、CP、M、Q1[3:0]、LD、CLR 、Qcc
周期:3000ns(图中蓝色marker)
输入参数:Q[3:0]、LD、CLR、CP(Q为输入状态,对应DCBA)
输出参数:Q1[3:0]、Qcc (Q1为输出状态,对应QdQcQbQa)
(C)开发板上的验证情况(主要记录:验证过程和结论)
①模16加1/减1计数器
验证过程:将生成比特流文件烧写进板子后,时钟脉冲对应引脚P17,输出状态为LED0~LED3,每按一次P17按钮就可根据M进行加一或减一计数。
结论:验证正确。
②实验时顶层文件由于使用wire型定义输出变量,仿真成功但生成比特流文件失败,实验课上未检查。后经修改后生成比特文件,无板子未验证。
(2)采用有限状态机(FSM) 实现序列检测器的实验结果记录
(A)给出Verilog设计的时序逻辑电路图
图2-4 10110序列检测器
(B)仿真结果截图(波形含clk,输入值,输出值等)
图2-5 10110序列检测器仿真
说明如下:
原程序有IDLE、A、B、C、D、E、F、G八个状态(依次对应0-7),in为输入信号,当发现序列为10110时,state到达D状态,输出标志flag输出为1。
仿真对象:data[23:0]、reset、clk、in、state、flag
输入参数:data[23:0](输入序列)
In(当前输入信号)
Clk(钟控脉冲信号)
Reset(重置信号)
输出参数:state(当前状态)
Flag(序列出现标志,发现序列时输出1,否则为0)
(C)开发板上的验证情况(主要记录:验证过程和结论)
验证过程:将比特文件烧写进板子后,in对应拨动开关sw0,flag对应LED0,拨动开关sw0输入序列10110,灯LED0亮起,状态为D。
结论:验证结果正确。但检查时未加入状态显示,后修改state对应灯LED1-3,生成比特流文件成功。
(3)3位二进制数值比较器的实验结果记录
(A)给出Verilog设计的3位二进制数值比较器的电路图
图2-6 3位二进制数值比较器
(B)仿真结果截图(含输入值,输出值等)
(要求对仿真进行如下说明:仿真对象、输入参数、输出参数、如果具有周期性的要在仿真图上将其“周期”加以标注和说明)
图2-7 3位二进制数值比较器仿真
仿真对象:A[2:0],B[2:0],F1,F2,F3
输入参数:A[2:0],B[2:0]
输出参数:F1,F2,F3
(C)开发板上的验证情况(主要记录:验证过程和结论)
验证过程:A对应开发板拨动开关SW2(高位)、SW1、SW0,B对应SW6、SW5、SW4。F1、F2、F3分别对应LED0、LED1、LED2。拨动AB开关,A>B,LED0亮起;A<B,LED 2亮起;A=B,LED1亮起。
结论:验证结果正确。
7、实验后的思考
1.请通过一个具体的实例来说明你是如何用仿真来验证你电路设计的正确性。
模16加1/减1计数器
设计仿真文件,输入端M每1500ns取反一次,时钟脉冲为100ns一次(上升沿),当,LD、CLR均为上升沿激励,LD每1500ns送入一次DCBA(即Q[3:0]),CLR每2
数字逻辑实验报告(2)
一、Verilog HDL设计数字逻辑电路
1、实验名称
Verilog HDL设计数字逻辑电路。
2、实验目的
要求同学用Verilog HDL设计数字逻辑电路,通过3个逻辑电路实验,并利用“Vivado 2015.2”软件进行“前、后”仿真检查电路设计,然后在“Xilinx NEXYS 4开发板”上操作、记录实验结果,最后验证设计是否达到要求。
通过以上设计、仿真、验证3个训练过程使同学们掌握Verilog HDL设计数字逻辑电路的基本方法,同时掌握如何避免锁存器的产生以及电路设计中的一致性问题的处理方法。
3、实验所用设备
Xilinx NEXYS 4开发板(芯片为XC7A100TCSG324-1,封装为CSG324,软件为Vivado 2015.2)1套。
4、实验内容
(1)组合、时序逻辑电路的“always”设计
(A)用“always块”设计纯组合逻辑电路
组合电路的一个特性是它的输出永远受输入变化的影响。也就是说组合电路绝不会保持它们以前的值,即输出不会出现锁存。
在使用always块中的case,if-else等语句设计纯组合逻辑电路时,要保证所有输入条件,其输出均有输出值,否则有可能会产生锁存器,导致“综合”出错。
例如:某题目要求使用Verilog设计实现一个纯组合逻辑电路的选择器,某同学设计了一个带“flag”标识的4选1的多路选择器,参见程序1-1所示,但是在“综合”时,报3个错误,即:“Place 30-574、Place 30-99、Common 17-69”。
具体要求:
(a)验证程序1-1在“综合”时,是否会出现上述问题;
(b)如果存在上述问题,请更正程序1-1,帮这位同学完成设计。
程序1-1 带“flag”标识的4选1的多路选择器
module mux_latch(
input [3:0] data,
input [1:0] valid,
input flag,
output reg valid_data);
initial begin
valid_data=1'b0;
end
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];end
2'b01 : begin if(flag) valid_data = data[1];end
2'b10 : begin if(flag) valid_data = data[2];end
2'b11 : begin if(flag) valid_data = data[3];end
endcase
end
endmodule
///*.xdc文件//
set_property PACKAGE_PIN T16 [get_ports flag]
set_property IOSTANDARD LVCMOS33 [get_ports flag]
set_property PACKAGE_PIN U8 [get_ports {valid[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {valid[0]}]
set_property PACKAGE_PIN R7 [get_ports {valid[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {valid[1]}]
set_property PACKAGE_PIN V7 [get_ports {data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[0]}]
set_property PACKAGE_PIN V6 [get_ports {data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[1]}]
set_property PACKAGE_PIN V5 [get_ports {data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[2]}]
set_property PACKAGE_PIN U4 [get_ports {data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data[3]}]
set_property PACKAGE_PIN T8 [get_ports valid_data]
set_property IOSTANDARD LVCMOS33 [get_ports valid_data]
(B)用“always块”设计一个同步时序逻辑电路
参见图1-1所示电路。
图1-1同步时序逻辑电路
具体要求:
利用Verilog HDL的“always块”设计该电路并进行仿真。
(注意:阻塞与非阻塞赋值的不同,这种组合和时序的混合电路建议使用非阻塞赋值)
(2)脉冲异步计数器的设计
分析如图1-2所示的脉冲异步计数器电路,完成如下内容:
图1-2 脉冲异步计数器电路
(A)说明该计数器的模是多少?
(B)用Verilog DHL实现该电路,并通过仿真和在开发板上验证设计。
(3)Verilog数字电路设计中一致性问题
分析如图1-3所示的电路,完成如下内容:
(A)程序1-2是对图1-3所示电路的描述,请用“Behavior Simulation-它可以称为前仿真”和“非Behavior Simulation-它可以称为后仿真”对程序1-2分别进行仿真,如果有错误,请更正程序1-2,并给出修正后的仿真结果。
(这就是:所谓前仿真和后仿真是否一致的问题)
q1 |
q2 |
图1-3 3位移位寄存器电路
(B)NEXYS 4开发板提供了一个100Mhz的同步时钟,引脚绑定为“E3”,在更正后的程序1-2中添加一个时钟分频部分,并将降频后的时钟信号接到图1-3中的“clk”,编译成功后再下载到开发板上测试它。
结论:在今后的设计中要保持:“前仿真和后仿真以及下载验证都正确”哟。
程序1-2 3位移位寄存器电路
module pipe3b(
input sig_nsyn,
input clk,
output q1,
output q2,
output sig_syn
);
reg q1;
reg q2;
reg sig_syn;
always@(posedge clk) q2=q1;
always@(posedge clk) sig_syn=q2;
always@(posedge clk) q1=sig_nsyn;
endmodule
5、实验方案设计
(1)组合、时序逻辑电路的“always”设计方案
(A)用“always块”设计纯组合逻辑电路
(a)验证程序1-1在“综合”时,是否会出现上述问题;
`timescale 1ns / 1ps
//
// Module Name: lab1
//
module mux_latch1(
input [3:0] data,
input [1:0] valid,
input flag,
output reg valid_data);
initial begin
valid_data=1'b0;
end
always @ (*)
begin
case(valid)
2'b00 : begin if(flag) valid_data = data[0];else valid_data = 1'bx; end
2'b01 : begin if(flag) valid_data = data[1];else valid_data = 1'bx; end
2'b10 : begin if(flag) valid_data = data[2];else valid_data = 1'bx; end
2'b11 : begin if(flag) valid_data = data[3];else valid_data = 1'bx; end
default: valid_data = 1'bx;
endcase
end
endmodule
(B)用“always块”设计实现一个同步时序逻辑电路
(a)源程序
module lab1_2(
input CP,
input X,
output Y);
reg T1;
reg Y;
wire T0,CP0,CP1,Q0,Q1;
T_trigger t0(.Q(Q0),.CP(CP0),.T(T0));
T_trigger t1(.Q(Q1),.CP(CP1),.T(T1));
assign T=1'b1;
assign CP0=CP;
assign CP1=CP;
always @ (CP)
begin
T1<= Q0^X;
Y<= ~(X&(~Q1));
end
endmodule
module T_trigger(Q,CP,T);
output Q;
reg Q;
input CP,T;
initial begin
Q=1'b0;
end
always @(negedge CP) begin
if(T)Q<=~Q;
(b)仿真程序
module test_lab1_2;
// Inputs
reg CP;
reg X;
// Outputs
wire Y;
// Instantiate the Unit Under Test (UUT)
lab1_2 uut ( .CP(CP),.X(X), .Y(Y));
// Initialize Inputs
initial begin
X=1'b0;
CP=1'b0;
#20;
end
always begin
#25 CP=~CP;
end
always begin
#200 X<=1;
#200 X<=0;
end
endmodule
(2)脉冲异步计数器的分析和设计方案
(A)源程序
module lab1_3(
input X,
output Z,
output Q1,Q2,Q3,Q4
);
wire J1,J2,J3,J4,K1,K2,K3,K4,CP1,CP2,CP3,CP4;
JK_trigger jk1(J1,K1,CP1,Q1);
JK_trigger jk2(J2,K2,CP2,Q2);
JK_trigger jk3(J3,K3,CP3,Q3);
JK_trigger jk4(J4,K4,CP4,Q4);
assign J1=1;
assign J2=~Q4;
assign J3=1;
assign J4=Q2&Q3;
assign K1=1;
assign K2=1;
assign K3=1;
assign K4=1;
assign CP1=X;
assign CP2=Q1;
assign CP3=Q2;
assign CP4=Q1;
assign Z=Q4&Q1&X;
endmodule
module JK_trigger(J,K,CP,Q);
input J,K,CP;
output Q;
reg Q;
initial begin
Q=0;
end
always @(negedge CP)
begin
case({J,K})
2'b00:Q<=Q;
2'b01:Q<=0;
2'b10:Q<=1;
2'b11:Q<=~Q;
endcase
end
endmodul
(B)仿真程序
module test_lab1_3();
reg X;
wire Z;
wire Q1,Q2,Q3,Q4;
lab1_3 test(.X(X),.Z(Z),.Q1(Q1),.Q2(Q2),.Q3(Q3),.Q4(Q4));
initial begin
X=0;
#20;
end
always #20 X=~X;
endmodule
(C)引脚约束(绑定)程序
set_property PACKAGE_PIN P17 [get_ports X]
set_property IOSTANDARD LVCMOS33 [get_ports X]
set_property PACKAGE_PIN R18 [get_ports {Z}]
set_property IOSTANDARD LVCMOS33 [get_ports {Z}]
set_property PACKAGE_PIN H17 [get_ports {Q1}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1}]
set_property PACKAGE_PIN K15 [get_ports {Q2}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q2}]
set_property PACKAGE_PIN J13 [get_ports {Q3}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q3}]
set_property PACKAGE_PIN N14 [get_ports {Q4}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q4}]
(3)Verilog设计中一致性问题的解决方案
(A)源程序
①更改后源程序:
module lab1_5(
input sig_nsyn,
input clk,
output q1,
output q2,
output sig_syn
);
reg q1;
reg q2;
reg sig_syn;
always@(posedge clk) begin
sig_syn<=q2;
q2<=q1;
q1<=sig_nsyn;
end
endmodule
(2)添加时钟分频后的源程序
module clk_device(clk,clk_N);
input clk; // 系统时钟 );
output reg clk_N; // 分频后的时钟endmodule
parameter N = 100_000_000; // 1kHz的时钟,N=fclk/fclk_N
reg [31:0] counter; //计数器变量,通过计数实现分频。
always @(posedge clk) begin
if(counter==((N/2-1)))counter=0;
else
counter= counter + 1;
end
always @(posedge clk) begin
if(counter==((N/2-1))) clk_N = !clk_N;
end
endmodule
module lab(clk,sig_nsyn,clk1,q1,q2,sig_syn);
input clk; // 系统时钟
input sig_nsyn;
output clk1; // 分频后的时钟
output q1,q2,sig_syn;
wire devide_clk;
clk_device #(100_000_000) divice(.clk(clk), .clk1(clk1));
lab1_5 lab(.sig_nsyn(sig_nsyn),.clk(clk1),.q1(q1),.q2(q2),.sig_syn(sig_syn));
endmodule
(B)仿真程序
module test_lab();
reg sig_nsyn;
reg clk;
wire clk1;
wire q1;
wire q2;
wire sig_syn;
lab test(.sig_nsyn(sig_nsyn),.clk(clk),.q1(q1),.q2(q2),.sig_syn(sig_syn),.clk1(clk1));
initial begin
sig_nsyn=1'b0;
clk=1'b0;
#10;
end
always begin
#25 clk=~clk;
end
always begin
#100 sig_nsyn<=1;
#100 sig_nsyn<=0;
end
endmodule
6、实验结果记录
(1)组合、时序逻辑电路的“always”设计
(A)用“always块”设计纯组合逻辑电路
(a)验证程序1-1在“综合”时,是否会出现上述问题;
综合时不会出现上述错误,而在run implementation时会出现。
(b)如果存在上述问题,请更正程序1-1,帮这位同学完成设计。
(B)用“always块”设计一个同步时序逻辑电路
参见图1-1所示电路。
图1-1同步时序逻辑电路
利用Verilog HDL的“always块”设计该电路并进行仿真。
仿真结果如下:
(2)脉冲异步计数器的设计
分析如图1-2所示的脉冲异步计数器电路,完成如下内容:
图1-2 脉冲异步计数器电路
- 说明该计数器的模是多少?
该计数器的模为十。计数序列(Q4Q3Q2Q1)为:
0000—>0001—>0010—>0011—>0100—>0101—>0110—>0111—>
1000—>1001—>0000。由1001—>0000时Z输出1。
(B)用Verilog DHL实现该电路,并通过仿真和在开发板上验证设计。
①仿真结果如下:
②开发板上验证通过。检查时缺少状态,现已添加。
(3)Verilog数字电路设计中一致性问题
分析如图1-3所示的电路,完成如下内容:
(A)程序1-2是对图1-3所示电路的描述,请用“Behavior Simulation-它可以称为前仿真”和“非Behavior Simulation-它可以称为后仿真”对程序1-2分别进行仿真,如果有错误,请更正程序1-2,并给出修正后的仿真结果。
(这就是:所谓前仿真和后仿真是否一致的问题)
q1 |
q2 |
图1-3 3位移位寄存器电路
- 更改前:由下图可知,原程序前后仿真不一致。
前仿真
后仿真
②更改后
前仿真:
后仿真
(B)NEXYS 4开发板提供了一个100Mhz的同步时钟,引脚绑定为“E3”,在更正后的程序1-2中添加一个时钟分频部分,并将降频后的时钟信号接到图1-3中的“clk”,编译成功后再下载到开发板上测试它。
- 仿真结果如下:
- 编译成功,下载失败:
原因:程序run implementation时出现placer错误,实验后经修改后可生成比特流文件,但无板子,无法验证。
二、Verilog HDL设计较复杂数字逻辑电路
1、实验名称
Verilog HDL设计较复杂数字逻辑电路。
2、实验目的
要求同学用Verilog HDL设计较复杂的数字逻辑电路,通过3个逻辑电路实验,并利用“Vivado 2015.2”软件进行“前、后”仿真检查电路设计,然后在“Xilinx NEXYS 4开发板”上操作、记录实验结果,最后验证设计是否达到要求。
通过以上设计、仿真、验证3个训练过程使同学们掌握Verilog HDL设计较复杂数字逻辑电路的基本方法,同时掌握“电路例化”、“模块化”的使用、异步时序逻辑电路的同步化处理以及用状态机设计控制电路。
3、实验所用组件
Xilinx NEXYS 4开发板(芯片为XC7A100TCSG324-1,封装为CSG324,软件为Vivado 2015.2)1套。
4、实验内容
(1)4位二进制加法/减法计数器的设计
设计一个能清零、置数和进位/借位输出的加1/减1的4位二进制计数器,其结构框图如图2-1所示。
图2-1 4位二进制加法/减法计数器
电路输入为计数脉冲CP、工作模式选择M、预制初值D,C,B,A(其中D为高位,A为低位)和预制控制 ,清零端 ;
输出为计数值QD,QC,QB,QA(QD为高位,QA为低位)和进位/借位输出 ;
当 为0时,电路输出清零;
预制控制 =0时,将D、C、B、A的输入值送到计数器中,并立即在QD,QC,QB,QA中输出;
模式选择端M=1时加1计数;
当M=0时减1计数;
当CP端输入一个上升沿信号时进行一次计数;
计数有进位/借位时 端输出一个负脉冲。
注意:用Verilog设计电路时,经常会遇到这样一些问题,例如:
(A)用两个always块对一个寄存器进行赋值,无论其中经过了怎样的条件判断,最终结果毫无疑问是将两个相独立的触发信号连在了寄存器的CLK端上,一个端口接入两信号,所以这样的语句是无法被综合成电路的。
(B)某电路如果有多个输入都可能引起输出值的改变,在使用“always”时,如果其触发条件为电路的“多个输入”时,如果语句的“并发性”处理不好,会造成系统编译成功、“行为仿真”也成功,但是系统生成不了“bit”文件。
解决方法:采用所谓“异步时序逻辑电路的同步化处理”,即:减少“always”的触发条件。
具体要求:
(A)用Verilog HDL实现该计数器,将之下载到开发板中进行验证;
(B)用已实现了的“4位二进制计数器”,采用“电路例化”或者“模块化”实现一个初值为2的模8计数器,并下载到开发板中进行验证;
(C)给出设计占用FPGA芯片的资源情况(希望越少越好)。
(2)采用有限状态机(FSM) 实现序列检测器
设计一个简单的状态机,其功能是检测一个串行的5位不可重叠的“10110”二进制序列检测器,当输入值出现“10110”时,给出输出标志。
具体要求如下:
(A)给出不可重叠的“10110”二进制序列的状态转移图;
(B)采用有限状态机“标准模板”来设计“10110”二进制序列检测器,在仿真正确后再下载到开发板中进行验证;
(C)给出设计占用FPGA芯片的资源情况(希望越少越好)。
(所谓有限状态机“标准模板”请参考教材:夏雨闻。Verilog数字系统设计教程第3版。北京:北京航空航天大学出版社,2013.)
(3)3位二进制数值比较器的设计
设计一个3位二进制数值比较器。当A>B时,F1=1,F2=F3=0;当A=B时, F2=1,F1=F3=0;当A<B时,F3=1,F1=F2=0。
具体要求:
(A)用Verilog HDL设计一个一位二进制数值比较器;
(B)用已实现了的一位二进制数值比较器,采用“电路例化”或者“模块化”实现一个3位二进制数值比较器;
(C)将所设计的电路下载到开发板上进行验证;
(D)给出设计占用FPGA芯片的资源情况(希望越少越好)。
5、实验方案设计
(1)4位二进制加法/减法计数器的设计方案
(A)模16加1/减1计数器
(a)源程序
module lab2(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
initial begin
Q1=4'b0000;
end
always @(posedge CP,posedge CLR,posedge LD) begin
if(CLR|LD)begin
if(CLR)Q1=0;
else if(LD)Q1=Q;
else
Q1=Q1;
end
else begin
if(M) begin
Q1<=Q1+1;
if(Q1==15)Qcc<=1;
else
Qcc=0;
end
else begin
Q1<=Q1-1;
if(!Q1)Qcc<=1;
else
Qcc<=0;
end
end
end
endmodule
(b)仿真程序
module test_lab2();
reg [3:0]Q;
reg CP,LD,M,CLR;
wire [3:0]Q1;
wire Qcc;
lab2 test(.Q1(Q1),.Q(Q),.CP(CP),.LD(LD),.CLR(CLR),.M(M),.Qcc(Qcc));
initial begin
Q=4'b1010;
CP=1'b0;
CLR=1'b0;
LD=1'b0;
M=1'b1;
#20;
end
always begin
#50 CP=~CP;
end
always begin
#1500 M=~M;
end;
always begin
#2475 CLR=1;
#25 CLR=0;
end
always begin
#1975 LD=1;
#25 LD=0;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports {Q[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[0]}]
set_property PACKAGE_PIN L16 [get_ports {Q[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[1]}]
set_property PACKAGE_PIN M13 [get_ports {Q[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[2]}]
set_property PACKAGE_PIN R15 [get_ports {Q[3}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q[3]}]
set_property PACKAGE_PIN P17 [get_ports CP]
set_property IOSTANDARD LVCMOS33 [get_ports CP]
set_property PACKAGE_PIN T18 [get_ports CLR]
set_property IOSTANDARD LVCMOS33 [get_ports CLR]
set_property PACKAGE_PIN U18 [get_ports LD]
set_property IOSTANDARD LVCMOS33 [get_ports LD]
set_property PACKAGE_PIN R13 [get_ports M]
set_property IOSTANDARD LVCMOS33 [get_ports M]
set_property PACKAGE_PIN H17 [get_ports {Q1[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[0]}]
set_property PACKAGE_PIN K15 [get_ports {Q1[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[1]}]
set_property PACKAGE_PIN J13 [get_ports {Q1[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[2]}]
set_property PACKAGE_PIN N14 [get_ports {Q1[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {Q1[3]}]
set_property PACKAGE_PIN V17 [get_ports {Qcc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qcc}]
(B)初值为2的模8计数器,要求:通过例化A【调用(A)实现的计数器】来实现。
(a)源程序
module counter1_4bit(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
initial begin
Q1=4'b0010;
end
always @(posedge CP,posedge CLR,posedge LD) begin
if(CLR|LD)begin
if(CLR)Q1<=4'b0010;
else if(LD)Q1<=Q;
else
Q1<=Q1;
end
else begin
if(M)begin
if(Q1>8||Q1<2)begin
Q1<=4'b0010;
Qcc<=1;
end
else begin
Q1<=Q1+1;
Qcc<=0;
end
end
else begin
if(Q1>9||Q1<3)begin
Q1<=4'b1001;
Qcc<=1;
end
else begin
Q1=Q1-1;
Qcc<=0;
end
end
end
end
endmodule
module model8_counter1(
input [3:0]Q,
input CP,LD,CLR,M,
output reg [3:0]Q1,
output reg Qcc
);
wire [3:0]Qt;
wire Qcc0;
counter1_4bit model_count(.Q(Q),.Q1(Qt),.CP(CP),.M(M),.LD(LD),.CLR(CLR),.Qcc(Qcc0));
always @(posedge CP)
begin
Q1=Qt;
Qcc=Qcc0;
end
endmodule
(b)仿真程序
module test_lab2_2();
reg [3:0]Q;
reg CP,M,LD,CLR;
wire [3:0]Q1;
wire Qcc;
model8_counter1 test(.Q(Q),.LD(LD),.CLR(CLR),.Q1(Q1),.CP(CP),.M(M),.Qcc(Qcc));
initial begin
Q=4'b0110;
CP=1'b0;
LD=1'b0;
CLR=1'b0;
M=1'b1;
#20;
end
always begin
#50 CP=~CP;
end
always begin
#1500 M=~M;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports A]
set_property IOSTANDARD LVCMOS33 [get_ports A]
set_property PACKAGE_PIN L16 [get_ports B]
set_property IOSTANDARD LVCMOS33 [get_ports B]
set_property PACKAGE_PIN M13 [get_ports C]
set_property IOSTANDARD LVCMOS33 [get_ports C]
set_property PACKAGE_PIN R15 [get_ports D]
set_property IOSTANDARD LVCMOS33 [get_ports D]
set_property PACKAGE_PIN P17 [get_ports CP]
set_property IOSTANDARD LVCMOS33 [get_ports CP]
set_property PACKAGE_PIN T18 [get_ports CLR]
set_property IOSTANDARD LVCMOS33 [get_ports CLR]
set_property PACKAGE_PIN U18 [get_ports LD]
set_property IOSTANDARD LVCMOS33 [get_ports LD]
set_property PACKAGE_PIN R13 [get_ports M]
set_property IOSTANDARD LVCMOS33 [get_ports M]
set_property PACKAGE_PIN H17 [get_ports {Qa}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qa}]
set_property PACKAGE_PIN K15 [get_ports {Qb}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qb}]
set_property PACKAGE_PIN J13 [get_ports {Qc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qc}]
set_property PACKAGE_PIN N14 [get_ports {Qd}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qd}]
set_property PACKAGE_PIN V17 [get_ports {Qcc}]
set_property IOSTANDARD LVCMOS33 [get_ports {Qcc}]
(2)采用有限状态机(FSM) 实现序列检测器的设计方案
(A)串行5位不可重叠的“10110”二进制序列检测器的状态图
(B)源程序
module lab2_3(in,clk,reset,flag,state);
input in,clk,reset;
output flag;
output reg [2:0]state;
wire flag;
parameter IDLE=3'd0,
A=3'd1,
B=3'd2,
C=3'd3,
D=3'd4,
E=3'd5,
F=3'd6,
G=3'd7;
assign flag=(state==D&&in==0)?1:0;
always @ (posedge clk or negedge reset)
if(!reset) begin
state<=IDLE;
end
else
casex(state)
IDLE:if(in==1)state<=A;
else
state<=IDLE;
A: if(in==0)state<=B;
else
state<=A;
B: if(in==1)state<=C;
else
state<=F;
C: if(in==1)state<=D;
else
state<=G;
D: if(in==0)state<=E;
else
state<=A;
E: if(in==1)state<=C;
else
state<=IDLE;
F: if(in==1)state<=A;
else
state<=IDLE;
G: if(in==1)state<=C;
else
state<=IDLE;
default: state<=IDLE;
endcase
endmodule
(C)仿真程序
module test_lab2_3();
reg clk,reset;
reg [23:0]data;
wire flag,in;
wire [2:0]state;
assign in=data[23];
initial
begin
clk=0;
reset=1;
#2 reset=0;
#30 reset=1;
data=20'b1011_0001_0110_1101_0110;
#(`halfperiod*1000)$stop;
end
always #(`halfperiod)clk=~clk;
always @(posedge clk)
#2 data={data[22:0],data[23]};
lab2_3 test(.in(in),.flag(flag),.clk(clk),.reset(reset),.state(state));
endmodule
(D)引脚约束(绑定)程序
set_property PACKAGE_PIN P17 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN J15 [get_ports in]
set_property IOSTANDARD LVCMOS33 [get_ports in]
set_property PACKAGE_PIN R17 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN H17 [get_ports flag]
set_property IOSTANDARD LVCMOS33 [get_ports flag]
set_property PACKAGE_PIN K15 [get_ports {state[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[0]}]
set_property PACKAGE_PIN J13 [get_ports {state[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[1]}]
set_property PACKAGE_PIN N14 [get_ports {state[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {state[2]}]
(3)3位二进制数值比较器的设计方案
(A)一位二进制数值比较器
(a)源程序
module lab2_4(
input A,B,
output F1,F2,F3
);
reg F1,F2,F3;
always @(A or B)begin
F1<=A&(~B);
F2<=~(A^B);
F3<=~A&B;
end
endmodule
(b)仿真程序
module test_lab2_4();
reg A,B;
wire F1,F2,F3;
initial begin
A=1'b0;
B=1'b0;
#10;
end
lab2_4 test(.A(A),.B(B),.F1(F1),.F2(F2),.F3(F3));
always begin
#50 A=~A;
#50 B=~B;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports A]
set_property IOSTAND LVCMOS33 [get_ports A]
set_property PACKAGE_PIN R17 [get_ports B]
set_property IOSTAND LVCMOS33 [get_ports B]
set_property PACKAGE_PIN H17 [get_ports F1]
set_property IOSTAND LVCMOS33 [get_ports F1]
set_property PACKAGE_PIN K15 [get_ports F2]
set_property IOSTAND LVCMOS33 [get_ports F2]
set_property PACKAGE_PIN J13 [get_ports F3]
set_property IOSTAND LVCMOS33 [get_ports F3]
(B)3位二进制数值比较器,要求:通过例化A【调用(A)实现的一位二进制数值比较器】来实现。
(a)源程序
module lab2_5(
input [2:0]A,B,
output reg F1,F2,F3
);
wire [2:0]A_F1_B,A_F2_B,A_F3_B;
lab2_4 lab(.A(A[2]),.B(B[2]),.F1(A_F1_B[2]),.F2(A_F2_B[2]),.F3(A_F3_B[2]));
lab2_4 lab1(.A(A[1]),.B(B[1]),.F1(A_F1_B[1]),.F2(A_F2_B[1]),.F3(A_F3_B[1]));
lab2_4 lab2(.A(A[0]),.B(B[0]),.F1(A_F1_B[0]),.F2(A_F2_B[0]),.F3(A_F3_B[0]));
always @ (A or B) begin
if(!A_F2_B[2])begin
F1=A_F1_B[2];
F2=A_F2_B[2];
F3=A_F3_B[2];
end
else begin
if(!A_F2_B[1])begin
F1=A_F1_B[1];
F2=A_F2_B[1];
F3=A_F3_B[1];
end
else begin
F1=A_F1_B[0];
F2=A_F2_B[0];
F3=A_F3_B[0];
end
end
end
endmodule
(b)仿真程序
module test_lab2_5();
reg [2:0]A,B;
wire F1,F2,F3;
initial begin
A=3'b000;
B=3'b000;
#10;
end
lab2_5 test(.A(A),.B(B),.F1(F1),.F2(F2),.F3(F3));
always begin
#50 A=3'b001;
#50 A=3'b010;
#50 B=3'b011;
#50 A=3'b011;
#50 A=3'b111;
end
endmodule
(c)引脚约束(绑定)程序
set_property PACKAGE_PIN J15 [get_ports {A[0]}]
set_property IOSTAND LVCMOS33 [get_ports {A[0]}]
set_property PACKAGE_PIN L16 [get_ports {A[1]}]
set_property IOSTAND LVCMOS33 [get_ports {A[1]}]
set_property PACKAGE_PIN M13 [get_ports {A[2]}]
set_property IOSTAND LVCMOS33 [get_ports {A[2]}]
set_property PACKAGE_PIN R17 [get_ports {B[0]}]
set_property IOSTAND LVCMOS33 [get_ports {B[0]}]
set_property PACKAGE_PIN T18 [get_ports {B[1]}]
set_property IOSTAND LVCMOS33 [get_ports {B[1]}]
set_property PACKAGE_PIN U18 [get_ports {B[2]}]
set_property IOSTAND LVCMOS33 [get_ports {B[2]}]
set_property PACKAGE_PIN H17 [get_ports F1]
set_property IOSTAND LVCMOS33 [get_ports F1]
set_property PACKAGE_PIN K15 [get_ports F2]
set_property IOSTAND LVCMOS33 [get_ports F2]
set_property PACKAGE_PIN J13 [get_ports F3]
set_property IOSTAND LVCMOS33 [get_ports F3]
6、实验结果记录
(1)4位二进制加法/减法计数器的实验结果记录
(A)给出Verilog设计的模16加1/减1计数器的电路图
图2-2 4位二进制加法/减法计数器
(B)初值为2的模8计数器仿真结果截图(波形含CP,M,Qa,Qb,Qc,Qd,Q模8等)
图2-3 初值为2的模8计数器仿真
仿真对象:Q[3:0]、CP、M、Q1[3:0]、LD、CLR 、Qcc
周期:3000ns(图中蓝色marker)
输入参数:Q[3:0]、LD、CLR、CP(Q为输入状态,对应DCBA)
输出参数:Q1[3:0]、Qcc (Q1为输出状态,对应QdQcQbQa)
(C)开发板上的验证情况(主要记录:验证过程和结论)
①模16加1/减1计数器
验证过程:将生成比特流文件烧写进板子后,时钟脉冲对应引脚P17,输出状态为LED0~LED3,每按一次P17按钮就可根据M进行加一或减一计数。
结论:验证正确。
②实验时顶层文件由于使用wire型定义输出变量,仿真成功但生成比特流文件失败,实验课上未检查。后经修改后生成比特文件,无板子未验证。
(2)采用有限状态机(FSM) 实现序列检测器的实验结果记录
(A)给出Verilog设计的时序逻辑电路图
图2-4 10110序列检测器
(B)仿真结果截图(波形含clk,输入值,输出值等)
图2-5 10110序列检测器仿真
说明如下:
原程序有IDLE、A、B、C、D、E、F、G八个状态(依次对应0-7),in为输入信号,当发现序列为10110时,state到达D状态,输出标志flag输出为1。
仿真对象:data[23:0]、reset、clk、in、state、flag
输入参数:data[23:0](输入序列)
In(当前输入信号)
Clk(钟控脉冲信号)
Reset(重置信号)
输出参数:state(当前状态)
Flag(序列出现标志,发现序列时输出1,否则为0)
(C)开发板上的验证情况(主要记录:验证过程和结论)
验证过程:将比特文件烧写进板子后,in对应拨动开关sw0,flag对应LED0,拨动开关sw0输入序列10110,灯LED0亮起,状态为D。
结论:验证结果正确。但检查时未加入状态显示,后修改state对应灯LED1-3,生成比特流文件成功。
(3)3位二进制数值比较器的实验结果记录
(A)给出Verilog设计的3位二进制数值比较器的电路图
图2-6 3位二进制数值比较器
(B)仿真结果截图(含输入值,输出值等)
(要求对仿真进行如下说明:仿真对象、输入参数、输出参数、如果具有周期性的要在仿真图上将其“周期”加以标注和说明)
图2-7 3位二进制数值比较器仿真
仿真对象:A[2:0],B[2:0],F1,F2,F3
输入参数:A[2:0],B[2:0]
输出参数:F1,F2,F3
(C)开发板上的验证情况(主要记录:验证过程和结论)
验证过程:A对应开发板拨动开关SW2(高位)、SW1、SW0,B对应SW6、SW5、SW4。F1、F2、F3分别对应LED0、LED1、LED2。拨动AB开关,A>B,LED0亮起;A<B,LED 2亮起;A=B,LED1亮起。
结论:验证结果正确。
7、实验后的思考
1.请通过一个具体的实例来说明你是如何用仿真来验证你电路设计的正确性。
模16加1/减1计数器
设计仿真文件,输入端M每1500ns取反一次,时钟脉冲为100ns一次(上升沿),当,LD、CLR均为上升沿激励,LD每1500ns送入一次DCBA(即Q[3:0]),CLR每2500ns置零一次。如上图,M=1进行加一计数;LD出现上升沿,送入Q;M=0进行减一计数;CLR出现上升沿,QdQcQbQa置零;QdQcQbQa由0000进行减一计数或由1111进行加一计数时,Qcc输出1,否则为0。