1. 程式人生 > >基於FPGA的簡易數字時鐘

基於FPGA的簡易數字時鐘

eight 賦值 else if iss 基於 pga 博文 移位 sel


基於FPGA的可顯示數字時鐘,設計思路為自底向上,包含三個子模塊:時鐘模塊,進制轉換模塊。led顯示模塊。所用到的FPGA晶振頻率為50Mhz,首先利用它得到1hz的時鐘然後然後得到時鐘模塊。把時鐘模塊輸出的時、分、秒輸入到進制轉換模塊後得到十進制的值再輸入到led顯示模塊,該project已經在FPGA開發板上親測可用。

下圖為模塊示意圖(實際project中並沒有採用原理圖的輸入方法。這裏僅作示意)。

技術分享
















以下分模塊說明:

clk1: 時鐘模塊,設計思路為首先依據50M晶振得到1hz的時鐘,然後通過時分秒的關系得到時鐘模塊(詳細見代碼)。

輸入 clk:系統時鐘信號 50Mhz rst_n:低電平異步復位

輸出 sec: 8bit位寬的秒位 min: 8bit位寬的分位 hour 8bit位寬的時位

bin_dec1: 進制轉換模塊,設計思路全然依照之前的博文《利用verilog將二進制碼轉換為十進制BCD碼 》,代碼稍作改動,去掉兩個用不到的輸出。

輸入 clk:系統時鐘信號 50Mhz rst_n:低電平異步復位 bin: 8bit位寬的輸入待轉換二進制數

輸出 one: 十進制數的個位 ten: 十進制數的十位 hun: 十進制數的百位,這裏用不到所以空置了。

led: 數碼管顯示模塊,八段數碼管在一定頻率下切換賦值,每個時鐘對一個數碼管單獨賦值並顯示,切換頻率大於一定值後。看起來像8位數碼管同一時候顯示(詳細設計見代碼)。

輸入 clk: 系統時鐘信號50Mhz

sec0,sec1,min0,min1。hour0。hour1:

4bit位寬的值。分代表時鐘秒、分、時的個位和十位。

輸出 sel: 8bit 數碼管位選信號

data:8bit數碼管譯碼顯示的值


以下給出code:

clk1:

module clock1(sec,min,hour,clk,rst_n
);
input clk,rst_n;
output [7:0] sec,min;
output [7:0] hour;
reg [7:0] sec=0;
reg [7:0] min=0;
reg [7:0] hour=0;
reg clk_div;
reg [32:0] cnt;

//////////////////////////////////////// 分頻部分 50MHz - 1Hz
always @ ( posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 0;
clk_div <= 0;
end
else begin
if ( cnt < 25000000 - 1 )
begin
clk_div <= 0;
cnt <= cnt + 1;
end
else if ( cnt < 50000000 - 1 )
begin
clk_div <= 1;
cnt <= cnt + 1 ;
end
else
cnt <=0 ;
end
end
///////////////////////////////////////// 時鐘部分
always @ ( posedge clk_div or negedge rst_n )
begin
if(!rst_n)
sec <= 0;
else begin
if ( sec == 59 )
sec <= 0 ;
else
sec <= sec + 1 ;
end
end
always @ ( posedge clk_div or negedge rst_n)
begin
if(!rst_n)
min <= 0;
else begin
if ( sec == 59 )
begin
if (min ==59 )
min <= 0;
else
min <= min + 1 ;
end
end
end

always @ ( posedge clk_div or negedge rst_n)
begin
if(!rst_n)
hour <= 0;
else begin
if ( sec == 59 && min ==59 )
begin
if (hour == 23)
hour <= 0 ;
else
hour <= hour + 1;
end
end
end

endmodule


bin_dec1
module bin_dec1(clk,bin,rst_n,one,ten,hun
);
input [7:0] bin;
input clk,rst_n;
output [3:0] one,ten;
output [1:0] hun;
reg [3:0] one,ten;
reg [1:0] hun;
reg [3:0] count;
reg [17:0]shift_reg=18‘b000000000000000000;
////////////////////// 計數部分 ////////////////////////
always @ ( posedge clk or negedge rst_n )
begin
if( !rst_n )
count<=0;
else if (count==9)
count<=0;
else
count<=count+1;
end
////////////////////// 二進制轉換為十進制 /////////////////
always @ (posedge clk or negedge rst_n )
begin
if (!rst_n)
shift_reg=0;
else if (count==0)
shift_reg={10‘b0000000000,bin};
else if ( count<=8) //實現8次移位操作
begin
if(shift_reg[11:8]>=5) //推斷個位是否>5。假設是則+3
begin
if(shift_reg[15:12]>=5) //推斷十位是否>5。假設是則+3
begin
shift_reg[15:12]=shift_reg[15:12]+2‘b11;
shift_reg[11:8]=shift_reg[11:8]+2‘b11;
shift_reg=shift_reg<<1; //對個位和十位操作結束後,總體左移
end
else
begin
shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8]+2‘b11;
shift_reg=shift_reg<<1;
end
end

else
begin
if(shift_reg[15:12]>=5)
begin
shift_reg[15:12]=shift_reg[15:12]+2‘b11;
shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
end
else
begin
shift_reg[15:12]=shift_reg[15:12];
shift_reg[11:8]=shift_reg[11:8];
shift_reg=shift_reg<<1;
end
end

end
end
/////////////////輸出賦值//////////////////////////
always @ ( posedge clk or negedge rst_n )
begin
if ( !rst_n )
begin
one<=0;
ten<=0;
hun<=0;
end
endmodule


led:

module led(clk,sec0,sec1,min0,min1,hour0,hour1,sel,data
);
input clk;
input [3:0] sec0,sec1,min0,min1,hour0,hour1;
output reg [7:0] data;
output reg [7:0] sel;
reg [3:0] data_dis=0;
reg [20:0] m=0;

always @ ( posedge clk )
begin
m<=m+1;
end


always@( posedge clk)
begin
case(m[16:14])
0: begin
data_dis<=4‘b0000;
sel<=8‘b1111_1110;
end
1: begin
data_dis<=4‘b0000;
sel<=8‘b1111_1101;
end
2: begin
data_dis<=hour1;
sel<=8‘b1111_1011;
end
3: begin
data_dis<=hour0;
sel<=8‘b1111_0111;
end
4: begin
data_dis<=min1;
sel<=8‘b1110_1111;
end
5: begin
data_dis<=min0;
sel<=8‘b1101_1111;
end
6: begin
data_dis<=sec1;
sel<=8‘b1011_1111;
end
7: begin
data_dis<=sec0;
sel<=8‘b0111_1111;
end
default:begin
data<=8‘bz;
sel<=8‘bz;
end
endcase

end


always @(data_dis)
begin
case(data_dis)//七段譯碼
4‘h0:data = 8‘hc0;//顯示0
4‘h1:data = 8‘hf9;//顯示1
4‘h2:data = 8‘ha4;//顯示2
4‘h3:data = 8‘hb0;//顯示3
4‘h4:data = 8‘h99;//顯示4
4‘h5:data = 8‘h92;//顯示5
4‘h6:data = 8‘h82;//顯示6
4‘h7:data = 8‘hf8;//顯示7
4‘h8:data = 8‘h80;//顯示8
4‘h9:data = 8‘h90;//顯示9
default data = 8‘hxx;
endcase
end

endmodule

頂層例化模塊:

top

module top(clk,rst_n,sel,data
);
input clk,rst_n;
output [7:0] sel,data;
wire [7:0] sec,min,hour;
wire [3:0] one1,ten1,one2,ten2,one3,ten3;

clock1 clock(
.clk(clk),
.rst_n(rst_n),
.sec(sec),
.min(min),
.hour(hour)
);

bin_dec1 bin_dec1(
.clk(clk),
.rst_n(rst_n),
.bin(sec),
.one(one1),
.ten(ten1)
);

bin_dec1 bin_dec2(
.clk(clk),
.rst_n(rst_n),
.bin(min),
.one(one2),
.ten(ten2)
);

bin_dec1 bin_dec3(
.clk(clk),
.rst_n(rst_n),
.bin(hour),
.one(one3),
.ten(ten3)
);

led led(
.clk(clk),
.sec0(one1),
.sec1(ten1),
.min0(one2),
.min1(ten2),
.hour0(one3),
.hour1(ten3),
.sel(sel),
.data(data)
);

endmodule





基於FPGA的簡易數字時鐘