基于FPGA的数字跑表

更新时间:2023-10-08 07:31:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

现代电子实验

数字跑表实验报告

一.功能要求 基本功能: 1)、跑表精度为0.01秒 2)、跑表计时范围为:1小时 3)、设置开始计时/停止计时、复位两个按钮 4)、显示工作方式:用六位BCD七段数码管显示读数。显示格式:

分 秒 0.01秒

扩展功能: 1)、按键消抖; 2)、分别存储三组选手时间并分时回放显示;

一.设计要求

1)设计出符合要求的解决方案 2)设计出单元电路

3)利用EDA软件对单元电路及整体电路进行仿真 4)利用EDA软件在实验板上验证

总体设计框图

时钟输入

按键输入

计数器 除法器 按键消抖 功能控制模块 译码模块 数码管扫描模块 数码管 设计说明:

对于按键输入,先对按键进行消抖,然后按键输入信息给功能控制模块,此模块是核心控制中心,它能控制计数模块计数的开始,停止。同时,当相应按键按下时,它还可以对计数结果进行存储和读取,其中用到了一个F I F O。由于计数时候个位和十位并没有分开,所以之后我们采用了一个除法器,把个位和十位分离。之后的数据经过译码以后就可以由数码管显示了。

单元电路划分

1.按键输入模块 (1)按键检测模块 (2)按键消抖模块 2.计数器模块 3.功能控制模块 4.数码管显示译码模块

(1)除法器(实现计数结果十位,个位的分离) (2)译码模块 5.数码管扫描显示模块

各单元电路设计

1.按键输入模块

功能说明:检测按键的输入,并对按键进行消抖,由两个小的模块组成 源码:

module debounce (

CLK, RST, Pin_In, Pin_Out ); input CLK; input RST; input Pin_In; output Pin_Out; /**************************/ wire H2L_Sig; wire L2H_Sig;

detect U1 ( .CLK( CLK ), .RST( RST ), .Pin_In( Pin_In ), // input - from top .H2L_Sig( H2L_Sig ), // output - to U2 .L2H_Sig( L2H_Sig ) // output - to U2 ); /**************************/ delay U2 ( .CLK( CLK ), .RST( RST ), .H2L_Sig( H2L_Sig ), // input - from U1 .L2H_Sig( L2H_Sig ), // input - from U1 .Pin_Out( Pin_Out ) // output - to top ); /*******************************/

endmodule

1)按键检测 功能说明:

本模块实现对按键的检测,当按键被按下时,产生相应的信号 源代码: module detect (

CLK, RST, Pin_In, H2L_Sig, L2H_Sig );

input CLK; input RST; input Pin_In; output H2L_Sig; output L2H_Sig; /**********************************/

parameter T100US = 11'd4_799; /**********************************/ reg [10:0]Count1; reg isEn; always @ ( posedge CLK or negedge RST ) if( !RST ) begin Count1 <= 11'd0; isEn <= 1'b0; end else if( Count1 == T100US ) isEn <= 1'b1; else Count1 <= Count1 + 1'b1;

/********************************************/ reg H2L_F1; reg H2L_F2; reg L2H_F1; reg L2H_F2; always @ ( posedge CLK or negedge RST ) if( !RST ) begin H2L_F1 <= 1'b1; H2L_F2 <= 1'b1; L2H_F1 <= 1'b0; L2H_F2 <= 1'b0; end else begin H2L_F1 <= Pin_In; H2L_F2 <= H2L_F1; L2H_F1 <= Pin_In; L2H_F2 <= L2H_F1; end

/***********************************/

assign H2L_Sig = isEn ? ( H2L_F2 & !H2L_F1 ) : 1'b0; assign L2H_Sig = isEn ? ( !L2H_F2 & L2H_F1 ) : 1'b0; /***********************************/

Endmodule

Testbench Detect.v

`timescale 1 ps/ 1 ps module detect_tb(); reg CLK; reg Pin_In; reg RST;

// wires wire H2L_Sig; wire L2H_Sig;

detect i1 ( .CLK(CLK), .H2L_Sig(H2L_Sig), .L2H_Sig(L2H_Sig), .Pin_In(Pin_In), .RST(RST) );

initial begin CLK=0; RST=0; Pin_In=0; #10 RST=1; #100 Pin_In=1;

end

always begin #1

CLK=~CLK;

end Endmodule

仿真截图:

结果说明:

当电平由0到1跳变时,L2H_Sig做出了正确的反应,此模块功能正确。

2)按键消抖模块

功能说明:

由于机械振动,当按键按下时,如果直接控制功能模块,我们可能会得到错误的信息,因此,我们有必要对按键进行消抖,本模块采用延时的方法,对按键进行消抖。 源代码: module delay (

CLK, RST, H2L_Sig, L2H_Sig, Pin_Out );

input CLK; input RST; input H2L_Sig; input L2H_Sig; output Pin_Out; /****************************************/ parameter T1MS = 16'd47_999; /***************************************/ reg [15:0]Count1; reg isCount; always @ ( posedge CLK or negedge RST ) if( !RST ) Count1 <= 16'd0;

else if( isCount && Count1 == T1MS ) Count1 <= 16'd0; else if( isCount ) Count1 <= Count1 + 1'b1; else if( !isCount ) Count1 <= 16'd0;

/****************************************/

reg [3:0]Count_MS; always @ ( posedge CLK or negedge RST ) if( !RST ) Count_MS <= 4'd0; else if( isCount && Count1 == T1MS ) Count_MS <= Count_MS + 1'b1; else if( !isCount ) Count_MS <= 4'd0; /******************************************/ reg rPin_Out; reg [1:0]i; always @ ( posedge CLK or negedge RST ) if( !RST ) begin isCount <= 1'b0; rPin_Out <= 1'b0; i <= 2'd0; end else case ( i ) 2'd0 : if( H2L_Sig ) i <= 2'd1; else if( L2H_Sig ) i <= 2'd2; 2'd1 : if( Count_MS == 4'd10 ) begin isCount <= 1'b0; rPin_Out <= 1'b1; i <= 2'd0; end else isCount <= 1'b1;

2'd2 : if( Count_MS == 4'd10 ) begin isCount <= 1'b0; rPin_Out <= 1'b0; i <= 2'd0; end else isCount <= 1'b1; endcase

/********************************************/ assign Pin_Out = rPin_Out; /********************************************/

Endmodule

Testbech

`timescale 1 ps/ 1 ps module delay_tb(); reg CLK; reg H2L_Sig; reg L2H_Sig; reg RST;

// wires wire Pin_Out;

delay i1 ( .CLK(CLK), .H2L_Sig(H2L_Sig), .L2H_Sig(L2H_Sig), .Pin_Out(Pin_Out), .RST(RST) );

initial begin CLK=0; RST=0; H2L_Sig=0; H2L_Sig=0; #10 RST=1; #100

H2L_Sig=1; #10

H2L_Sig=0;

#50

H2L_Sig=1; #100

H2L_Sig=0;

end

always begin #1

CLK=~CLK;

end Endmodule

仿真截图

功能说明:

对于短暂的抖动,Pin_Out并无变化,只有当按键按下时间大于一定时间是,Pin_Out才会发生变化。此模块功能正确。

2.计数器模块

功能说明:

由于本实验是为了实现数字跑表,毫无疑问,计数器就成了本实验的关键,本模块主要完成技术功能,实现毫秒,秒,分的计数 源代码:

module count(CLK, RST, Ten_MS, Minute,

isCount, Second);

input CLK; input RST; input isCount;

output [7:0]Minute; output [7:0]Second; output [7:0]Ten_MS;

/**********************************/

parameter T10MS = 19'd479_999;//CLK=48MHz-1

/**********************************/

reg [18:0]Count1; reg [7:0]Count_S; reg [7:0]Count_M;

reg [7:0]Count_10MS;

always @ ( posedge CLK or negedge RST ) if(! RST ) begin Count1 <= 16'd0; Count_S <= 6'd0; Count_M <= 6'd0; Count_10MS<=10'd0; end

else if(isCount) begin if( Count1 == T10MS ) begin Count1 <= 16'd0; if( Count_10MS== 7'd99 ) begin Count_10MS<=10'd0; if( Count_S== 6'd59 ) begin Count_S<=6'd0; if( Count_M== 6'd59 ) begin Count_M<=6'd0;

end else Count_M<=Count_M+1'b1; end else Count_S<=Count_S+1'b1; end else Count_10MS<=Count_10MS+1'b1; end else Count1 <= Count1 + 1'b1; end

else if(!isCount) begin Count1 <= Count1; Count_S <= Count_S; Count_M <= Count_M; Count_10MS<=Count_10MS; end

/******************************************/ assign Minute=Count_M; assign Second=Count_S; assign Ten_MS=Count_10MS;

/******************************************/ Endmodule

Testbench

`timescale 1 ps/ 1 ps module count_tb();

reg CLK; reg RST; reg isCount;

// wires wire [7:0] Minute; wire [7:0] Second; wire [7:0] Ten_MS;

count i1 (

.CLK(CLK), .Minute(Minute), .RST(RST), .Second(Second), .Ten_MS(Ten_MS), .isCount(isCount) );

initial begin CLK=0; RST=0; isCount=1; #10 RST=1;

end always begin #1

CLK=~CLK; end

endmodule 仿真波形

仿真结果说明:

由仿真图可知,当Ten_MS=99是,秒加一,当秒计数到59时,分加一,所以此模块功能正确

3.功能控制模块

功能说明:

此模块接受按键传过来的信息,并根据按键信息对各模块进行控制,包括了计时器的计数使能,存储数据,回放数据,是所有模块中最复杂的部分。 源代码:

module control( CLK, RST, KEY, MS_Data_in, SEC_Data_in, Minu_Data_in, MS_Data_out, SEC_Data_out, Minu_Data_out, Count_EN, LED );

input CLK; input RST; input [2:0]KEY;

input [7:0]MS_Data_in; input [7:0]SEC_Data_in; input [7:0]Minu_Data_in; output [7:0]MS_Data_out; output [7:0]SEC_Data_out; output [7:0]Minu_Data_out; output Count_EN; output [3:0]LED;

/****************************************/ parameter T10MS = 19'd49_9999; /***************************************/ reg [18:0]Count1; reg isCount;

always @ ( posedge CLK or negedge RST ) if( !RST ) Count1 <= 19'd0; else if( isCount && Count1 == T10MS ) Count1 <= 19'd0; else if( isCount ) Count1 <= Count1 + 1'b1; else if( !isCount ) Count1 <= 19'd0;

/****************************************/

reg [9:0]Count_MS; always @ ( posedge CLK or negedge RST ) if( !RST ) Count_MS <= 4'd0; else if( isCount && Count1 == T10MS ) if( Count_MS == 10'd200 ) Count_MS<=10'd0; else Count_MS <= Count_MS + 1'b1; else if( !isCount ) Count_MS <= 4'd0; /******************************************/

reg [7:0]rMS; reg [7:0]rSEC; reg [7:0]rMinu;

reg [7:0]rMS_Data[2:0]; reg [7:0]rSEC_Data[2:0]; reg [7:0]rMinu_Data[2:0];

reg rEN;

reg [2:0]wr_addr; reg [2:0]rd_addr; reg Key_Up;

always @(posedge CLK or negedge RST) if(!RST) begin wr_addr=3'b0;

rd_addr=3'b0; rEN=1'b0; Key_Up=0; rMS<=MS_Data_in; rSEC<=SEC_Data_in; rMinu<=Minu_Data_in; end else

case(Key_Up) 1'b0: case(KEY) 3'b001: begin rEN=~rEN; Key_Up<=1'b1; end 3'b010: begin Key_Up<=1'b1; if(wr_addr==2'b11) wr_addr=2'b0; else begin rMS_Data[wr_addr]<=MS_Data_in; rSEC_Data[wr_addr]<=SEC_Data_in; rMinu_Data[wr_addr]<=Minu_Data_in; wr_addr<=wr_addr+1'b1; end end 3'b100: begin rEN=0; Key_Up<=1'b1; if(rd_addr==2'b11) rd_addr<=3'd0; else begin rMS<=rMS_Data[rd_addr]; rSEC<=rSEC_Data[rd_addr]; rMinu<=rMinu_Data[rd_addr]; rd_addr<=rd_addr+1'b1; end end

default: begin if(rEN) begin rMS<=MS_Data_in; rSEC<=SEC_Data_in; rMinu<=Minu_Data_in; end end endcase 1'b1: if( Count_MS == 10'd200 ) Key_Up <= 1'd0; else isCount <= 1'b1; endcase

assign MS_Data_out=rMS; assign SEC_Data_out=rSEC; assign Minu_Data_out=rMinu; assign Count_EN=rEN; assign LED[3]=rEN; assign LED[2]=Key_Up;

assign LED[1:0]=rd_addr[1:0]; endmodule

数码管译码模块

功能说明:

此模块用来实现对计数结果的显示,包括两个小模块:除法器,译码模块。 源码:

module convert (

CLK, RST, MS_Data, S_Data, M_Data, MS_One_SData, MS_Ten_SData, S_One_SData, S_Ten_SData, M_One_SData, M_Ten_SData

);

input CLK; input RST;

input [7:0]MS_Data; input [7:0]S_Data; input [7:0]M_Data;

output [7:0]MS_One_SData; output [7:0]MS_Ten_SData; output [7:0]S_One_SData; output [7:0]S_Ten_SData; output [7:0]M_One_SData; output [7:0]M_Ten_SData;

wire [3:0]MS_One_Data; wire [3:0]MS_Ten_Data; wire [3:0]S_One_Data; wire [3:0]S_Ten_Data; wire [3:0]M_One_Data; wire [3:0]M_Ten_Data;

encoder6 U1 ( .CLK(CLK), .RST(RST), .MS_One_Data(MS_One_Data), .MS_Ten_Data(MS_Ten_Data), .S_One_Data(S_One_Data), .S_Ten_Data(S_Ten_Data), .M_One_Data(M_One_Data), .M_Ten_Data(M_Ten_Data), .MS_One_SData(MS_One_SData), .MS_Ten_SData(MS_Ten_SData), .S_One_SData(S_One_SData), .S_Ten_SData(S_Ten_SData), .M_One_SData(M_One_SData), .M_Ten_SData(M_Ten_SData) ); div3 U2 (

.CLK(CLK), .RST(RST), .MS_Data(MS_Data), .S_Data(S_Data), .M_Data(M_Data), .MS_One_Data(MS_One_Data), .MS_Ten_Data(MS_Ten_Data), .S_One_Data(S_One_Data), .S_Ten_Data(S_Ten_Data), .M_One_Data(M_One_Data), .M_Ten_Data(M_Ten_Data), );

endmodule

除法器

功能说明:

此模块用来实现把技术结果的个位和十位分离 源代码: module div (

CLK, RST, Number_Data, Ten_Data, One_Data );

input CLK; input RST; input [7:0]Number_Data; output [3:0]Ten_Data; output [3:0]One_Data; /*********************************/ reg [3:0]rTen; reg [3:0]rOne; reg [3:0]cnt; reg [7:0]rem; reg i;

always @ ( posedge CLK or negedge RST )

if( !RST ) begin rTen <= 4'd0; rOne <= 4'd0; i<=1'b0; cnt<=4'd0; rem<=8'd0; end else case(i) 0: begin rem<=Number_Data; i=1'b1; cnt=4'd0; end 1: begin if(rem<4'd10) begin rTen<=cnt; rOne<=rem[3:0]; i=1'b0; end else begin cnt<=cnt+1; rem<=rem-4'd10; end end endcase /***********************************/ assign Ten_Data = rTen; assign One_Data = rOne; /***********************************/

Endmodule Testbench

`timescale 1 ps/ 1 ps module div_tb(); reg CLK;

.M_Ten_SData(M_Ten_SData), .S_One_SData(S_One_SData), .S_Ten_SData(S_Ten_SData), .DIG_Sig(SEL), .SEG_Sig(DIG) ); endmodule 下载验证

1. 管脚分配 NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \NET \

NET \NET \NET \NET \NET \2. 下载过程

点击IMPACT,对FPGA进行编程,程序下载完成后,数码管显示计时时间,按下存储按键,能存储此时的时间,按下回放按键,可以显示存储的时间,达到实验要求。

测试结果与结论

本实验采用Verilog编写源代码,模块划分精细,采用TOP-DOWN的设计流程,对各个模块给予仿真,最终下载验证,达到了预期的效果。

本文来源:https://www.bwwdw.com/article/7pud.html

Top