基于FPGA的简易数字秒表设计

一,设计原理
因Verilog HDL编写的源程序是并行执行的,故分析原理时,分别分析各个层次模块之间的接口关系。
(1)顶层模块与计数器计数模块:外部50Mhz时钟和复位信号传递给顶层模块,顶层模块通过模块例化将50Mhz的时钟、复位信号及3位的key_value变量值分别传递给计数器计数模块中的clk、rst_n和key_control,在计数器计数模块中经分频后产生周期为0.01秒的方波并在rst_n1和key_control3’b011时开始计数;在key_control3’b101时计数值清零;在key_control3’b110时暂停,在并将计数值存于24位的rNum变量,然后将24位的rNum变量里的值传递给24位的Number_Sig变量,最后通过Number_Sig变量将计数值返回至顶层模块中的24位的Number_Sig变量中暂存。
(2)顶层模块与按键检测模块:外部三个独立按键、50Mhz的时钟及复位信号传递给顶层模块,通过模块例化的方式将三个独立按键值、时钟和复位信号分别传递给按键检测模块中的三位的key_in变量、clk和rst_n变量。在按键检测模块中将时钟信号分频至周期为20毫秒的方波,利用按键在20毫秒里电平的变化检测是否有按键按下,即:wire [2:0]flag_key = key_scan_r[2:0] & (~key_scan[2:0]);此语句检测按键是否按下。再通过flag_key里的值判断哪个按键按下,再将对应的按键值赋值给三位的temp变量,最后将temp里的值赋给三位的key_out变量返回至顶层模块中的三位的key_value变量。
(3)顶层模块与数码管接口模块:顶层模块利用模块例化的方式将50Mhz时钟、复位信号、Number_Sig变量值分别传递给数码管接口模块中的一位CLK、RSTn和24位的Number_Sig变量。数码管接口模块最终将八位的SMG_Data和六位的Scan_Sig变量返回给顶层模块中八位的SMG_Data和六位的Scan_Sig变量,顶层最后将八位的SMG_Data和六位的Scan_Sig变量里的值经译码电路输送至六位共阳数码管显示。
(4)数码管接口模块与计数值分配模块:数码管接口模块将从顶层模块传递过来的Number_Sig变量值、50Mhz时钟和复位信号分别传给计数值分配模块里的24位的Number_Sig变量、一位的CLK、RSTn变量。在计数值分配模块中,将时钟信号经分频后产生周期为1毫秒的方波,将24位的Number_Sig变量里的值在分频后的时序下从高到低四位四位的取出赋值给四位rNumber,最后将rNumber里的值赋值给Number_Data返回至数码管接口模块里的四位的Number_Data变量。
(5)数码管接口模块与段选模块:将50Mhz、复位信号以及Number_Data变量值传递给段选模块中的一位的CLK、RSTn和四位Number_Data变量。在段选模块里,利用parameter语句定义数码管显示0-9时对应的八位段选值,例如:parameter _0 = 8’b1100_0000;在50Mhz时钟产生的时序下,利用case语句将Number_Data变量值进行比较,若为零则八位的rSMG变量被赋值为数码管显示零的八位段选值。最后将rSMG赋值给八位的SMG_Data变量返回至上层模块里的SMG_Data变量。
(6)数码管接口模块与位选模块:将50Mhz、复位信号传递给位选模块中的一位的CLK、RSTn,在位选模块中,将时钟信号分频至周期为1毫秒的方波,在此时序下,从低到高依次选通一位数码管,即将一个低电平和五个高电平赋值给六位的rScan变量。最后将rScan变量赋值给六位Scan_Sig变量返回至上层模块里的Scan_Sig 变量。

二,程序源码

module key_test  
(
	clk,
	rst_n,				
	key_in,           
	key_out           
);
//端口信号					
input  clk,rst_n;  
input  [2:0] key_in;
output [2:0] key_out;

//定义寄存器
reg [19:0] count;
reg [2:0] key_scan; 

//每次40ms判断一次
always @(posedge clk or negedge rst_n)    
begin
   if(!rst_n)                
      count <= 20'd0;       
   else
      begin
         if(count ==20'd999_999)   
            begin
               count <= 20'b0;
               key_scan <= key_in; 
            end
         else
            count <= count + 20'b1; 
     end
end

reg [2:0] key_scan_r;   

always @(posedge clk)
begin
    key_scan_r <= key_scan;       //将输入信号打一拍,用于捕获下降沿
end
    
wire [2:0] flag_key = key_scan_r[2:0] & (~key_scan[2:0]);  //捕获下降沿

reg [2:0] temp;             //每个按键按下所得到的值

always @ (posedge clk or negedge rst_n)  //判断哪个按键按下
begin
    if (!rst_n)               					
        begin temp<= 3'b111;end  
    else
         begin            
             if(flag_key[0])
             temp <= 3'b110;  		
             else if(flag_key[1])
             temp<= 3'b101;   
             else if(flag_key[2])
             temp<= 3'b011;   
             else ;
         end
end

assign key_out = temp;
endmodule

module smg_control_module
(
    input CLK,
	 input RSTn,
	 input [23:0]Number_Sig,
     
	 output [3:0]Number_Data
);
parameter T1MS = 16'd49999;            //1ms计数 
reg [15:0]C1; 
always @ ( posedge CLK or negedge RSTn )
begin
	if( !RSTn )
		C1 <= 16'd0;
	else if( C1 == T1MS )
		C1 <= 16'd0;
	else
		C1 <= C1 + 1'b1;
end	  
reg [3:0]i;reg [3:0]rNumber;
always @ ( posedge CLK or negedge RSTn )
begin
	if( !RSTn )
		begin
			i <= 4'd0;
			rNumber <= 4'd0;
		end
	else 
		case( i )
			0:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rNumber <= Number_Sig[23:20];//十万位数码管显示           
			1:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rNumber <= Number_Sig[19:16];//万位数码管显示
			2:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rNumber <= Number_Sig[15:12]; //千位数码管显示
			3:
			   if( C1 == T1MS ) i <= i + 1'b1;
				else rNumber <= Number_Sig[11:8]; //百位数码管显示
			4:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rNumber <= Number_Sig[7:4]; //十位数码管显示
			5:
				if( C1 == T1MS ) i <= 4'd0;
				else rNumber <= Number_Sig[3:0]; //低位数码管显示
		endcase end				
assign Number_Data = rNumber;

endmodule

module seg_led_key
(
    input CLK,                      
	 input RSTn,                    
	 output [7:0]SMG_Data,
	 output [5:0]Scan_Sig,         
	 input [2:0]button			
);

wire [23:0]Number_Sig;
wire [2:0]key_value;
	 
key_test  u1
(
	.clk(CLK),              				
	.rst_n(RSTn),
	.key_in(button),
	.key_out(key_value)
);

 demo_control_module U1						
(
	     .CLK( CLK ),
		  .RSTn( RSTn ),
		  .Number_Sig( Number_Sig ),		
		  .key_control(key_value)			
);


smg_interface U2								
(
	.CLK( CLK ),							  
	.RSTn( RSTn ),
	.Number_Sig( Number_Sig ), 			 
	.SMG_Data( SMG_Data ),     			// 
	.Scan_Sig( Scan_Sig )      			// 
);

endmodule
// 编码模块: 十进制数 -> 7段数码管 
module smg_encode_module
(
	 input CLK,
	 input RSTn,
	 input [3:0]Number_Data,
	 output [7:0]SMG_Data,
     input flag
);

//数字码
parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, 
          _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010, 
		    _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,
		    _9 = 8'b1001_0000;

//
reg [7:0]rSMG;

always @ ( posedge CLK or negedge RSTn )
begin	
     if(!RSTn) 
				rSMG <= 8'b1111_1111;	
     else    
			case( Number_Data )
				4'd0 : rSMG <= _0;	
				4'd1 : rSMG <= _1;
				4'd2 : rSMG <= _2;	
				4'd3 : rSMG <= _3;	
				4'd4 : rSMG <= _4;	
				4'd5 : rSMG <= _5;		
				4'd6 : rSMG <= _6;		
				4'd7 : rSMG <= _7;			
				4'd8 : rSMG <= _8;	
				4'd9 : rSMG <= _9;			
			endcase  
end 
assign SMG_Data = flag ? rSMG & 8'b0111_1111 : rSMG;
endmodule

module smg_interface
(
    input CLK,
	 input RSTn,               
	 input [23:0]Number_Sig,
	 output [7:0]SMG_Data,		
	 output [5:0]Scan_Sig		
);
 
wire [3:0]Number_Data;
wire flag;
	 
smg_control_module U1            
(
	.CLK( CLK ),						
	.RSTn( RSTn ),						
	.Number_Sig( Number_Sig ),   
	.Number_Data( Number_Data )   
    
);
 
smg_encode_module U2
(
	.CLK( CLK ),
	.RSTn( RSTn ),
	.Number_Data(Number_Data),    
	.SMG_Data( SMG_Data ),
    .flag (flag)
);

smg_scan_module U3					
(
	.CLK( CLK ),
	.RSTn( RSTn ),
	.Scan_Sig( Scan_Sig ),
    .flag (flag)
);

endmodule

//     数码管扫描模块          //
module smg_scan_module
(
    input CLK, 
	 input RSTn, 
     
	 output [5:0]Scan_Sig,
     output reg flag
);
parameter T1MS = 16'd49999;
reg [15:0]C1;
reg [3:0]i;
reg [5:0]rScan;

always @ ( posedge CLK or negedge RSTn )
begin
if( !RSTn )
    C1 <= 16'd0;
else if( C1 == T1MS )
    C1 <= 16'd0;
else
    C1 <= C1 + 1'b1;
end 
 
always @ ( posedge CLK or negedge RSTn )
begin
	if( !RSTn )begin
              flag <= 1'b0;
			  i <=   4'd0;
		      rScan <= 6'b100_000;
              end
	else 
    begin
                flag <= 1'b0;
		case( i )
            
			0:  
				if( C1 == T1MS ) i <= i + 1'b1;
				else rScan <= 6'b011_111;                      
//第一个数码选通 
			1:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rScan <= 6'b101_111;                      
//第二个数码选通 
			2:
				if( C1 == T1MS ) i <= i + 1'b1;
				else rScan <= 6'b110_111;                      
//第三个数码选通 
			3:
				if( C1 == T1MS ) i <= i + 1'b1;
				else 
                begin
                rScan <= 6'b111_011;  
                flag <= 1'b1;
                end 
//第四个数码选通
			4:
				if( C1 == T1MS ) i <= i + 1'b1;
				else
                    rScan <= 6'b111_101;
//第五个数码选通 
			5:
				if( C1 == T1MS ) i <= 4'd0;
				else rScan <= 6'b111_110;                      
//第六个数码选通
		endcase
       end
       
end				
assign Scan_Sig = rScan;

endmodule


发布了26 篇原创文章 · 获赞 23 · 访问量 5744

猜你喜欢

转载自blog.csdn.net/liuxianfei0810/article/details/105335710