在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于FPGA的數碼管動態顯示

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

設計規劃

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

理論基礎

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

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

編寫代碼

圖片

通過系統框圖可以看出,分為6個模塊:數據生成模塊,二進制轉BCD模塊,數碼管動態顯示驅動模塊,74HC595模塊,數碼管動態顯示模塊,頂層模塊。

1、數據生成模塊data_gen

應該具有輸入:時鐘和復位,輸出:數據data和使能seg_en。中間信號有100ms計數器cnt_100ms,標志位cnt_flag。

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


//reg define
reg [22:0] cnt_100ms ; // 100ms計數器
reg cnt_flag ; //100ms標志信號


 //cnt_100ms:用50MHz時鐘從0到4999_999計數即為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產生一個標志信號
 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;


 //數碼管顯示的數據: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;


 //數碼管使能信號給高即可
 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

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

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

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

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

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

2、BCD模塊bcd_8421

輸入是時鐘、復位和數據data,data是2進制數,要先轉換成10進制,再將10進制的每一位轉換成BCD碼,才能使每一個數碼管顯示對應的字符。我們看二進制碼如何變為BCD碼。輸出是8個數碼管對應8位,每位轉換BCD碼是4位。輸出是:個位,十位,百位,千位,萬位,十萬位,百萬位,千萬位。中間信號是移位判斷計數器cnt_shift,移位判斷數據寄存器data_shift,移位判斷標志信號shift_flag。

圖片

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

module bcd_8421(
input wire sys_clk , //系統時鐘,頻率50MHz
input wire sys_rst_n , //復位信號,低電平有效
input wire [26:0] data , //輸入需要轉換的數據
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 ;  //移位判斷計數器
 reg [58:0] data_shift ; //移位判斷數據寄存器
 reg shift_flag ; //移位判斷標志信號




 //cnt_shift:從0到28循環計數
 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:計數器為0時賦初值,計數器為1~27時進行移位判斷操作
 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:移位判斷標志信號,用于控制移位判斷的先后順序
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 shift_flag <= 1'b0;
 else
 shift_flag <= ~shift_flag;


 //當計數器等于28時,移位判斷操作完成,對各個位數的BCD碼進行賦值
 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:移位判斷計數器,data有27位,一共要判斷27次,cnt_shift位數為5位,從0開始計數到28,其中1-27是移位判斷操作。復位有效時歸0,計滿且flag為高點平(移位結束)時歸0,flag為高點平(每次移位結束)都+1,其他情況保持不變

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

shift_flag:隨著時鐘周期高低變化的移位判斷標志信號,復位有效時歸0,其他情況取反,即一個時鐘周期內為低電平表示判斷,下一個時鐘周期內為高點平表示移位

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

3、數碼管動態顯示驅動模塊seg_dynamic

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

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


//reg define
reg [31:0] data_reg ; //待顯示數據寄存器
reg [15:0] cnt_1ms ; //1ms計數器
reg flag_1ms ; //1ms標志信號
reg [2:0] cnt_sel ; //數碼管位選計數器
reg [7:0] sel_reg ; //位選信號
reg [3:0] data_disp; //當前數碼管顯示的數據


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


//cnt_1ms:1ms循環計數
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標志信號
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循環數,用于選擇當前顯示的數碼管
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;


//數碼管位選信號寄存器
 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;

 //控制數碼管的位選信號,使8個數碼管輪流顯示
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個數碼管賦個位值
 3'd1: data_disp <= data_reg[7:4] ; //給第2個數碼管賦十位值
 3'd2: data_disp <= data_reg[11:8] ; //給第3個數碼管賦百位值
 3'd3: data_disp <= data_reg[15:12]; //給第4個數碼管賦千位值
 3'd4: data_disp <= data_reg[19:16]; //給第5個數碼管賦萬位值
 3'd5: data_disp <= data_reg[23:20]; //給第6個數碼管賦十萬位值
 3'd6: data_disp <= data_reg[27:24]; //給第7個數碼管賦百萬位值
 3'd7: data_disp <= data_reg[31:28]; //給第8個數碼管賦千萬位值
 default:data_disp <= 4'b0;
 endcase
 else
data_disp <= data_disp;


//控制數碼管段選信號,顯示數字
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}; //顯示數字0
 4'd1 : seg <= {1'b1,7'b111_1001}; //顯示數字1
 4'd2 : seg <= {1'b1,7'b010_0100}; //顯示數字2
 4'd3 : seg <= {1'b1,7'b011_0000}; //顯示數字3
 4'd4 : seg <= {1'b1,7'b001_1001}; //顯示數字4
 4'd5 : seg <= {1'b1,7'b001_0010}; //顯示數字5
 4'd6 : seg <= {1'b1,7'b000_0010}; //顯示數字6
 4'd7 : seg <= {1'b1,7'b111_1000}; //顯示數字7
 4'd8 : seg <= {1'b1,7'b000_0000}; //顯示數字8
 4'd9 : seg <= {1'b1,7'b001_0000}; //顯示數字9
 4'd10 : seg <= 8'b1111_1111 ; //不顯示任何字符
 default:seg <= 8'b1100_0000;
endcase


//sel:數碼管位選信號賦值
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 ), //系統時鐘,頻率50MHz
 .sys_rst_n (sys_rst_n), //復位信號,低電平有效
 .data (data ), //輸入需要轉換的數據
 .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

參數定義:1ms計數2500000個,最大計數值49_999。

data_reg:控制數碼管要顯示的數據,復位有效時歸0,因為沒有小數點,我們考慮到有幾位就只讓幾個數碼管進行顯示。不顯示的數碼管定義為4'd11

cnt_1ms:復位有效或計滿時歸0,其他情況+1

flag_1ms:1ms標志位,復位有效時歸0,計滿數值-1時拉高,其他情況保持低電平

cnt_sel:數碼管編號,從0-7計數,復位有效時歸0,計滿7個數且標志位拉高時歸0,標志位拉高時+1,其他情況保持不變

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

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

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

實例化BCD

4、74HC595控制模塊

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

5、數碼管動態顯示模塊

該模塊主要是對數碼管動態顯示驅動模塊和74HC595控制模塊的實例化,以及對應信號的連接

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


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


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


endmodule

兩個模塊的實例化

6、頂層模塊top_seg_595

頂層模塊主要是對各個子功能模塊的實例化,以及對應信號的連接

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

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

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

數據產生和動態顯示模塊的實例化

圖片

編寫testbench

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


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


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


 //重新定義參數值,縮短仿真時間
 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 ), //系統時鐘,頻率50MHz
 .sys_rst_n (sys_rst_n ), //復位信號,低電平有效


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


 endmodule

testbench已經很熟悉了。

對比波形

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

圖片

數據產生模塊

圖片

后面幾個模塊不細列。

分配管腳

和上一節一樣

圖片

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FPGA
    +關注

    關注

    1630

    文章

    21798

    瀏覽量

    606065
  • 發光二極管
    +關注

    關注

    13

    文章

    1205

    瀏覽量

    66513
  • 數碼管
    +關注

    關注

    32

    文章

    1887

    瀏覽量

    91410
  • 顯示模塊
    +關注

    關注

    1

    文章

    50

    瀏覽量

    23602
  • 動態顯示
    +關注

    關注

    0

    文章

    40

    瀏覽量

    11726
收藏 人收藏

    評論

    相關推薦

    #硬聲創作季 數字設計FPGA應用:數碼管動態顯示1

    數碼管數字設計
    Mr_haohao
    發布于 :2022年10月24日 03:11:55

    #硬聲創作季 數字設計FPGA應用:數碼管動態顯示2

    fpga數字設計
    Mr_haohao
    發布于 :2022年10月24日 03:12:44

    #硬聲創作季 數字設計FPGA應用:數碼管動態顯示3

    數碼管數字設計
    Mr_haohao
    發布于 :2022年10月24日 03:13:25

    這個fpga數碼管動態顯示程序錯誤嗎?動態掃描不出來

    各位大哥幫我看看,始終動態掃描不來,只能顯示第一個數碼管module seg7(CLK_50M,RST_N,SEG_DATA,SEG_EN,LED);input CLK_50M;input
    發表于 08-10 21:10

    FPGA入門實現教程之數碼管動態顯示

    FPGA入門實現教程之數碼管動態顯示
    發表于 11-13 16:25 ?93次下載

    數碼管動態顯示實驗

    數碼管動態顯示實驗一、實驗目的在實際的單片機系統中,往往需要多位顯示動態顯示是一種最常見的多位顯示方法,應用非常廣泛。本實驗要求實驗兩
    發表于 03-23 10:45 ?1w次閱讀

    基于FPGA的8段數碼管動態顯示IP核設計

    基于FPGA的8段數碼管動態顯示IP核設計  引言   數碼管顯示簡單的字符和數字,由于其價格低廉、性能穩定、
    發表于 02-03 10:03 ?2406次閱讀
    基于<b class='flag-5'>FPGA</b>的8段<b class='flag-5'>數碼管</b><b class='flag-5'>動態顯示</b>IP核設計

    數碼管動態顯示)【C語言版】

    數碼管動態顯示)【C語言版】數碼管動態顯示)【C語言版】數碼管動態顯示)【C語言版】
    發表于 12-29 15:51 ?0次下載

    MIN數碼管動態顯示

    數碼管動態顯示,MIN數碼管動態顯示,MIN。
    發表于 05-03 10:48 ?9次下載

    使用FPGA DIY控制板實現數碼管動態顯示功能

    數碼管動態顯示——FPGA
    的頭像 發表于 06-22 01:00 ?4808次閱讀
    使用<b class='flag-5'>FPGA</b> DIY控制板實現<b class='flag-5'>數碼管</b><b class='flag-5'>動態顯示</b>功能

    采用FPGA DIY開發板實現數碼管動態顯示60計數

    asean的 FPGA DIY 數碼管動態顯示60計數視頻
    的頭像 發表于 06-20 12:04 ?3528次閱讀

    通過FPGA DIY開發板實現數碼管動態顯示

    8個數碼管動態顯示數字,數碼管依次顯示數字0~7
    的頭像 發表于 06-20 01:29 ?4372次閱讀
    通過<b class='flag-5'>FPGA</b> DIY開發板實現<b class='flag-5'>數碼管</b><b class='flag-5'>動態顯示</b>

    數字設計FPGA應用:數碼管動態顯示實驗

    數碼管的最常見形式有10個陰極,形狀為數字0到9,某些數碼管還有一個或兩個小數點。然而也有其他類型的數碼管顯示字母、標記和符號。
    的頭像 發表于 12-04 07:08 ?5442次閱讀
    數字設計<b class='flag-5'>FPGA</b>應用:<b class='flag-5'>數碼管</b><b class='flag-5'>動態顯示</b>實驗

    正點原子開拓者FPGA數碼管動態顯示實驗

    數碼管動態顯示接口是單片機中應用最為廣泛的一種顯示方式之一,動態驅動是將所有數碼管的8個顯示筆劃
    的頭像 發表于 09-09 06:09 ?3581次閱讀
    正點原子開拓者<b class='flag-5'>FPGA</b>:<b class='flag-5'>數碼管</b><b class='flag-5'>動態顯示</b>實驗

    數碼管動態顯示的原理概述

    動態顯示的特點是將所有數碼管的段選線并聯在一起,由位選線控制是哪一位數碼管有效。選亮數碼管采用動態掃描
    發表于 11-04 08:00 ?0次下載
    主站蜘蛛池模板: 激情理论| 三级在线观看网站 | 色极影院 | 手机在线看福利 | 四虎影院永久网址 | 久久综合精品视频 | 色婷婷亚洲综合五月 | 好大好硬好深好爽想要免费视频 | 男女爱爱免费高清 | 亚洲免费一区二区 | 亚洲国产成a人v在线观看 | 国产精品美乳在线观看 | 色噜噜狠狠狠色综合久 | 人与牲动交xx | 99热官网 | 最新亚洲人成网站在线影院 | 欧美二级黄色片 | 久久999| 午夜 dy888理论久久 | 两性色视频 | 国产精品三级a三级三级午夜 | 免费看欧美一级特黄a大片 免费看欧美一级特黄a大片一 | 337p亚洲精品色噜噜狠狠 | 激情综合五月婷婷 | 特级片毛片 | 医生好大好硬好爽好紧 | 色视频一区二区三区 | 在线免费视频手机版 | 亚洲五月综合网色九月色 | 在线免费视频 | 婷婷99 | 国产美女视频爽爽爽 | 综合99| 欧美怡红院免费全视频 | 午夜视频你懂的 | 手机毛片在线 | 大又大又粗又爽女人毛片 | 91高清在线成人免费观看 | 女人被免费网站视频在线 | 丰满年轻岳欲乱中文字幕 | 美女视频黄a全部免费看小说 |