FPGA-07-50秒倒計時的實現(特權XILINX spartan-6開發板)
阿新 • • 發佈:2018-11-17
工具 ISE14.7
通過時間分頻在4位7段數碼管中顯示2個數字,給人眼一個錯覺是同時顯示出兩個數字。
實驗原理是輪流向各位數碼管送出字形碼和相應的位選訊號,利用數碼管閃爍的餘暉和人眼視覺的暫留作用,使人感覺像各位管同時在顯示
就像微控制器數碼管的思想一樣:這裡也要做相同的事情。
微控制器步驟如下:
動態顯示:
1)位選數碼管; 2)段選數碼管; 3)延時
dula=1;//段選 P0=table[i]; dula=0; P0=0xff; wela=1;//位選 P0=a; wela=0; delayms(500);//延時
這樣的程式碼實現流水顯示,如果延時時間夠短肉眼難以分辨;則可以實現幾位數據的同時顯示;
同理到FPGA中也是這樣,不過要考慮用不同的模組實現這個功能
EG 兩位數碼管顯示:
微控制器中延時用個delay就可以實現,但是這裡的延時要用一個計數器來模擬延時的狀態
1.0)段選選擇數碼管顯示的數值
1.1)因為這裡我程式碼中值用了4個位來顯示當前的資料(資料位寬為4)所以要在不同的時間選擇當前顯示的值
2)位選選擇數碼管的位數
3)延時(保證動態顯示肉眼分辨不出)
程式碼如下:
module seg(clk,ext_rst_n,TimeH,TimeL,dtube_cs_n,dtube_data ); input clk; //時鐘訊號25MHz input ext_rst_n; //復位訊號 input [3:0]TimeH; //兩位輸入高位 input [3:0]TimeL; //兩位輸入低位 output reg[1:0] dtube_cs_n; //段選資料位 output reg[6:0] dtube_data;//位選資料位 reg[3:0] display_num; //當前顯示資料 reg[15:0] div_cnt; //延時計數器計數位 initial div_cnt = 0;//賦初值為0 //延時計數器模組
[email protected] (posedge clk or negedge ext_rst_n) begin if(!ext_rst_n) div_cnt <= 8'd0; else if(div_cnt==16'd50000) div_cnt <= 8'd0; else div_cnt <= div_cnt+1'b1; end //顯示當前的資料模組 always @(posedge clk or negedge ext_rst_n) begin if(!ext_rst_n) display_num <= 4'h0; else if(div_cnt < 25000) display_num <= TimeH; else display_num <= TimeL; end //段選資料譯碼模組(共陰數碼管) always @(posedge clk or negedge ext_rst_n) begin if(!ext_rst_n) dtube_data <= 8'h00; else begin case(display_num) 4'h0: dtube_data <= 8'h3f; 4'h1: dtube_data <= 8'h06; 4'h2: dtube_data <= 8'h5b; 4'h3: dtube_data <= 8'h4f; 4'h4: dtube_data <= 8'h66; 4'h5: dtube_data <= 8'h6d; 4'h6: dtube_data <= 8'h7d; 4'h7: dtube_data <= 8'h07; 4'h8: dtube_data <= 8'h7f; 4'h9: dtube_data <= 8'h6f; default:dtube_data <= 8'h00; endcase end end //位選選譯模組 always @(posedge clk or negedge ext_rst_n) begin if(!ext_rst_n) dtube_cs_n <= 2'b11; else if(div_cnt < 20000) dtube_cs_n <= 2'b01; else dtube_cs_n <= 2'b10; end endmodule
數碼管顯示模組定義好了就要想如何實現倒計時的完成
這裡的設計思路是
頂層設計模組
分頻器模組 --> 計數器模組 -----> 數碼管顯示模組
輸入復位訊號 和系統時鐘
1)分頻器輸入25MHz輸出1Hz
2)IHz時鐘訊號傳給計數器模組用於計數
3)計數的值在數碼管顯示
輸出數碼管的段選和位選
和蜂鳴器(計時完成標誌位)
程式碼如下:
1,.TOP.v
module top(ext_clk_25m,ext_rst_n,beep,dtube_cs_n,dtube_data
);
//頂層控制模組
input ext_clk_25m; //時鐘訊號25MHz
input ext_rst_n; //復位訊號
output [1:0] dtube_cs_n; //段選資料位
output [6:0] dtube_data;//位選資料位
output beep; //計時完成標誌位
wire clk;//中間變數
wire [3:0] TimeL;
wire [3:0] TimeH;
//分頻25MHZ變為1HZ
div d1(
.ext_clk_25m(ext_clk_25m),
.ext_rst_n(ext_rst_n),
.mclk(clk)
);
//倒計時計數模組
counter c1(
.mclk(clk),
.ext_rst_n(ext_rst_n),
.TimeH(TimeH),
.TimeL(TimeL),
.beep(beep)
);
//數碼管顯示模組
seg s1(
.clk(ext_clk_25m),
.ext_rst_n(ext_rst_n),
.TimeH(TimeH),
.TimeL(TimeL),
.dtube_cs_n(dtube_cs_n),
.dtube_data(dtube_data)
);
endmodule
2.div.v
module div(ext_clk_25m,ext_rst_n,mclk
);
input ext_clk_25m;//輸入時鐘
input ext_rst_n; //復位埠
output reg mclk;//輸出1Hz
reg [23:0] cnt;//存放計數器的值
initial cnt = 0;
parameter TIME=24'd1250_0000;//時鐘25MHz
//分頻模組
//使得輸入時鐘為25MHz輸出時鐘為1Hz
[email protected](posedge ext_clk_25m or negedge ext_rst_n)
begin
if(!ext_rst_n)
begin
mclk <=1'b0;
cnt <=25'd0;
end
else if(cnt ==TIME-1'b1)
begin
mclk <=~mclk;
cnt <=1'b0;
end
else
cnt <=cnt + 1'b1;
end
endmodule
3.counter.v
module counter(mclk,ext_rst_n,TimeH,TimeL,beep
);
input mclk;//時鐘訊號
input ext_rst_n;//復位訊號
output reg [3:0]TimeH;//兩位數碼管顯示高位
output reg [3:0]TimeL;//兩位數碼管顯示低位
output beep; //計數完成位
assign beep =({TimeH,TimeL}==8'h00);//當計數為0時,蜂鳴器響
initial {TimeH,TimeL} = 8'h50; //計數器賦初值
//計數器模組
[email protected](posedge mclk or negedge ext_rst_n)
begin
if(!ext_rst_n)
{TimeH,TimeL} <= 8'h50;
else if({TimeH,TimeL}==8'h00)
{TimeH,TimeL} <={TimeH,TimeL};
else if(TimeL==4'h0)
begin
TimeH <=TimeH-1'b1;
TimeL <=4'h9;
end
else
begin
TimeH <=TimeH;
TimeL <=TimeL-1'b1;
end
end
endmodule
4.數碼管.v
上文已經貼出