基于FPGA的七段数码管计时器实现

秒表计时器(2019.7.28)

mistake:
1.在一个模块中尽量不要对输出端口进行操作,在模块内部再定义一个 reg类型的数据,对这个数据进行操作,然后用assign 连接到输出端口上
2.在顶层模块中例化另一个模块时候,注意赋予的激励跟所调用模块中定义的数据位宽要保持一致
3.在书写tb文件时候,信号有效时间要在复位信号反转之后
4.设计的思想,每个模块的功能是干什么的,这个模块的输出以及输入的作用,画出设计的思路模块流程图,这是最重要的
5. 每个模块都有时钟和复位信号

设计思路:
顶层模块 top.v(input: key_start key_stop output led1)

消抖、检测沿模块(input key_start key_stop output key_start_neg key_stop_neg)
消抖方法:1.将信号打三拍 2.用计数器计数到 20ms认为抖动结束

分频:( 输出en)
作用:对50M的时钟进行分频(设置一个带输出使能的计数器即可),得到一个不对称的百微妙脉 冲信号

得到六个计数器表示六个数码管:(input:en output: en1,en2,en3,en4,en5,en6)
在上一步分频模块的基础上,按照满十进一 并且自声归零的方法,依次得到六个脉冲信号

状态机:数码管的工作模式转换(IDLE WORK STOP)

译码:对上步产生的六个计数器进行译码 (可以先做一个模块进行译码,然后例化六次)

设计要求:
六个数码管,最高的两位是秒,中间三位是毫秒,最低位时百微妙

代码:
1.顶层模块
module clock_0(clk,Rst_n,key1,key2,
led1,led2,led3,led4,led5,led6);

input clk;
input Rst_n;
input key1;
input key2;

output [6:0]led1;
output [6:0]led2;
output [6:0]led3;
output [6:0]led4;
output [6:0]led5;
output [6:0]led6;

wire en1_wire;
wire en2_wire;
wire en3_wire;

div div_inst//分频 ok
(
.clk(clk),
.Rst_n(Rst_n),
.en1(en1_wire),
.en2(en2_wire),
.en3(en3_wire)
);

//消抖和采沿 ok
wire key1_neg_wir ;
wire key2_neg_wir ;
pro pro_inst
(
.clk(clk),
.Rst_n(Rst_n),
.key1(key1),
.key2(key2),
.key_start(),
.key_stop(),
.key1_neg(key1_neg_wir),
.key2_neg(key2_neg_wir)
);

//state machine
wire [3:0]count_en1_wire;
st st_inst
(
.clk(clk),
.Rst_n(Rst_n),
.key1_neg(key1_neg_wir),
.key2_neg(key2_neg_wir),
.en1(en1_wire),
.en2(en2_wire),
.en3(en3_wire),
.count_en1(count_en1_wire),
.count_en2( ),
.count_en3( )
);

//分离
wire [3:0] count1_wire;
wire [3:0] count2_wire;
wire [3:0] count3_wire;
wire [3:0] count4_wire;
wire [3:0] count5_wire;
wire [3:0] count6_wire;
fenli fenli_list
(
.clk(clk),
.Rst_n(Rst_n),
.count_en1(count_en1_wire),
.count1(count1_wire),
.count2(count2_wire),
.count3(count3_wire),
.count4(count4_wire),
.count5(count5_wire),
.count6(count6_wire)
);

//译码
decode decode_inst
(
.clk(clk),
.Rst_n(Rst_n),
.output1(count1_wire),
.output2(count2_wire),
.output3(count3_wire),
.output4(count4_wire),
.output5(count5_wire),
.output6(count6_wire),
.out_led1(led1),
.out_led2(led2),
.out_led3(led3),
.out_led4(led4),
.out_led5(led5),
.out_led6(led6)
);
endmodule

2.分频模块
module div(clk,Rst_n,en1,en2,en3);

input clk;
input Rst_n;
output reg en1;
output reg en2;
output reg en3;

parameter countus_max=5000;
parameter countms_max=10;
parameter counts_max=1000;

reg[15:0]countus;
reg[3:0]countms;
reg[11:0]counts;

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
countus<=1’b0;
else if(countus==countus_max-1’b1)
countus<=1’b0;
else
countus<=countus+1’b1;
end

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
en1<=1’b0;
else if(countus==countus_max-1’b1)
en1<=1’b1;
else
en1<=1’b0;

always@(posedge clk or negedge Rst_n)
begin
/* 两种写法等价
if(!Rst_n)
countms<=1’b0;
else if((countmscountms_max-1’b1)&&(countuscountus_max-1’b1))
countms<=1’b0;
else if(countuscountus_max-1’b1)
countms<=countms+1’b1;
*/
if(!Rst_n)
countms<=1’b0;
else if(countus
countus_max-1’b1)
begin
if (countms==countms_max-1’b1)
countms<=1’b0;
else
countms<=countms+1’b1;
end
end

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
en2<=1’b0;
else if(countms==countms_max-1’b1)
en2<=1’b1;
else
en2<=1’b0;

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
counts<=1’b0;
else if(countscounts_max-1’b1)
counts<=1’b0;
else if(countms
countms_max-1’b1)
counts<=counts+1’b1;
end

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
en3<=1’b0;
else if(countms==countms_max-1’b1)
en3<=1’b1;
else
en3<=1’b0;

endmodule

3.消抖和采沿
//消抖以及采沿
module pro(clk,Rst_n,key1,key2,key_start,key_stop,key1_neg,key2_neg);
input clk;
input Rst_n;
input key1;
input key2;

output reg key_start;
output reg key_stop;
output key1_neg;
output key2_neg;

reg key1_1;
reg key1_2;
reg key1_3;
reg key1_4;

reg key2_1;
reg key2_2;
reg key2_3;
reg key2_4;

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)begin

key1_1<=1’b0;
key1_2<=1’b0;
key1_3<=1’b0;
end
else begin
key1_1<=key1;
key1_2<=key1_1;
key1_3<=key1_2;
key_start<=key1_3;
end
end

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)begin
key2_1<=1’b0;
key2_2<=1’b0;
key2_3<=1’b0;
end
else begin
key2_1<=key2;
key2_2<=key2_1;
key2_3<=key2_2;
key_stop<=key2_3;
end
end

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
key1_4<=1’b0;//对一个数据进行操作
else
key1_4<=key1_3;
end

assign key1_neg=(~key1_3)&key1_4;

always@(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
key2_4<=1’b0;
else
key2_4<=key2_3;
end

assign key2_neg=(~key2_3)&key2_4;

endmodule

4状态机
module st(clk,Rst_n,key1_neg,key2_neg,en1,en2,en3,count_en1,count_en2,count_en3);

input clk;
input Rst_n;
input key1_neg;
input key2_neg;
input en1;
input en2;
input en3;

output reg [3:0]count_en1;
output reg [11:0]count_en2;
output reg [7:0]count_en3;

parameter IDLE=3’b001;
parameter WORK=3’b010;
parameter STOP=3’b100;

reg [2:0]current_state;
reg [2:0]next_state;

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
current_state<=IDLE;
else
current_state<=next_state;

always@(*)
if(!Rst_n)
next_state=IDLE;
else
case(current_state)
IDLE: if(key1_neg)
next_state=WORK;
else
next_state=IDLE;
WORK: if(key2_neg)
next_state=STOP;
else
next_state=WORK;
STOP: if(key1_neg)
next_state=WORK;
else
next_state=STOP;
default: next_state=IDLE;
endcase

always@(posedge clk or negedge Rst_n)
if(!Rst_n)begin
count_en1<=1’b0;
count_en2<=1’b0;
count_en3<=1’b0;
end
else
case(next_state)
IDLE: begin
count_en1<=1’b0;
count_en2<=1’b0;
count_en3<=1’b0;
end
WORK: begin
begin
if(count_en1==4’d9)
count_en1<=1’b0;
else if(en1)
count_en1<=count_en1+1’b1;
else
count_en1<=count_en1;
end

	   begin 
	   if(count_en2==10'd999) 
	       count_en2<=1'b0;
	   else if(en2) 
	       count_en2<=count_en2+1'b1;
	   else 
	       count_en2<=count_en2;
	   end
	   
	   begin 
	   if(count_en3==6'd59) 
	       count_en3<=1'b0;
	   else if(en3) 
	       count_en3<=count_en3+1'b1;
	   else 
	       count_en3<=count_en3;
	   end
	   end 
STOP:  
        begin
        count_en1<=count_en1;
		count_en2<=count_en2;
		count_en3<=count_en3;
        end 
default: ;

endcase

endmodule

5.做出六个脉冲信号
module fenli(clk,Rst_n,count_en1,count1,count2,count3,count4,count5,count6);

input clk;
input Rst_n;
input [3:0]count_en1;

output reg [3:0]count1,count2,count3,count4,count5,count6;
//count1
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count1<=1’b0;
else
count1<=count_en1;
//count2
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count2<=1’b0;
else if(count24’d9&&count14’d9)
count2<=1’b0;
else if(count14’d9)
count2<=count2+1’b1;
else
count2<=count2;
//count3
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count3<=1’b0;
else if(count3
4’d9&&count24’d9&&count14’d9)
count3<=1’b0;
else if(count24’d9&&count14’d9)
count3<=count3+1’b1;
else
count3<=count3;
//count4
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count4<=1’b0;
else if(count44’d9&&count34’d9&&count24’d9&&count14’d9)
count4<=1’b0;
else if(count34’d9&&count24’d9&&count14’d9)
count4<=count4+1’b1;
else
count4<=count4;
//count5
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count5<=1’b0;
else if(count5
4’d9&&count44’d9&&count34’d9&&count24’d9&&count14’d9)
count5<=1’b0;
else if(count44’d9&&count34’d9&&count24’d9&&count14’d9)
count5<=count5+1’b1;
else
count5<=count5;
//count6 写法简单 外设一个wire
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count6<=1’b0;
else if(count64’d5&&count54’d9&&count44’d9&&count34’d9&&count24’d9&&count14’d9)
count6<=1’b0;
else if(count54’d9&&count44’d9&&count34’d9&&count24’d9&&count1==4’d9)
count6<=count6+1’b1;
else
count6<=count6;
endmodule

6.译码器
module decode(clk,Rst_n,output1,output2,output3,output4,output5,output6,
out_led1,out_led2,out_led3,out_led4,out_led5,out_led6);

input clk;
input Rst_n;
input [3:0]output1;
input [3:0]output2;
input [3:0]output3;
input [3:0]output4;
input [3:0]output5;
input [3:0]output6;

output [6:0]out_led1;
output [6:0]out_led2;
output [6:0]out_led3;
output [6:0]out_led4;
output [6:0]out_led5;
output [6:0]out_led6;

wire [6:0]out_led11;
wire [6:0]out_led21;
wire [6:0]out_led31;
wire [6:0]out_led41;
wire [6:0]out_led51;
wire [6:0]out_led61;

led8 decode1_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output1),
. seg(out_led11)
);

led8 decode2_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output2),
. seg(out_led21)
);

led8 decode3_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output3),
. seg(out_led31)
);

led8 decode4_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output4),
. seg(out_led41)
);

led8 decode5_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output5),
. seg(out_led51)
);

led8 decode6_i
(
. clk(clk),
. Rst_n(Rst_n),
. d_cnt(output6),
. seg(out_led61)
);

assign out_led1=out_led11;
assign out_led2=out_led21;
assign out_led3=out_led31;
assign out_led4=out_led41;
assign out_led5=out_led51;
assign out_led6=out_led61;
endmodule

7.译码模块
module led8
(
input clk,
input Rst_n,
input [3:0] d_cnt ,
output [6:0]seg
);

parameter
S0=7’b100_0000,
S1=7’b111_1001,
S2=7’b010_0100,
S3=7’b011_0000,
S4=7’b001_1001,
S5=7’b001_0010,
S6=7’b000_0010,
S7=7’b111_1000,
S8=7’b000_0000,
S9=7’b001_0000;

reg [6:0]seg_1;
always@(posedge clk)
begin
if(~Rst_n)
seg_1<=0;
else
case(d_cnt )
4’b0000:seg_1<=S0;
4’b0001:seg_1<=S1;
4’b0010:seg_1<=S2;
4’b0011:seg_1<=S4;
4’b0100:seg_1<=S5;
4’b0101:seg_1<=S6;
4’b0110:seg_1<=S7;
4’b0111:seg_1<=S8;
4’b1000:seg_1<=S9;
default:seg_1<=S0;
endcase
end
assign seg=seg_1;

endmodule

猜你喜欢

转载自blog.csdn.net/jiyishizhe/article/details/97624066