赞
踩
目录
来分享第一个案例了!简易电子时钟的Verilog设计,电子时钟应该算是走嵌入式和FPGA开发的敲门砖了叭(也可能是流水灯)。本次设计实现的平台是Altera的DE2开发板。
一个简易的电子时钟应该包含以下功能:
在此基础上也还可以继续扩展功能,本次由于刚入门,便只实现了基本功能。
要正常计时,我们需要一个1Hz的信号。在Verilog中采用分频器对基准时钟进行分频,使用这个1Hz信号进行计数,便可以产生时分秒。再将时分秒用数码管显示出来,第一个功能成功实现;在第一个基础上,设置一个拨码开关,用以区分正常模式和调时模式。当电子时钟处于调时模式时,最低位数码管闪烁,按下增1按键时数字加1;按下移位按键时闪烁位向高位移动。当模式调回正常模式时,从修改后的时间开始计时。
综上,需要一个分频器、一个时间管理模块、需要六个数码管显示译码器。整体框图如下:
对于分频器这一ip,之后会出文详述,此处使用的是占空比50%的偶分频。数码管显示译码模块属于较为简单的模块,读者在看其Verilog代码时很容易便理解。
开门见山!先上整个完整能编译的Verilog代码!
- module simple_electronic_clock(clk,key_add,key_displace,switch_mode,hour_decode,min_decode,sec_decode);
- input clk;//基准时钟50MHz
- input key_add;//增一按键
- input key_displace;//移位按键
- input switch_mode;//模式开关
- output [13:0] hour_decode;//小时译码
- output [13:0] min_decode;//分钟译码
- output [13:0] sec_decode;//秒译码
-
- wire clk_1Hz,clk_2Hz;//分频后的1Hz、2Hz信号
- wire [1:0] mode_cnt;//调时的闪烁位
- wire [7:0] hour,min,sec;//时,分,秒
-
- divider(clk_2Hz,clk_1Hz,clk);//分频器
- time_management(clk_1Hz,switch_mode,key_add,key_displace,hour,min,sec,mode_cnt);//时间管理模块
- digital_tube_decode(clk_2Hz,mode_cnt,hour,min,sec,hour_decode,min_decode,sec_decode);//数码管显示译码模块
- endmodule
-
- module divider(clk_2Hz,clk_1Hz,clk);//分频器
- output reg clk_1Hz,clk_2Hz;
- input clk;
- reg [24:0] count,count2;//内部计数单元
-
-
- //count计满24999999时信号反向,产生1Hz信号
- always@(posedge clk) begin
- if(count==25'd24999999)
- begin
- count<=25'b0;
- clk_1Hz<=~clk_1Hz;
- end
- else
- count<=count+1'b1;
- end
- //count2计满12499999时信号反向,产生2Hz信号
- always@(posedge clk) begin
- if(count==25'd12499999)
- begin
- count2<=25'b0;
- clk_2Hz<=~clk_2Hz;
- end
- else
- count2<=count2+1'b1;
- end
- endmodule
-
-
- module time_management(clk_1Hz,switch_mode,key_add,key_displace,hour,min,sec,mode_cnt);//时间管理模块
- input clk_1Hz,switch_mode,key_add,key_displace;
- output reg [7:0] hour,min,sec;
- output reg [1:0] mode_cnt;//调时的闪烁位标志
-
- //时间计时&调时
- always @(posedge clk_1Hz) begin
- case (switch_mode)
- 1'b0:sec[3:0] <= sec[3:0] + 1'b1;//正常模式计时
- 1'b1:begin //调时模式
- if(key_add) begin
- case (mode_cnt)
- 2'b00:sec[3:0] <= sec[3:0] + 1'b1;//秒时间加一
- 2'b01:min[3:0] <= min[3:0] + 1'b1;//分时间加一
- 2'b10:hour[3:0] <= hour[3:0] + 1'b1;//时时间加一
- default:;
- endcase
- end
- end
- default:;
- endcase
- //以下为进位条件判断
- if(sec[3:0] == 4'd10) begin
- sec[3:0] <= 4'b0;
- sec[7:4] <= sec[7:4] + 1'b1;
- end
- if(sec[7:4] == 4'd6) begin
- sec[7:4] <= 4'b0;
- min[3:0] <= min[3:0] + 1'b1;
- end
-
- if(min[3:0] == 4'd10) begin
- min[3:0] <= 4'b0;
- min[7:4] <= min[7:4] + 1'b1;
- end
- if(min[7:4] == 4'd6) begin
- min[7:4] <= 4'b0;
- hour[3:0] <= hour[3:0] + 1'b1;
- end
-
- if(hour[3:0] == 4'd10) begin
- hour[3:0] <= 4'b0;
- hour[7:4] <= hour[7:4] + 1'b1;
- end
- if(hour[3:0] == 4'd4 && hour[7:4] == 4'd2) begin
- hour[3:0] <= 4'b0;
- hour[7:4] <= 4'b0;
- end
- end
-
- //移位按键触发移位
- always @(posedge key_displace) begin
- if(switch_mode) begin
- if(mode_cnt == 2'b10) mode_cnt <= 2'b0;
- else mode_cnt <= mode_cnt + 1'b1;
- end
- end
- endmodule
-
- module digital_tube_decode(clk_2Hz,mode_cnt,hour,min,sec,hour_decode,min_decode,sec_decode);
- input clk_2Hz;
- input [1:0] mode_cnt;
- input [7:0] hour,min,sec;
- output reg [13:0] hour_decode,min_decode,sec_decode;
- reg flag;
- //闪烁产生
- always @(posedge clk_2Hz) begin
- flag <= ~flag;
- end
- //显示译码
- always @(posedge clk_2Hz) begin
- case (mode_cnt) //根据闪烁位标志,使得闪烁位数字闪烁
- 2'b00:begin
- hour_decode[6:0] <= decode(hour[3:0]);
- hour_decode[13:7] <= decode(hour[7:4]);
- min_decode[6:0] <= decode(min[3:0]);
- min_decode[13:7] <= decode(min[3:0]);
- if(flag) begin
- sec_decode[6:0] <= decode(sec[3:0]);
- sec_decode[13:7] <= decode(sec[3:0]);
- end
- else begin //7'b1111111为数码管全灭,下面同理
- sec_decode[6:0] <= 7'b1111111;
- sec_decode[13:7] <= 7'b1111111;
- end
- end
- 2'b01:begin
- hour_decode[6:0] <= decode(hour[3:0]);
- hour_decode[13:7] <= decode(hour[7:4]);
- sec_decode[6:0] <= decode(sec[3:0]);
- sec_decode[13:7] <= decode(sec[7:4]);
- if(flag) begin
- min_decode[6:0] <= decode(min[3:0]);
- min_decode[13:7] <= decode(min[7:4]);
- end
- else begin
- min_decode[6:0] <= 7'b1111111;
- min_decode[13:7] <= 7'b1111111;
- end
- end
- 2'b10:begin
- sec_decode[6:0] <= decode(sec[3:0]);
- sec_decode[13:7] <= decode(sec[7:4]);
- min_decode[6:0] <= decode(min[3:0]);
- min_decode[13:7] <= decode(min[7:4]);
- if(flag) begin
- hour_decode[6:0] <= decode(hour[3:0]);
- hour_decode[13:7] <= decode(hour[7:4]);
- end
- else begin
- hour_decode[6:0] <= 7'b1111111;
- hour_decode[13:7] <= 7'b1111111;
- end
- end
- default:;
- endcase
- end
-
- //译码函数,便于重复调用
- function [6:0] decode;
- input [3:0] num;
- begin
- case (num)
- 4'd0:decode=7'b1000000;
- 4'd1:decode=7'b1111001;
- 4'd2:decode=7'b0100100;
- 4'd3:decode=7'b0110000;
- 4'd4:decode=7'b0011001;
- 4'd5:decode=7'b0010010;
- 4'd6:decode=7'b0000010;
- 4'd7:decode=7'b1111000;
- 4'd8:decode=7'b0000000;
- 4'd9:decode=7'b0010000;
- default: decode=7'b1111111;
- endcase
- end
- endfunction
-
- endmodule
仿真就等我之后有空再弄叭(dog)。
这篇文是我第一个Verilog案例,主要讲解设计思路,当然还有更好的电子时钟例码,我这个算是无脑编写QaQ
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。