一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FPGA的數(shù)碼管動(dòng)態(tài)顯示

CHANBAEK ? 來源:小小研究生 ? 作者:xxyjs2020 ? 2023-08-15 15:59 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

設(shè)計(jì)規(guī)劃

8個(gè)數(shù)碼管顯示從十進(jìn)制0開始計(jì)數(shù),每0.1s加1,一直加到十進(jìn)制數(shù)9999_9999,然后回到0重新計(jì)數(shù)。

理論基礎(chǔ)

上一節(jié)介紹了靜態(tài)顯示,每個(gè)數(shù)碼管顯示的數(shù)字是一樣的,但是實(shí)際生活中遠(yuǎn)遠(yuǎn)不能滿足需求。因此我們要學(xué)習(xí)顯示不同字符的數(shù)碼管驅(qū)動(dòng)方式-動(dòng)態(tài)驅(qū)動(dòng)。靜態(tài)驅(qū)動(dòng)的原理是位選信號(hào)為1111_1111,即8個(gè)數(shù)碼管同時(shí)選中,再用段選信號(hào)讓數(shù)碼管顯示理想數(shù)值,那么8個(gè)數(shù)碼管的字符就一樣。那么如果我們每次只選中一個(gè)數(shù)碼管,再利用段選信號(hào)讓它顯示理想數(shù)值,就可以顯示不同數(shù)值了。由于視覺暫留以及數(shù)碼管的余暉效應(yīng) 即使數(shù)碼管不是同時(shí)點(diǎn)亮,我們?cè)谝曈X效果上看到的也是同時(shí)點(diǎn)亮。(視覺暫留:視覺影像不會(huì)立即消失,動(dòng)畫就是利用這個(gè)原理,當(dāng)一秒內(nèi)幀數(shù)達(dá)到24就會(huì)感覺比較流暢。余暉效應(yīng):停止供電發(fā)光二極管亮度會(huì)維持一段時(shí)間。)實(shí)驗(yàn)證明,掃描間隔為1ms,即一秒點(diǎn)亮1000次,不會(huì)有閃爍感。那么我們只需要第1ms點(diǎn)亮第一個(gè)數(shù)碼管,第2ms點(diǎn)亮第二個(gè)數(shù)碼管…

BCD碼:2-10進(jìn)制碼,將1位十進(jìn)制數(shù)和4位二進(jìn)制數(shù)對(duì)應(yīng)的碼。8421碼比較常見,第0位權(quán)重為1,第1位權(quán)重為2,第三位權(quán)重為4,第4位權(quán)重為8,0對(duì)應(yīng)0000,1對(duì)應(yīng)0001,...,9對(duì)應(yīng)1001。那么例如一個(gè)二進(jìn)制數(shù)10010,對(duì)應(yīng)十進(jìn)制是18,對(duì)應(yīng)BCD碼是0001_1000。

編寫代碼

圖片

通過系統(tǒng)框圖可以看出,分為6個(gè)模塊:數(shù)據(jù)生成模塊,二進(jìn)制轉(zhuǎn)BCD模塊,數(shù)碼管動(dòng)態(tài)顯示驅(qū)動(dòng)模塊,74HC595模塊,數(shù)碼管動(dòng)態(tài)顯示模塊,頂層模塊。

1、數(shù)據(jù)生成模塊data_gen

應(yīng)該具有輸入:時(shí)鐘和復(fù)位,輸出:數(shù)據(jù)data和使能seg_en。中間信號(hào)有100ms計(jì)數(shù)器cnt_100ms,標(biāo)志位cnt_flag。

module data_gen
#(
parameter CNT_MAX = 23'd4999_999, //100ms計(jì)數(shù)值
parameter DATA_MAX= 27'd9999_9999 //顯示的最大值
)
(
input wire sys_clk , //系統(tǒng)時(shí)鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號(hào),低電平有效
output reg [26:0] data , //數(shù)碼管要顯示的值
output reg seg_en //數(shù)碼管使能信號(hào),高電平有效
);


//reg define
reg [22:0] cnt_100ms ; // 100ms計(jì)數(shù)器
reg cnt_flag ; //100ms標(biāo)志信號(hào)


 //cnt_100ms:用50MHz時(shí)鐘從0到4999_999計(jì)數(shù)即為100ms
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_100ms <= 23'd0;
 else if(cnt_100ms == CNT_MAX)
 cnt_100ms <= 23'd0;
 else
 cnt_100ms <= cnt_100ms + 1'b1;


 //cnt_flag:每100ms產(chǎn)生一個(gè)標(biāo)志信號(hào)
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_flag <= 1'b0;
 else if(cnt_100ms == CNT_MAX - 1'b1)
 cnt_flag <= 1'b1;
 else
 cnt_flag <= 1'b0;


 //數(shù)碼管顯示的數(shù)據(jù):0-9999_9999
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data <= 27'd0;
 else if((data == DATA_MAX) && (cnt_flag == 1'b1))
 data <= 27'd0;
 else if(cnt_flag == 1'b1)
 data <= data + 1'b1;
 else
 data <= data;


 //數(shù)碼管使能信號(hào)給高即可
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 seg_en <= 1'b0;
 else
 seg_en <= 1'b1;


 endmodule

參數(shù)定義:首先確定計(jì)數(shù)和顯示的最大值,計(jì)數(shù)100ms,用50MHz的時(shí)鐘需要從0記到4999_999,顯示的最大值是999_999,前者是23位,后者是27位。

cnt_100ms:復(fù)位有效和記滿時(shí)歸零,其他情況+1

cnt_flag:復(fù)位有效時(shí)歸0,計(jì)滿時(shí)拉高,其他情況都是保持低電平

data:復(fù)位有效時(shí)歸0,數(shù)據(jù)達(dá)到最大值且標(biāo)志位拉高時(shí)+1(數(shù)據(jù)要在999_999保持0.1ms,如果計(jì)滿就+1就只能維持一個(gè)時(shí)鐘周期,這就是flag的意義),其他情況保持

seg_en:復(fù)位有效時(shí)歸0,其他情況都是高電平有效。

2、BCD模塊bcd_8421

輸入是時(shí)鐘、復(fù)位和數(shù)據(jù)data,data是2進(jìn)制數(shù),要先轉(zhuǎn)換成10進(jìn)制,再將10進(jìn)制的每一位轉(zhuǎn)換成BCD碼,才能使每一個(gè)數(shù)碼管顯示對(duì)應(yīng)的字符。我們看二進(jìn)制碼如何變?yōu)锽CD碼。輸出是8個(gè)數(shù)碼管對(duì)應(yīng)8位,每位轉(zhuǎn)換BCD碼是4位。輸出是:個(gè)位,十位,百位,千位,萬位,十萬位,百萬位,千萬位。中間信號(hào)是移位判斷計(jì)數(shù)器cnt_shift,移位判斷數(shù)據(jù)寄存器data_shift,移位判斷標(biāo)志信號(hào)shift_flag。

圖片

以十進(jìn)制數(shù)234為例,二進(jìn)制是1110_1010,BCD碼應(yīng)該是0010_0011_1000,那么先進(jìn)行補(bǔ)0操作,輸入的二進(jìn)制碼不足12位,在高位補(bǔ)0。再將二進(jìn)制碼的最高位作為BCD的最低位進(jìn)行移位,并判斷每一個(gè)BCD碼其對(duì)應(yīng)的十進(jìn)制數(shù)是否大于4,如果大于4就對(duì)BCD碼做加3操作,若小于等于4就讓其值保持不變。然后繼續(xù)移位,每次移位后都要進(jìn)行判斷。

module bcd_8421(
input wire sys_clk , //系統(tǒng)時(shí)鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號(hào),低電平有效
input wire [26:0] data , //輸入需要轉(zhuǎn)換的數(shù)據(jù)
output reg [3:0] unit , //個(gè)位BCD碼
output reg [3:0] ten , //十位BCD碼
output reg [3:0] hun , //百位BCD碼
output reg [3:0] tho , //千位BCD碼
output reg [3:0] t_tho , //萬位BCD碼
output reg [3:0] h_hun , //十萬位BCD碼
output reg [3:0] t_hun ,  //百萬位BCD碼
output reg [3:0] h_tho //千萬位BCD碼 
);


//reg define
reg [4:0] cnt_shift ;  //移位判斷計(jì)數(shù)器
 reg [58:0] data_shift ; //移位判斷數(shù)據(jù)寄存器
 reg shift_flag ; //移位判斷標(biāo)志信號(hào)




 //cnt_shift:從0到28循環(huán)計(jì)數(shù)
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt_shift <= 5'd0;
 else if((cnt_shift == 5'd28) && (shift_flag == 1'b1))
 cnt_shift <= 5'd0;
 else if(shift_flag == 1'b1)
 cnt_shift <= cnt_shift + 1'b1;
 else
 cnt_shift <= cnt_shift;


 //data_shift:計(jì)數(shù)器為0時(shí)賦初值,計(jì)數(shù)器為1~27時(shí)進(jìn)行移位判斷操作
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data_shift <= 59'b0;
 else if(cnt_shift == 5'd0)
 data_shift <= {32'b0,data};
 else if((cnt_shift <= 27) && (shift_flag == 1'b0))
 begin
 data_shift[30:27] <= (data_shift[30:27] > 4) ?
 (data_shift[30:27] + 2'd3) : (data_shift[30:27]);
 data_shift[34:31] <= (data_shift[34:31] > 4) ?
 (data_shift[34:31] + 2'd3) : (data_shift[34:31]);
 data_shift[38:35] <= (data_shift[38:35] > 4) ?
 (data_shift[38:35] + 2'd3) : (data_shift[38:35]);
 data_shift[42:39] <= (data_shift[42:39] > 4) ?
 (data_shift[42:39] + 2'd3) : (data_shift[42:39]);
 data_shift[46:43] <= (data_shift[46:43] > 4) ?
 (data_shift[46:43] + 2'd3) : (data_shift[46:43]);
  data_shift[50:47] <= (data_shift[50:47] > 4) ?
 (data_shift[50:47] + 2'd3) : (data_shift[50:47]);
  data_shift[54:51] <= (data_shift[54:51] > 4) ?
 (data_shift[54:51] + 2'd3) : (data_shift[54:51]);
  data_shift[58:55] <= (data_shift[58:55] > 4) ?
 (data_shift[58:55] + 2'd3) : (data_shift[58:55]);
 end
 else if((cnt_shift <= 27) && (shift_flag == 1'b1))
 data_shift <= data_shift < < 1;
 else
 data_shift <= data_shift;


 //shift_flag:移位判斷標(biāo)志信號(hào),用于控制移位判斷的先后順序
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 shift_flag <= 1'b0;
 else
 shift_flag <= ~shift_flag;


 //當(dāng)計(jì)數(shù)器等于28時(shí),移位判斷操作完成,對(duì)各個(gè)位數(shù)的BCD碼進(jìn)行賦值
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 begin
 unit <= 4'b0;
 ten <= 4'b0;
 hun <= 4'b0;
 tho <= 4'b0;
 t_tho <= 4'b0;
 h_hun <= 4'b0;
 t_hun <= 4'b0;
 h_tho <= 4'b0;
 end
 else if(cnt_shift == 5'd28)
begin
 unit <= data_shift[30:27];
 ten <= data_shift[34:31];
 hun <= data_shift[38:35];
 tho <= data_shift[42:39];
 t_tho <= data_shift[46:43];
 h_hun <= data_shift[50:47];
 t_hun <= data_shift[54:51];
 h_tho <= data_shift[58:55];
 end
 endmodule

cnt_shift:移位判斷計(jì)數(shù)器,data有27位,一共要判斷27次,cnt_shift位數(shù)為5位,從0開始計(jì)數(shù)到28,其中1-27是移位判斷操作。復(fù)位有效時(shí)歸0,計(jì)滿且flag為高點(diǎn)平(移位結(jié)束)時(shí)歸0,flag為高點(diǎn)平(每次移位結(jié)束)都+1,其他情況保持不變

data_shift:移位判斷數(shù)據(jù)寄存器,移位數(shù)據(jù)放在高位,data數(shù)據(jù)放在低位,輸出數(shù)據(jù)一共要32位,data有27位,一共需要59位。計(jì)數(shù)器cnt_shift為0時(shí)賦初值,計(jì)數(shù)器為1-27時(shí)移位判斷。復(fù)位有效時(shí)歸0,計(jì)數(shù)器為0時(shí)賦初值,高32位為0,后27位是data初值。當(dāng)計(jì)數(shù)器不到27且flag為低電平(還沒開始判斷時(shí)),就要開始判斷移位了,具體是:判斷data_shift[30:27]是否大于4(0-26是data,27-30是移位數(shù)據(jù)的低4位),大于4則將[30:27]+3,不滿足就保持原值。...判斷data_shift[58:55]是否大于4,大于4則+3,不滿足保持原值,判斷結(jié)束后,data_shift左移一位,其他情況維持不變

shift_flag:隨著時(shí)鐘周期高低變化的移位判斷標(biāo)志信號(hào),復(fù)位有效時(shí)歸0,其他情況取反,即一個(gè)時(shí)鐘周期內(nèi)為低電平表示判斷,下一個(gè)時(shí)鐘周期內(nèi)為高點(diǎn)平表示移位

輸出:復(fù)位有效時(shí),個(gè)位-千萬位的輸出都為0。由于data有27位,要判斷移位27次,計(jì)數(shù)器計(jì)數(shù)到27時(shí)結(jié)束最后一次判斷移位,計(jì)數(shù)到28時(shí)進(jìn)行輸出的賦值。個(gè)位的4位BCD碼是移位數(shù)據(jù)的低四位data_shift[31:27],千萬位的4位BCD碼是移位數(shù)據(jù)的高4位data_shift[58:55]

3、數(shù)碼管動(dòng)態(tài)顯示驅(qū)動(dòng)模塊seg_dynamic

我們由上一節(jié)知道數(shù)碼管是由位選和段選信號(hào)進(jìn)行選擇和控制的,那么這個(gè)模塊里要將輸入的data轉(zhuǎn)換成對(duì)應(yīng)的段選位選信號(hào)。因此,輸入為時(shí)鐘、復(fù)位、data、seg_en,輸出為sel,seg。因?yàn)榈?ms第一個(gè)數(shù)碼管亮,第2ms第二個(gè)數(shù)碼管亮,這里需要用1ms時(shí)鐘去控制位選信號(hào)即哪個(gè)數(shù)碼管亮。每100ms數(shù)碼管顯示的十進(jìn)制數(shù)要+1,因此時(shí)鐘還要控制段選信號(hào)即選中的數(shù)碼管顯示什么值。中間信號(hào)有實(shí)例化后的輸出unit,...,h_tho,data_reg,cnt_1ms,flag_1ms,cnt_sel,sel_reg,data_disp。data_reg是數(shù)碼管帶顯示內(nèi)容寄存器,假設(shè)輸入要顯示的十進(jìn)制數(shù)是9999_9999,那么不考慮符號(hào)時(shí)8個(gè)數(shù)碼管顯示9999_9999。cnt_1ms時(shí)1ms計(jì)數(shù)器。flag_1ms是標(biāo)志信號(hào),計(jì)滿時(shí)拉高,控制位選。cnt_sel是位選數(shù)碼管計(jì)數(shù)器,8個(gè)數(shù)碼管每1ms換一個(gè)亮,也就是每個(gè)數(shù)碼管8ms亮一次。cnt_sel從0-7計(jì)數(shù),相當(dāng)于給數(shù)碼管編碼。sel_reg是數(shù)碼管位選信號(hào)寄存器,選中點(diǎn)亮的數(shù)碼管后給他顯示的值。data_disp:當(dāng)前點(diǎn)亮數(shù)碼管顯示的值。

module seg_dynamic
(
input wire sys_clk , //系統(tǒng)時(shí)鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號(hào),低有效
input wire [26:0] data , //數(shù)碼管要顯示的值
input wire seg_en , //數(shù)碼管使能信號(hào),高電平有效
output reg [7:0] sel , //數(shù)碼管位選信號(hào)
output reg [7:0] seg //數(shù)碼管段選信號(hào)
);
//parameter define
parameter CNT_MAX = 16'd49_999; //數(shù)碼管刷新時(shí)間計(jì)數(shù)最大值
//wire define
wire [3:0] unit ; //個(gè)位數(shù)
wire [3:0] ten ; //十位數(shù)
wire [3:0] hun ; //百位數(shù)
wire [3:0] tho ; //千位數(shù)
wire [3:0] t_tho ; //萬位數(shù)
wire [3:0] h_hun ; //十萬位數(shù)
wire [3:0] t_hun ;
wire [3:0] h_tho ;


//reg define
reg [31:0] data_reg ; //待顯示數(shù)據(jù)寄存器
reg [15:0] cnt_1ms ; //1ms計(jì)數(shù)器
reg flag_1ms ; //1ms標(biāo)志信號(hào)
reg [2:0] cnt_sel ; //數(shù)碼管位選計(jì)數(shù)器
reg [7:0] sel_reg ; //位選信號(hào)
reg [3:0] data_disp; //當(dāng)前數(shù)碼管顯示的數(shù)據(jù)


//data_reg:控制數(shù)碼管顯示數(shù)據(jù)
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_reg <= 32'b0;
//不考慮小數(shù)點(diǎn),若顯示的數(shù)據(jù)是8位都非0,則8個(gè)數(shù)碼管全顯示
else if(h_tho)
data_reg <= {h_tho,t_hun,h_hun,t_tho,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)7位非0,比如1234567不是顯示01234567,則7個(gè)數(shù)碼管亮
else if(t_hun)
data_reg <= {4'd10,t_hun,h_hun,t_tho,tho,hun,ten,unit};//4'd10我們定義為不顯示
//若顯示的數(shù)據(jù)6位非0,則6個(gè)數(shù)碼管亮
else if(h_hun)
data_reg <= {4'd10,4'd10,h_hun,t_tho,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)5位非0,則5個(gè)數(shù)碼管亮
else if(t_tho)
data_reg <= {4'd10,4'd10,4'd10,t_tho,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)4位非0,則4個(gè)數(shù)碼管亮
else if(tho)
data_reg <= {4'd10,4'd10,4'd10,4'd10,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)3位非0,則3個(gè)數(shù)碼管亮
else if(hun)
data_reg <= {4'd10,4'd10,4'd10,4'd10,4'd10,hun,ten,unit};
//若顯示的數(shù)據(jù)2位非0,則2個(gè)數(shù)碼管亮
else if(ten)
data_reg <= {4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,ten,unit};
//若上面都不滿足都只顯示一位數(shù)碼管
else
data_reg <= {4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,4'd10,unit};


//cnt_1ms:1ms循環(huán)計(jì)數(shù)
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1ms <= 16'd0;
else if(cnt_1ms == CNT_MAX)
cnt_1ms <= 16'd0;
else
cnt_1ms <= cnt_1ms + 1'b1;


//flag_1ms:1ms標(biāo)志信號(hào)
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
flag_1ms <= 1'b0;
else if(cnt_1ms == CNT_MAX - 1'b1)
flag_1ms <= 1'b1;
else
flag_1ms <= 1'b0;


//cnt_sel:從0到7循環(huán)數(shù),用于選擇當(dāng)前顯示的數(shù)碼管
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_sel <= 3'd0;
else if((cnt_sel == 3'd7) && (flag_1ms == 1'b1))
 cnt_sel <= 3'd0;
 else if(flag_1ms == 1'b1)
 cnt_sel <= cnt_sel + 1'b1;
 else
 cnt_sel <= cnt_sel;


//數(shù)碼管位選信號(hào)寄存器
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 sel_reg <= 8'b0000_0000;
 else if((cnt_sel == 3'd0) && (flag_1ms == 1'b1))
 sel_reg <= 8'b0000_0001;
 else if(flag_1ms == 1'b1)
 sel_reg <= sel_reg < < 1;
 else
 sel_reg <= sel_reg;

 //控制數(shù)碼管的位選信號(hào),使8個(gè)數(shù)碼管輪流顯示
always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 data_disp <= 4'b0;
 else if((seg_en == 1'b1) && (flag_1ms == 1'b1))
 case(cnt_sel)
 3'd0: data_disp <= data_reg[3:0] ; //給第1個(gè)數(shù)碼管賦個(gè)位值
 3'd1: data_disp <= data_reg[7:4] ; //給第2個(gè)數(shù)碼管賦十位值
 3'd2: data_disp <= data_reg[11:8] ; //給第3個(gè)數(shù)碼管賦百位值
 3'd3: data_disp <= data_reg[15:12]; //給第4個(gè)數(shù)碼管賦千位值
 3'd4: data_disp <= data_reg[19:16]; //給第5個(gè)數(shù)碼管賦萬位值
 3'd5: data_disp <= data_reg[23:20]; //給第6個(gè)數(shù)碼管賦十萬位值
 3'd6: data_disp <= data_reg[27:24]; //給第7個(gè)數(shù)碼管賦百萬位值
 3'd7: data_disp <= data_reg[31:28]; //給第8個(gè)數(shù)碼管賦千萬位值
 default:data_disp <= 4'b0;
 endcase
 else
data_disp <= data_disp;


//控制數(shù)碼管段選信號(hào),顯示數(shù)字
always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 seg <= 8'b1111_1111;
 else
 case(data_disp)
 4'd0 : seg <= {1'b1,7'b100_0000}; //顯示數(shù)字0
 4'd1 : seg <= {1'b1,7'b111_1001}; //顯示數(shù)字1
 4'd2 : seg <= {1'b1,7'b010_0100}; //顯示數(shù)字2
 4'd3 : seg <= {1'b1,7'b011_0000}; //顯示數(shù)字3
 4'd4 : seg <= {1'b1,7'b001_1001}; //顯示數(shù)字4
 4'd5 : seg <= {1'b1,7'b001_0010}; //顯示數(shù)字5
 4'd6 : seg <= {1'b1,7'b000_0010}; //顯示數(shù)字6
 4'd7 : seg <= {1'b1,7'b111_1000}; //顯示數(shù)字7
 4'd8 : seg <= {1'b1,7'b000_0000}; //顯示數(shù)字8
 4'd9 : seg <= {1'b1,7'b001_0000}; //顯示數(shù)字9
 4'd10 : seg <= 8'b1111_1111 ; //不顯示任何字符
 default:seg <= 8'b1100_0000;
endcase


//sel:數(shù)碼管位選信號(hào)賦值
always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 sel <= 8'b0000_0000;
 else
sel <= sel_reg;


bcd_8421 bcd_8421_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復(fù)位信號(hào),低電平有效
 .data (data ), //輸入需要轉(zhuǎn)換的數(shù)據(jù)
 .unit (unit ), //個(gè)位BCD碼
 .ten (ten ), //十位BCD碼
 .hun (hun ), //百位BCD碼
 .tho (tho ), //千位BCD碼
 .t_tho (t_tho ), //萬位BCD碼
 .h_hun (h_hun ), //十萬位BCD碼
 .t_hun (t_hun ), //百萬位BCD碼
 .h_tho (h_tho ) //千萬位BCD碼
 );

endmodule

參數(shù)定義:1ms計(jì)數(shù)2500000個(gè),最大計(jì)數(shù)值49_999。

data_reg:控制數(shù)碼管要顯示的數(shù)據(jù),復(fù)位有效時(shí)歸0,因?yàn)闆]有小數(shù)點(diǎn),我們考慮到有幾位就只讓幾個(gè)數(shù)碼管進(jìn)行顯示。不顯示的數(shù)碼管定義為4'd11

cnt_1ms:復(fù)位有效或計(jì)滿時(shí)歸0,其他情況+1

flag_1ms:1ms標(biāo)志位,復(fù)位有效時(shí)歸0,計(jì)滿數(shù)值-1時(shí)拉高,其他情況保持低電平

cnt_sel:數(shù)碼管編號(hào),從0-7計(jì)數(shù),復(fù)位有效時(shí)歸0,計(jì)滿7個(gè)數(shù)且標(biāo)志位拉高時(shí)歸0,標(biāo)志位拉高時(shí)+1,其他情況保持不變

控制數(shù)碼管位選信號(hào):復(fù)位有效時(shí)data_disp歸0,使能為高電平有效且標(biāo)志信號(hào)為高時(shí),分情況討論,cnt_sel為0,第一個(gè)數(shù)碼管賦data_reg的低四位,第一個(gè)數(shù)碼管顯示個(gè)位,...,需要有default語句,data_disp賦0即可,其他情況,data_disp保持不變

控制數(shù)碼管段選信號(hào):復(fù)位有效時(shí)seg所有位賦1表示每一段都不點(diǎn)亮,其他分情況討論,data_disp為0時(shí)數(shù)碼管顯示0,0對(duì)應(yīng)的段選碼上一節(jié)討論了,最高位是小數(shù)點(diǎn)不用都為1表示滅,低7位對(duì)應(yīng)abcdefg=100_0000,以此類推,加上default語句

sel:數(shù)碼管位選信號(hào)賦值,復(fù)位有效時(shí)歸0,其他情況將sel_reg賦值給

實(shí)例化BCD

4、74HC595控制模塊

直接用上一節(jié)的代碼,需要注意的是hc595_ctrl.v中第23行對(duì)data的賦值,把最右邊的數(shù)碼管作為個(gè)位比較符合我們的書寫習(xí)慣,所以位選信號(hào)的順序要改,原語句是assign data={sel,seg[0],seg[1],...,seg[7]};要改做assign data={sel[0],sel[1],...,sel[7],seg[0],seg[1],...,seg[7]};否則,數(shù)碼管最左邊是個(gè)位,不符合書寫習(xí)慣。

5、數(shù)碼管動(dòng)態(tài)顯示模塊

該模塊主要是對(duì)數(shù)碼管動(dòng)態(tài)顯示驅(qū)動(dòng)模塊和74HC595控制模塊的實(shí)例化,以及對(duì)應(yīng)信號(hào)的連接

module seg_595_dynamic
(
input wire sys_clk , //系統(tǒng)時(shí)鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號(hào),低有效
input wire [26:0] data , //數(shù)碼管要顯示的值
input wire seg_en , //數(shù)碼管使能信號(hào),高電平有效
output wire stcp , //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
output wire shcp , //移位寄存器的時(shí)鐘輸入
output wire ds //串行數(shù)據(jù)輸入
);
//wire define
 wire [7:0] sel; //數(shù)碼管位選信號(hào)
 wire [7:0] seg; //數(shù)碼管段選信號(hào)


seg_dynamic seg_dynamic_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復(fù)位信號(hào),低有效
 .data (data ), //數(shù)碼管要顯示的值
 .seg_en (seg_en ), //數(shù)碼管使能信號(hào),高電平有效
 .sel (sel ), //數(shù)碼管位選信號(hào)
 .seg (seg ) //數(shù)碼管段選信號(hào)
);


hc595_ctrl hc595_ctrl_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復(fù)位信號(hào),低有效
 .sel (sel ), //數(shù)碼管位選信號(hào)
 .seg (seg ), //數(shù)碼管段選信號(hào)
 .en (1'b1),
 .stcp (stcp ), //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
 .shcp (shcp ), //移位寄存器的時(shí)鐘輸入
 .ds (ds ) //串行數(shù)據(jù)輸入
 );


endmodule

兩個(gè)模塊的實(shí)例化

6、頂層模塊top_seg_595

頂層模塊主要是對(duì)各個(gè)子功能模塊的實(shí)例化,以及對(duì)應(yīng)信號(hào)的連接

module top_seg_595
(
input wire sys_clk , //系統(tǒng)時(shí)鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號(hào),低電平有效
output wire stcp , //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
output wire shcp , //移位寄存器的時(shí)鐘輸入
output wire ds //串行數(shù)據(jù)輸入
);
 //wire define
 wire [26:0] data ; //數(shù)碼管要顯示的值
 wire seg_en ;//數(shù)碼管使能信號(hào),高電平有效 

 data_gen data_gen_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復(fù)位信號(hào),低電平有效
 .data (data ), //數(shù)碼管要顯示的值
 .seg_en (seg_en) //數(shù)碼管使能信號(hào),高電平有效
 );

 seg_595_dynamic seg_595_dynamic_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n ), //復(fù)位信號(hào),低有效
 .data (data ), //數(shù)碼管要顯示的值
 .seg_en (seg_en ), //數(shù)碼管使能信號(hào),高電平有效
 .stcp (stcp ), //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
 .shcp (shcp ), //移位寄存器的時(shí)鐘輸入
 .ds (ds ) //串行數(shù)據(jù)輸入
 );
 endmodule

數(shù)據(jù)產(chǎn)生和動(dòng)態(tài)顯示模塊的實(shí)例化

圖片

編寫testbench

`timescale 1ns/1ns
module tb_top_seg_595();


//wire define
wire stcp ; //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
wire shcp ; //移位寄存器的時(shí)鐘輸入
wire ds ; //串行數(shù)據(jù)輸入


 //reg define
 reg sys_clk ;
 reg sys_rst_n ;


 //對(duì)sys_clk,sys_rst_n賦初始值
 initial
 begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #100
 sys_rst_n <= 1'b1;
 end


 //clk:產(chǎn)生時(shí)鐘
 always #10 sys_clk <= ~sys_clk;


 //重新定義參數(shù)值,縮短仿真時(shí)間
 defparam top_seg_595_inst.seg_595_dynamic_inst.seg_dynamic_inst.
 CNT_MAX=19;
 defparam top_seg_595_inst.data_gen_inst.CNT_MAX = 49;

 top_seg_595 top_seg_595_inst
 (
 .sys_clk (sys_clk ), //系統(tǒng)時(shí)鐘,頻率50MHz
 .sys_rst_n (sys_rst_n ), //復(fù)位信號(hào),低電平有效


 .stcp (stcp ), //輸出數(shù)據(jù)存儲(chǔ)寄時(shí)鐘
 .shcp (shcp ), //移位寄存器的時(shí)鐘輸入
 .ds (ds )//串行數(shù)據(jù)輸入
 );


 endmodule

testbench已經(jīng)很熟悉了。

對(duì)比波形

先看6個(gè)模塊的從屬關(guān)系,再分別檢查6個(gè)模塊的波形,比較容易debug。

圖片

數(shù)據(jù)產(chǎn)生模塊

圖片

后面幾個(gè)模塊不細(xì)列。

分配管腳

和上一節(jié)一樣

圖片

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1646

    文章

    22054

    瀏覽量

    618802
  • 發(fā)光二極管
    +關(guān)注

    關(guān)注

    13

    文章

    1218

    瀏覽量

    67695
  • 數(shù)碼管
    +關(guān)注

    關(guān)注

    32

    文章

    1889

    瀏覽量

    92654
  • 顯示模塊
    +關(guān)注

    關(guān)注

    1

    文章

    54

    瀏覽量

    23800
  • 動(dòng)態(tài)顯示
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    11879
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    #硬聲創(chuàng)作季 數(shù)字設(shè)計(jì)FPGA應(yīng)用:數(shù)碼管動(dòng)態(tài)顯示1

    數(shù)碼管數(shù)字設(shè)計(jì)
    Mr_haohao
    發(fā)布于 :2022年10月24日 03:11:55

    #硬聲創(chuàng)作季 數(shù)字設(shè)計(jì)FPGA應(yīng)用:數(shù)碼管動(dòng)態(tài)顯示2

    fpga數(shù)字設(shè)計(jì)
    Mr_haohao
    發(fā)布于 :2022年10月24日 03:12:44

    #硬聲創(chuàng)作季 數(shù)字設(shè)計(jì)FPGA應(yīng)用:數(shù)碼管動(dòng)態(tài)顯示3

    數(shù)碼管數(shù)字設(shè)計(jì)
    Mr_haohao
    發(fā)布于 :2022年10月24日 03:13:25

    這個(gè)fpga數(shù)碼管動(dòng)態(tài)顯示程序錯(cuò)誤嗎?動(dòng)態(tài)掃描不出來

    各位大哥幫我看看,始終動(dòng)態(tài)掃描不來,只能顯示第一個(gè)數(shù)碼管module seg7(CLK_50M,RST_N,SEG_DATA,SEG_EN,LED);input CLK_50M;input
    發(fā)表于 08-10 21:10

    FPGA入門實(shí)現(xiàn)教程之數(shù)碼管動(dòng)態(tài)顯示

    FPGA入門實(shí)現(xiàn)教程之數(shù)碼管動(dòng)態(tài)顯示
    發(fā)表于 11-13 16:25 ?93次下載

    數(shù)碼管動(dòng)態(tài)顯示實(shí)驗(yàn)

    數(shù)碼管動(dòng)態(tài)顯示實(shí)驗(yàn)一、實(shí)驗(yàn)?zāi)康脑趯?shí)際的單片機(jī)系統(tǒng)中,往往需要多位顯示。動(dòng)態(tài)顯示是一種最常見的多位顯示方法,應(yīng)用非常廣泛。本實(shí)驗(yàn)要求實(shí)驗(yàn)兩
    發(fā)表于 03-23 10:45 ?1.1w次閱讀

    基于FPGA的8段數(shù)碼管動(dòng)態(tài)顯示IP核設(shè)計(jì)

    基于FPGA的8段數(shù)碼管動(dòng)態(tài)顯示IP核設(shè)計(jì)  引言   數(shù)碼管顯示簡(jiǎn)單的字符和數(shù)字,由于其價(jià)格低廉、性能穩(wěn)定、
    發(fā)表于 02-03 10:03 ?2505次閱讀
    基于<b class='flag-5'>FPGA</b>的8段<b class='flag-5'>數(shù)碼管</b><b class='flag-5'>動(dòng)態(tài)顯示</b>IP核設(shè)計(jì)

    數(shù)碼管動(dòng)態(tài)顯示)【C語言版】

    數(shù)碼管動(dòng)態(tài)顯示)【C語言版】數(shù)碼管動(dòng)態(tài)顯示)【C語言版】數(shù)碼管動(dòng)態(tài)顯示)【C語言版】
    發(fā)表于 12-29 15:51 ?0次下載

    MIN數(shù)碼管動(dòng)態(tài)顯示

    數(shù)碼管動(dòng)態(tài)顯示,MIN數(shù)碼管動(dòng)態(tài)顯示,MIN。
    發(fā)表于 05-03 10:48 ?11次下載

    使用FPGA DIY控制板實(shí)現(xiàn)數(shù)碼管動(dòng)態(tài)顯示功能

    數(shù)碼管動(dòng)態(tài)顯示——FPGA
    的頭像 發(fā)表于 06-22 01:00 ?5105次閱讀
    使用<b class='flag-5'>FPGA</b> DIY控制板實(shí)現(xiàn)<b class='flag-5'>數(shù)碼管</b><b class='flag-5'>動(dòng)態(tài)顯示</b>功能

    采用FPGA DIY開發(fā)板實(shí)現(xiàn)數(shù)碼管動(dòng)態(tài)顯示60計(jì)數(shù)

    asean的 FPGA DIY 數(shù)碼管動(dòng)態(tài)顯示60計(jì)數(shù)視頻
    的頭像 發(fā)表于 06-20 12:04 ?3873次閱讀

    通過FPGA DIY開發(fā)板實(shí)現(xiàn)數(shù)碼管動(dòng)態(tài)顯示

    8個(gè)數(shù)碼管動(dòng)態(tài)顯示數(shù)字,數(shù)碼管依次顯示數(shù)字0~7
    的頭像 發(fā)表于 06-20 01:29 ?4674次閱讀
    通過<b class='flag-5'>FPGA</b> DIY開發(fā)板實(shí)現(xiàn)<b class='flag-5'>數(shù)碼管</b><b class='flag-5'>動(dòng)態(tài)顯示</b>

    數(shù)字設(shè)計(jì)FPGA應(yīng)用:數(shù)碼管動(dòng)態(tài)顯示實(shí)驗(yàn)

    數(shù)碼管的最常見形式有10個(gè)陰極,形狀為數(shù)字0到9,某些數(shù)碼管還有一個(gè)或兩個(gè)小數(shù)點(diǎn)。然而也有其他類型的數(shù)碼管顯示字母、標(biāo)記和符號(hào)。
    的頭像 發(fā)表于 12-04 07:08 ?5667次閱讀
    數(shù)字設(shè)計(jì)<b class='flag-5'>FPGA</b>應(yīng)用:<b class='flag-5'>數(shù)碼管</b><b class='flag-5'>動(dòng)態(tài)顯示</b>實(shí)驗(yàn)

    正點(diǎn)原子開拓者FPGA數(shù)碼管動(dòng)態(tài)顯示實(shí)驗(yàn)

    數(shù)碼管動(dòng)態(tài)顯示接口是單片機(jī)中應(yīng)用最為廣泛的一種顯示方式之一,動(dòng)態(tài)驅(qū)動(dòng)是將所有數(shù)碼管的8個(gè)顯示筆劃
    的頭像 發(fā)表于 09-09 06:09 ?3808次閱讀
    正點(diǎn)原子開拓者<b class='flag-5'>FPGA</b>:<b class='flag-5'>數(shù)碼管</b><b class='flag-5'>動(dòng)態(tài)顯示</b>實(shí)驗(yàn)

    數(shù)碼管動(dòng)態(tài)顯示的原理概述

    動(dòng)態(tài)顯示的特點(diǎn)是將所有數(shù)碼管的段選線并聯(lián)在一起,由位選線控制是哪一位數(shù)碼管有效。選亮數(shù)碼管采用動(dòng)態(tài)掃描
    發(fā)表于 11-04 08:00 ?0次下載