【实验三】设计一个8位十进制计数器(异步/同步)模块
- 实验内容与原理说明
根据计数器的构成原理,必须由四个触发器的状态来表示一位十进制数的四位二进制编码。而四位编码总共有十六个状态。所以必须去掉其中的六个状态,至于去掉哪六个状态,可有不同的选择。这里考虑去掉1010~1111六个状态,即采用8421BCD 码的编码方式来表示一位十进制数。
在十进制运算时,当相加二数之和大于9时,便产生进位。可是用BCD码完成十进制数运算时,当和数大于9 时,必须对和数进行加6修正。这是因为,采用BCD码后,在二数相加的和数小于等于9时,十进制运算的结果是正确的;而当相加的和数大于9时,结果不正确,必须加6修正后才能得出正确的结果。因此,当第一次近似求值时,可将它看成每一级是一个4位二进制加法器来执行,就好像X,和Y,是普通4位二进制数一样。设Si代表这样得到的4位二进制数和,Ci+1
为输出进位,而Si代表正确的BCD和,Ci+1代表正确的进位,那么
当Xi+Yi+Ci<10时,Si= Si`
当Xi+Yi+Ci≥10时,Si=Si`+6
显然,当Ci+1=1或S
≥10时,输出进位Ci+1=1。因此,可利用C i+1的状态来产生所要求的校正因子。C i+1=1时,校正因子为6;C i+1=0时校正因子为0。
当时钟信号CLK、复位信号RST、时钟使能信号EN或加载信号LOAD中任一信号发生变化,都将启动进程语句PROCESS。此时如果RST为'0',将对计数器清0,即复位。这项操作是独立于CLK的异步(独立)行为;如果RST为'1',则看是否有时钟信号的上升沿;如果此时有CLK 信号,且又测得 EN='1',接下去是判断加载控制信号 LOAD的电平。如果LOAD为低电平,则允许将输人口的4位加载数据置入计数寄存器中,以便计数器在此数基础上累加计数。而若LOAD为高电平,则允许计数器计数;此时若满足计数值小于9,即Q<9,计数器将进行正常计数,即执行语句“Q:=Q+1”,否则对计数器清0。但如果测得EN=’0’,则跳出IF语句,使Q保持原值,并将技术值向端口输出:“DOUT<=Q;”。
第二个IF语句的功能是当计数器Q的计数值达到9时由端口COUT输出高电平,作为十进制计数溢出的进位信号,而当Q为其他值时,输出低电平’0’。
- 实验模块程序代码和激励代码
(1)设计模块代码
module bit1Dcount(clk,dout,num,rst);
input clk;
input rst;
output reg dout;
output reg [3:0] num;
always@(posedge clk or negedge rst) begin
if(~rst) begin
num<=0;
end
else begin
if(num==9) begin
num<=0;
dout<=1;
end
else begin
num<=num+1;
dout<=0;
end
end
end
endmodule
module bit8Dcount(clk,dout,data,rst);
input clk;
input rst;
output reg dout=0;
output reg [31:0] data;
wire dout_1,dout_2,dout_3,dout_4,dout_5,dout_6,dout_7;
wire[31:0] num;
wire out;
bit1Dcount U0(.clk(clk),.dout(dout_1),.num(num[3:0]),.rst(rst));
bit1Dcount U1(.clk(dout_1),.dout(dout_2),.num(num[7:4]),.rst(rst));
bit1Dcount U2(.clk(dout_2),.dout(dout_3),.num(num[11:8]),.rst(rst));
bit1Dcount U3(.clk(dout_3),.dout(dout_4),.num(num[15:12]),.rst(rst));
bit1Dcount U4(.clk(dout_4),.dout(dout_5),.num(num[19:16]),.rst(rst));
bit1Dcount U5(.clk(dout_5),.dout(dout_6),.num(num[23:20]),.rst(rst));
bit1Dcount U6(.clk(dout_6),.dout(dout_7),.num(num[27:24]),.rst(rst));
bit1Dcount U7(.clk(dout_7),.dout(out),.num(num[31:28]),.rst(rst));
always@(posedge clk or negedge rst) begin
if(~rst) begin
data<=0;
dout<=0;
end
else begin
data<=num;
dout<=out;
end
end
endmodule
(2)激励模块代码
// Verilog Test Bench template for design : bit8Dcount
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module bit8Dcount_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg rst;
// wirst
wire [31:0] data;
wire dout;
// assign statements (if any)
bit8Dcount i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.data(data),
.dout(dout),
.rst(rst)
);
initial
begin
clk<=0;rst<=0;
4 rst<=1;
130000000 $stop;
end
always #1 clk<=~clk;
endmodule
- 波形仿真图
4.门级电路图
【四】设计一个m序列码产生器模块(要求:码长为31,寄存器级数5,反馈系数为75(八进制)的m序列产生器)
- 实验内容与原理说明
m序列又叫做伪随机序列、伪噪声(Pseudo Noise,PN)码或伪随机码,是一种可以资先确定、可以重复产生和复制又具有随机统计特性的二进制码序列。在通信系统中有着泛的应用,如扩频通信,卫星通信的码分多址,数字数据中的加密、加扰、同步、误码率测量等领域。
伪随机序列一般用二进制表示,每个码元(即构成m序列的元素)只有“0”或“1”两种取值,分别与数字电路中的低电平或高电平相对应。
m序列是对最长线性反馈移位寄存器序列的简称,它是一种由带线性反馈的移位寄存器所产生的序列,并且具有最长周期。下图所示是一种3位m序列产生器,它将最后两级触发器的输出通过同或门反馈到第一级的输入端,其工作原理是:在清零后,3个触发器的输出均为0,于是同或门的输出为1,在时钟触发下,每次移位后各级寄存器状态都会发生变化。分析该电路的仿真波形图,其中任何一级触发器(通常为末级)的输出都是一个周期序列(或者称为m序列),但各个输出端的m序列的初始相位不同。m序列的周期不仅与移位寄存器的级数有关,而且与线性反馈逻辑和初始状态有关。此外,在相同级数的情况下,采用不同的线性反馈逻辑所得到的周期长度是不同的。
通常,将类似于上图所示电路结构的m序列产生器称为简单型码序列发生器(Simple Shift Register Generator,SSRG),它的一般结构如图4.7.4所示、其中各个触发器构成位移寄存器。M序列反馈系数表如下所示:
- 实验模块程序代码和激励代码
(1)设计模块代码
module PNGenerator(clk,rst,en,dout,y);
input clk;
input rst;
input en;
output dout;
output reg [4:0] y;
assign dout=y[0];
always@(posedge clk or negedge rst) begin
if(~rst) begin
y<=5'b00001;
end
else if(en) begin
y[0]<=y[1];
y[1]<=y[2];
y[2]<=y[3];
y[3]<=y[4];
y[4]<=y[0]^y[1]^y[2]^y[3];
end
else begin
y<=y;
end
end
endmodule
(2)激励模块代码
// Verilog Test Bench template for design : PNGenerator
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module PNGenerator_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg en;
reg rst;
// wirst
wire dout;
wire [4:0] y;
// assign statements (if any)
PNGenerator i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.dout(dout),
.en(en),
.rst(rst),
.y(y)
);
initial
begin
clk<=0;rst<=0;en<=0;
17
rst<=1;
17
en<=1;
6000 $stop;
end
always #5 clk<=~clk;
endmodule
- 波形仿真图
4.门级电路图
【实验结果分析及思考】
这次实验是设计8位异步二进制计数器模块、8位同步二进制计数器模块、8位十进制计数器以及m序列码产生器模块的实验,我更加理解了在FPGA课本一开始所介绍的,行为描述是最常用的描述方法。在实际的建模中,我从看到题目要求的迷惑,逐渐转变为仔细分析题目要求,建模的自信,很大原因归功于行为描述的简洁与清晰。同样,实验中需要注意的地方是有关于异步、同步还有位数以及进制的问题。
此外,通过实验,也让我从实践的角度理解了异步和同步二进制加法计数器的构成区别:异步二进制加法计数器的构成方法是将触发器接成计数触发器;最低位触发器用计数脉冲 CP 触发,其他触发器用邻低位输出的下降沿触发。而同步二进制加法计数器的构成方法:将触发器接成 T 触发器;各触发器都用计数脉冲 CP 触发,最低位触发器 的T 输入为 1,其他触发器的 T 输入为其低位各触发器输出信号相与。
在程序设计和原理图设计的过程中,我通过对Quartus的练习和使用,锻炼了自己的编程能力,对于Quartus和Modelsim联合仿真也比以往熟练不少,也学会了如何在遇到错误的时候冷静分析原因,例如端口的定义错误,测试程序的逻辑报错等等,通过对程序不断调试和改进,我对于verilog语言的理解有了很大的提升。