数字逻辑与处理器基础
实验三 频率计
实验报告
实验目的:
掌握频率计的原理和设计方法。
实验工具:
1 Verilog语言
2 Quartus II 9.0
3 DE2实验板
实验设计:
1 总体思路以及模块总述
设计的基本思路是按照实验指导书上给出的原理图划分模块。
① 待测信号产生模块signalinput.v :由指导书给出,用于产生待测信号sigin ; ② 1Hz 时钟产生模块clk_1hz.v:通过实验板50MHz 产生1Hz 时钟clk_1hz;
③ 控制信号产生模块control.v :通过1Hz 时钟,产生频率计所需的使能信号en ,同步清零信号reset ,锁存信号la ,生成一个3秒钟的频率计数周期;
④ 十分频模块div_10.v:若量程选择信号sw_2为高电平,则待测信号需进行十分频; ⑤ 计数器模块counter.v :频率计的核心部分,包括四位十进制计数器,以及对应七段译码器的译码器。这里我把实验指导书中的译码模块整合在了里面,原因是认为在这个设计中单做一个译码模块意义不大,整合在里面翻倒方便一些;
⑥ 信号锁存模块lat.v :当锁存信号la 为高电平时,锁存输出持续显示; ⑦ 顶层模块div.v :进行各分立模块的功能综合;
2 模块分述
(1) 待测信号产生模块
代码:
module signalinput(testmode,sysclk,sigin);
input [1:0] testmode;//00,01,10,11分别代表4种频率,分别为3125,6250,50,12500Hz ,使用SW1~SW0来控制
input sysclk;//系统时钟50M
output sigin;//输出待测信号
reg[20:0] state;
reg[20:0] divide;
reg sigin;
initial
begin
sigin=0;
state=21'b[***********]000;
divide=21'b000000_1111_1010_0000000;
end
always@(testmode)
begin
case(testmode[1:0])
2'b00:divide=21'd16000; //3125Hz
2'b01:divide=21'd8000; //6250Hz
2'b10:divide=21'd1000000; //50Hz
2'b11:divide=21'd4000; //12500Hz
endcase
end
always@(posedge sysclk)//按divide 分频
begin
if(state==0)
sigin=~sigin;
state=state+21'b0_00__0000_0000_0000_0000_10;
if(state==divide)
state=27'b000_0000_0000_0000_0000_0000_0000;
end
endmodule
可以看出大致由两部分构成:频率选择、分频。通过testmode 的值先进行选择所需的频率,然后进行分频。
(2) 1Hz 时钟产生模块
代码:
module clk_1hz(sysclk,clk);
input sysclk;
output clk;
reg clk;
reg [31:0] counter;
initial
begin
counter
clk
end
always@(posedge sysclk)
begin
if(counter==32'd24999999)
begin
clk
counter
end
else counter
end
endmodule
把实验板上的50MHz 时钟进行50M 倍分频,得到1Hz 时钟。
(3) 控制信号产生模块
代码:
module control(clk_1hz,en,reset,la);
input clk_1hz;
output en,reset,la;
reg [2:0] state=3'b000;
reg en;
reg reset;
reg la;
parameter s0=3'b000,s1=3'b001,s2=3'b010;
always@(posedge clk_1hz)
begin
case(state)
s0:begin
en
reset
la
state
end
s1:begin
en
reset
la
state
end
s2:begin
la
reset
en
state
end
endcase
end
endmodule
通过1Hz 时钟产生3个控制信号,用了一个简单的状态转移,在3秒周期内,第一秒使能信号en 为高电平进行计数,第二三秒锁存信号为高电平,第三秒清零。为了验证正确性,单独进行了仿真,波形图如下图
可见功能正确。
(4) 十分频模块
代码:
module div_10(sigin,sw_2,sigout,led);
input sigin,sw_2;
output sigout,led;
reg sigout;
reg [3:0] counter;
always@(posedge sigin) begin
if(sw_2) begin
if(counter==4'd4) begin
sigout
counter
end
else counter
end
end
assign led=sw_2?1:0;
endmodule
当sw_2信号为高电平时,对信号进行10分频,并使led 信号为1。
(5) 计数器模块
代码:
module counter(sigin,en,reset,clr,hex0,hex1,hex2,hex3);
input sigin,en,reset,clr;
reg [3:0] q0;
reg [3:0] q1;
reg [3:0] q2;
reg [3:0] q3;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
always@(posedge sigin or posedge reset or negedge clr) begin
if(reset||(!clr)) begin
q0
q1
q2
q3
end
else if(en) begin
if(q0==4'd9) begin
if(q1==4'd9) begin
if(q2==4'd9) begin
q3
q2
else q2
q1
else q1
q0
else q0
else begin {q0,q1,q2,q3}
assign hex0=(q0==4'd0)?7'b1000000:
(q0==4'd1)?7'b1111001:
(q0==4'd2)?7'b0100100:
(q0==4'd3)?7'b0110000:
(q0==4'd4)?7'b0011001:
(q0==4'd5)?7'b0010010:
(q0==4'd6)?7'b0000010:
(q0==4'd7)?7'b1111000:
(q0==4'd8)?7'b0000000:
(q0==4'd9)?7'b0010000:7'b0;
assign hex1=(q1==4'd0)?7'b1000000:
(q1==4'd1)?7'b1111001:
(q1==4'd2)?7'b0100100:
(q1==4'd3)?7'b0110000:
(q1==4'd4)?7'b0011001:
(q1==4'd5)?7'b0010010:
(q1==4'd6)?7'b0000010:
(q1==4'd7)?7'b1111000:
(q1==4'd8)?7'b0000000:
(q1==4'd9)?7'b0010000:7'b0;
assign hex2=(q2==4'd0)?7'b1000000:
(q2==4'd1)?7'b1111001:
(q2==4'd2)?7'b0100100:
(q2==4'd3)?7'b0110000:
(q2==4'd4)?7'b0011001:
(q2==4'd5)?7'b0010010:
(q2==4'd6)?7'b0000010:
(q2==4'd7)?7'b1111000:
(q2==4'd8)?7'b0000000:
(q2==4'd9)?7'b0010000:7'b0;
assign hex3=(q3==4'd0)?7'b1000000:
(q3==4'd1)?7'b1111001:
(q3==4'd2)?7'b0100100:
(q3==4'd3)?7'b0110000:
(q3==4'd4)?7'b0011001:
(q3==4'd5)?7'b0010010:
(q3==4'd6)?7'b0000010:
(q3==4'd7)?7'b1111000:
(q3==4'd8)?7'b0000000:
(q3==4'd9)?7'b0010000:7'b0;
endmodule
包含一个四位十进制计数部分,和译码器电路,同时包含同步清零reset 和异步清零clr 。
(6) 信号锁存模块
代码:module lat(la,h0,h1,h2,h3,hex0,hex1,hex2,hex3);
input la;
input [6:0] h0;
input [6:0] h1;
input [6:0] h2;
input [6:0] h3;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
reg [6:0]hex0;
reg [6:0]hex1;
reg [6:0]hex2;
reg [6:0]hex3;
always@(la) begin
if(la) begin
hex0
hex1
hex2
hex3
end
else begin
hex0
hex1
hex2
hex3
end
end
endmodule
锁存信号la 低电平时输出透明,高电平时输出锁存。
(7) 顶层模块
代码:
module div(clock_50,clr,sw_0,sw_1,sw_2,led,hex0,hex1,hex2,hex3,led_1hz); input clock_50,clr,sw_0,sw_1,sw_2;
output led,led_1hz;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
wire [1:0] a;
wire sigin,sigout,clk_1hz,en,reset,la;
wire [6:0] h0;
wire [6:0] h1;
wire [6:0] h2;
wire [6:0] h3;
wire x;
assign a = {sw_1,sw_0};
assign led_1hz=la;
signalinput sig_top(.testmode(a),.sysclk(clock_50),.sigin(sigin));
div_10 div_top(.sigin(sigin),.sw_2(sw_2),.sigout(x),.led(led));
clk_1hz clk_top(.sysclk(clock_50),.clk(clk_1hz));
assign sigout=sw_2?x:sigin;
control
control_top(.clk_1hz(clk_1hz),.en(en),.reset(reset),.la(la));
counter
counter_top(.sigin(sigout),.en(en),.reset(reset),.clr(clr),.hex0(h0),.hex1(h1),.hex2(h2),.hex3(h3));
lat
lat_top(.la(la),.h0(h0),.h1(h1),.h2(h2),.h3(h3),.hex0(hex0),.hex1(hex1),.hex2(hex2),.hex3(hex3));
endmodule
把所有模块进行串联,中间根据sw_2选择是否进行十分频。
顶层模块的RTL 级电路图如下:
问题及解决办法
1 十分频判断问题
待测信号是否需要十分频依据sw_2信号的判断,我开始把判断语句写在了十分频always 语句的里面,如:
always@(posegdge sigin) begin
if(!sw_2) sigout
else 十分频...
end
这样导致输出信号无变化,后来发现原因是sigout 每次被sigin 赋值时,均在sigin 上升沿,所以无变化。解决办法是在十分频模块中增加一个wire 信号进行判断,或者把判断放在顶层模块中,我选择后者。
2 十进制问题
十进制数是4位二进制代表1位十进制,我开始把十进制数写成了1’d1,使十进制数只有1位被表示出来,故十进制变成了二进制。
3 reg 声明问题
声明寄存器时需要写上位数如:reg [6:0] hex1; 没有带位数时,只给hex1赋了最低位,导致七段译码器前两位为无输入状态“88”。并且此时变异不报错,只能从警告中查出,经老师指出改正后正常。
心得收获
本次实验涉及了之前实验中的内容并且进行了综合,我在开始设计时并没有仔细分析信号的变化过程,导致出现了很多低级错误,如问题1,在以后的设计中需要更加稳健。
数字逻辑与处理器基础
实验三 频率计
实验报告
实验目的:
掌握频率计的原理和设计方法。
实验工具:
1 Verilog语言
2 Quartus II 9.0
3 DE2实验板
实验设计:
1 总体思路以及模块总述
设计的基本思路是按照实验指导书上给出的原理图划分模块。
① 待测信号产生模块signalinput.v :由指导书给出,用于产生待测信号sigin ; ② 1Hz 时钟产生模块clk_1hz.v:通过实验板50MHz 产生1Hz 时钟clk_1hz;
③ 控制信号产生模块control.v :通过1Hz 时钟,产生频率计所需的使能信号en ,同步清零信号reset ,锁存信号la ,生成一个3秒钟的频率计数周期;
④ 十分频模块div_10.v:若量程选择信号sw_2为高电平,则待测信号需进行十分频; ⑤ 计数器模块counter.v :频率计的核心部分,包括四位十进制计数器,以及对应七段译码器的译码器。这里我把实验指导书中的译码模块整合在了里面,原因是认为在这个设计中单做一个译码模块意义不大,整合在里面翻倒方便一些;
⑥ 信号锁存模块lat.v :当锁存信号la 为高电平时,锁存输出持续显示; ⑦ 顶层模块div.v :进行各分立模块的功能综合;
2 模块分述
(1) 待测信号产生模块
代码:
module signalinput(testmode,sysclk,sigin);
input [1:0] testmode;//00,01,10,11分别代表4种频率,分别为3125,6250,50,12500Hz ,使用SW1~SW0来控制
input sysclk;//系统时钟50M
output sigin;//输出待测信号
reg[20:0] state;
reg[20:0] divide;
reg sigin;
initial
begin
sigin=0;
state=21'b[***********]000;
divide=21'b000000_1111_1010_0000000;
end
always@(testmode)
begin
case(testmode[1:0])
2'b00:divide=21'd16000; //3125Hz
2'b01:divide=21'd8000; //6250Hz
2'b10:divide=21'd1000000; //50Hz
2'b11:divide=21'd4000; //12500Hz
endcase
end
always@(posedge sysclk)//按divide 分频
begin
if(state==0)
sigin=~sigin;
state=state+21'b0_00__0000_0000_0000_0000_10;
if(state==divide)
state=27'b000_0000_0000_0000_0000_0000_0000;
end
endmodule
可以看出大致由两部分构成:频率选择、分频。通过testmode 的值先进行选择所需的频率,然后进行分频。
(2) 1Hz 时钟产生模块
代码:
module clk_1hz(sysclk,clk);
input sysclk;
output clk;
reg clk;
reg [31:0] counter;
initial
begin
counter
clk
end
always@(posedge sysclk)
begin
if(counter==32'd24999999)
begin
clk
counter
end
else counter
end
endmodule
把实验板上的50MHz 时钟进行50M 倍分频,得到1Hz 时钟。
(3) 控制信号产生模块
代码:
module control(clk_1hz,en,reset,la);
input clk_1hz;
output en,reset,la;
reg [2:0] state=3'b000;
reg en;
reg reset;
reg la;
parameter s0=3'b000,s1=3'b001,s2=3'b010;
always@(posedge clk_1hz)
begin
case(state)
s0:begin
en
reset
la
state
end
s1:begin
en
reset
la
state
end
s2:begin
la
reset
en
state
end
endcase
end
endmodule
通过1Hz 时钟产生3个控制信号,用了一个简单的状态转移,在3秒周期内,第一秒使能信号en 为高电平进行计数,第二三秒锁存信号为高电平,第三秒清零。为了验证正确性,单独进行了仿真,波形图如下图
可见功能正确。
(4) 十分频模块
代码:
module div_10(sigin,sw_2,sigout,led);
input sigin,sw_2;
output sigout,led;
reg sigout;
reg [3:0] counter;
always@(posedge sigin) begin
if(sw_2) begin
if(counter==4'd4) begin
sigout
counter
end
else counter
end
end
assign led=sw_2?1:0;
endmodule
当sw_2信号为高电平时,对信号进行10分频,并使led 信号为1。
(5) 计数器模块
代码:
module counter(sigin,en,reset,clr,hex0,hex1,hex2,hex3);
input sigin,en,reset,clr;
reg [3:0] q0;
reg [3:0] q1;
reg [3:0] q2;
reg [3:0] q3;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
always@(posedge sigin or posedge reset or negedge clr) begin
if(reset||(!clr)) begin
q0
q1
q2
q3
end
else if(en) begin
if(q0==4'd9) begin
if(q1==4'd9) begin
if(q2==4'd9) begin
q3
q2
else q2
q1
else q1
q0
else q0
else begin {q0,q1,q2,q3}
assign hex0=(q0==4'd0)?7'b1000000:
(q0==4'd1)?7'b1111001:
(q0==4'd2)?7'b0100100:
(q0==4'd3)?7'b0110000:
(q0==4'd4)?7'b0011001:
(q0==4'd5)?7'b0010010:
(q0==4'd6)?7'b0000010:
(q0==4'd7)?7'b1111000:
(q0==4'd8)?7'b0000000:
(q0==4'd9)?7'b0010000:7'b0;
assign hex1=(q1==4'd0)?7'b1000000:
(q1==4'd1)?7'b1111001:
(q1==4'd2)?7'b0100100:
(q1==4'd3)?7'b0110000:
(q1==4'd4)?7'b0011001:
(q1==4'd5)?7'b0010010:
(q1==4'd6)?7'b0000010:
(q1==4'd7)?7'b1111000:
(q1==4'd8)?7'b0000000:
(q1==4'd9)?7'b0010000:7'b0;
assign hex2=(q2==4'd0)?7'b1000000:
(q2==4'd1)?7'b1111001:
(q2==4'd2)?7'b0100100:
(q2==4'd3)?7'b0110000:
(q2==4'd4)?7'b0011001:
(q2==4'd5)?7'b0010010:
(q2==4'd6)?7'b0000010:
(q2==4'd7)?7'b1111000:
(q2==4'd8)?7'b0000000:
(q2==4'd9)?7'b0010000:7'b0;
assign hex3=(q3==4'd0)?7'b1000000:
(q3==4'd1)?7'b1111001:
(q3==4'd2)?7'b0100100:
(q3==4'd3)?7'b0110000:
(q3==4'd4)?7'b0011001:
(q3==4'd5)?7'b0010010:
(q3==4'd6)?7'b0000010:
(q3==4'd7)?7'b1111000:
(q3==4'd8)?7'b0000000:
(q3==4'd9)?7'b0010000:7'b0;
endmodule
包含一个四位十进制计数部分,和译码器电路,同时包含同步清零reset 和异步清零clr 。
(6) 信号锁存模块
代码:module lat(la,h0,h1,h2,h3,hex0,hex1,hex2,hex3);
input la;
input [6:0] h0;
input [6:0] h1;
input [6:0] h2;
input [6:0] h3;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
reg [6:0]hex0;
reg [6:0]hex1;
reg [6:0]hex2;
reg [6:0]hex3;
always@(la) begin
if(la) begin
hex0
hex1
hex2
hex3
end
else begin
hex0
hex1
hex2
hex3
end
end
endmodule
锁存信号la 低电平时输出透明,高电平时输出锁存。
(7) 顶层模块
代码:
module div(clock_50,clr,sw_0,sw_1,sw_2,led,hex0,hex1,hex2,hex3,led_1hz); input clock_50,clr,sw_0,sw_1,sw_2;
output led,led_1hz;
output [6:0] hex0;
output [6:0] hex1;
output [6:0] hex2;
output [6:0] hex3;
wire [1:0] a;
wire sigin,sigout,clk_1hz,en,reset,la;
wire [6:0] h0;
wire [6:0] h1;
wire [6:0] h2;
wire [6:0] h3;
wire x;
assign a = {sw_1,sw_0};
assign led_1hz=la;
signalinput sig_top(.testmode(a),.sysclk(clock_50),.sigin(sigin));
div_10 div_top(.sigin(sigin),.sw_2(sw_2),.sigout(x),.led(led));
clk_1hz clk_top(.sysclk(clock_50),.clk(clk_1hz));
assign sigout=sw_2?x:sigin;
control
control_top(.clk_1hz(clk_1hz),.en(en),.reset(reset),.la(la));
counter
counter_top(.sigin(sigout),.en(en),.reset(reset),.clr(clr),.hex0(h0),.hex1(h1),.hex2(h2),.hex3(h3));
lat
lat_top(.la(la),.h0(h0),.h1(h1),.h2(h2),.h3(h3),.hex0(hex0),.hex1(hex1),.hex2(hex2),.hex3(hex3));
endmodule
把所有模块进行串联,中间根据sw_2选择是否进行十分频。
顶层模块的RTL 级电路图如下:
问题及解决办法
1 十分频判断问题
待测信号是否需要十分频依据sw_2信号的判断,我开始把判断语句写在了十分频always 语句的里面,如:
always@(posegdge sigin) begin
if(!sw_2) sigout
else 十分频...
end
这样导致输出信号无变化,后来发现原因是sigout 每次被sigin 赋值时,均在sigin 上升沿,所以无变化。解决办法是在十分频模块中增加一个wire 信号进行判断,或者把判断放在顶层模块中,我选择后者。
2 十进制问题
十进制数是4位二进制代表1位十进制,我开始把十进制数写成了1’d1,使十进制数只有1位被表示出来,故十进制变成了二进制。
3 reg 声明问题
声明寄存器时需要写上位数如:reg [6:0] hex1; 没有带位数时,只给hex1赋了最低位,导致七段译码器前两位为无输入状态“88”。并且此时变异不报错,只能从警告中查出,经老师指出改正后正常。
心得收获
本次实验涉及了之前实验中的内容并且进行了综合,我在开始设计时并没有仔细分析信号的变化过程,导致出现了很多低级错误,如问题1,在以后的设计中需要更加稳健。