欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

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

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

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

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

CHANBAEK ? 來源:小小研究生 ? 作者:xxyjs2020 ? 2023-08-15 15:59 ? 次閱讀

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

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

理論基礎(chǔ)

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

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

編寫代碼

圖片

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

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

應(yīng)該具有輸入:時鐘和復(fù)位,輸出:數(shù)據(jù)data和使能seg_en。中間信號有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)時鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號,低電平有效
output reg [26:0] data , //數(shù)碼管要顯示的值
output reg seg_en //數(shù)碼管使能信號,高電平有效
);


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


 //cnt_100ms:用50MHz時鐘從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)生一個標(biā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ù)碼管使能信號給高即可
 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的時鐘需要從0記到4999_999,顯示的最大值是999_999,前者是23位,后者是27位。

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

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

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

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

2、BCD模塊bcd_8421

輸入是時鐘、復(fù)位和數(shù)據(jù)data,data是2進(jìn)制數(shù),要先轉(zhuǎn)換成10進(jìn)制,再將10進(jìn)制的每一位轉(zhuǎn)換成BCD碼,才能使每一個數(shù)碼管顯示對應(yīng)的字符。我們看二進(jìn)制碼如何變?yōu)锽CD碼。輸出是8個數(shù)碼管對應(yīng)8位,每位轉(zhuǎn)換BCD碼是4位。輸出是:個位,十位,百位,千位,萬位,十萬位,百萬位,千萬位。中間信號是移位判斷計(jì)數(shù)器cnt_shift,移位判斷數(shù)據(jù)寄存器data_shift,移位判斷標(biā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)行移位,并判斷每一個BCD碼其對應(yīng)的十進(jìn)制數(shù)是否大于4,如果大于4就對BCD碼做加3操作,若小于等于4就讓其值保持不變。然后繼續(xù)移位,每次移位后都要進(jìn)行判斷。

module bcd_8421(
input wire sys_clk , //系統(tǒng)時鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號,低電平有效
input wire [26:0] data , //輸入需要轉(zhuǎn)換的數(shù)據(jù)
output reg [3:0] unit , //個位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)志信號




 //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時賦初值,計(jì)數(shù)器為1~27時進(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)志信號,用于控制移位判斷的先后順序
 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ù)的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ù)位有效時歸0,計(jì)滿且flag為高點(diǎn)平(移位結(jié)束)時歸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時賦初值,計(jì)數(shù)器為1-27時移位判斷。復(fù)位有效時歸0,計(jì)數(shù)器為0時賦初值,高32位為0,后27位是data初值。當(dāng)計(jì)數(shù)器不到27且flag為低電平(還沒開始判斷時),就要開始判斷移位了,具體是:判斷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:隨著時鐘周期高低變化的移位判斷標(biāo)志信號,復(fù)位有效時歸0,其他情況取反,即一個時鐘周期內(nèi)為低電平表示判斷,下一個時鐘周期內(nèi)為高點(diǎn)平表示移位

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

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

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

module seg_dynamic
(
input wire sys_clk , //系統(tǒng)時鐘,頻率50MHz
input wire sys_rst_n , //復(fù)位信號,低有效
input wire [26:0] data , //數(shù)碼管要顯示的值
input wire seg_en , //數(shù)碼管使能信號,高電平有效
output reg [7:0] sel , //數(shù)碼管位選信號
output reg [7:0] seg //數(shù)碼管段選信號
);
//parameter define
parameter CNT_MAX = 16'd49_999; //數(shù)碼管刷新時間計(jì)數(shù)最大值
//wire define
wire [3:0] unit ; //個位數(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)志信號
reg [2:0] cnt_sel ; //數(shù)碼管位選計(jì)數(shù)器
reg [7:0] sel_reg ; //位選信號
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個數(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個數(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個數(shù)碼管亮
else if(h_hun)
data_reg <= {4'd10,4'd10,h_hun,t_tho,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)5位非0,則5個數(shù)碼管亮
else if(t_tho)
data_reg <= {4'd10,4'd10,4'd10,t_tho,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)4位非0,則4個數(shù)碼管亮
else if(tho)
data_reg <= {4'd10,4'd10,4'd10,4'd10,tho,hun,ten,unit};
//若顯示的數(shù)據(jù)3位非0,則3個數(shù)碼管亮
else if(hun)
data_reg <= {4'd10,4'd10,4'd10,4'd10,4'd10,hun,ten,unit};
//若顯示的數(shù)據(jù)2位非0,則2個數(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)志信號
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ù)碼管位選信號寄存器
 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ù)碼管的位選信號,使8個數(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個數(shù)碼管賦個位值
 3'd1: data_disp <= data_reg[7:4] ; //給第2個數(shù)碼管賦十位值
 3'd2: data_disp <= data_reg[11:8] ; //給第3個數(shù)碼管賦百位值
 3'd3: data_disp <= data_reg[15:12]; //給第4個數(shù)碼管賦千位值
 3'd4: data_disp <= data_reg[19:16]; //給第5個數(shù)碼管賦萬位值
 3'd5: data_disp <= data_reg[23:20]; //給第6個數(shù)碼管賦十萬位值
 3'd6: data_disp <= data_reg[27:24]; //給第7個數(shù)碼管賦百萬位值
 3'd7: data_disp <= data_reg[31:28]; //給第8個數(shù)碼管賦千萬位值
 default:data_disp <= 4'b0;
 endcase
 else
data_disp <= data_disp;


//控制數(shù)碼管段選信號,顯示數(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ù)碼管位選信號賦值
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)時鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復(fù)位信號,低電平有效
 .data (data ), //輸入需要轉(zhuǎn)換的數(shù)據(jù)
 .unit (unit ), //個位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個,最大計(jì)數(shù)值49_999。

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

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

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

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

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

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

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

實(shí)例化BCD

4、74HC595控制模塊

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

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

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

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


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


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


endmodule

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

6、頂層模塊top_seg_595

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

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

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

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

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

圖片

編寫testbench

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


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


 //reg define
 reg sys_clk ;
 reg sys_rst_n ;


 //對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)生時鐘
 always #10 sys_clk <= ~sys_clk;


 //重新定義參數(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)時鐘,頻率50MHz
 .sys_rst_n (sys_rst_n ), //復(fù)位信號,低電平有效


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


 endmodule

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

對比波形

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

圖片

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

圖片

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

分配管腳

和上一節(jié)一樣

圖片

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

    關(guān)注

    1630

    文章

    21799

    瀏覽量

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

    關(guān)注

    13

    文章

    1205

    瀏覽量

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

    關(guān)注

    32

    文章

    1887

    瀏覽量

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

    關(guān)注

    1

    文章

    50

    瀏覽量

    23604
  • 動態(tài)顯示
    +關(guān)注

    關(guān)注

    0

    文章

    40

    瀏覽量

    11728
收藏 人收藏

    評論

    相關(guān)推薦

    #硬聲創(chuàng)作季 數(shù)字設(shè)計(jì)FPGA應(yīng)用:數(shù)碼管動態(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ù)碼管動態(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ù)碼管動態(tài)顯示3

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

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

    各位大哥幫我看看,始終動態(tài)掃描不來,只能顯示第一個數(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ù)碼管動態(tài)顯示

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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