このドキュメントは http://icrus.org/fpga_atlys_design/ 上にあります.
本日はカウンタと7セグLEDについて解説と実習を行います.先ずは,前回の「LEDチカチカ」プログラムをよく読んで,理解してください.
ここでは,カウンタをいくつか紹介し,それをもとに皆さんにその発展形を考えていってもらいます.扱うカウンタは以下の通りです.
本日の実習に参考になる資料のURLを示します.
はじめは4ビットカウンタです.4ビットですから0〜15までを数え上げることができます.ここでは,LEDチカチカを利用して1秒に1カウントアップするようにしています.先ずはリストを入力して実行しててみてください.もちろん入力前には新プロジェクトを作って,ISEを再起動するのを忘れないでください.
001 `timescale 1ns / 1ps
002 ///////////////////////////////////////////////////////////////////////////////
003 // Create Date: 2014,11,23
004 // Module Name: bit_4_counter
005 ///////////////////////////////////////////////////////////////////////////////
006 module bit_4_counter(
007 input wire clk0,
008 output wire [3:0] led
009 );
010
011 assign led=count16;
012 reg[26:0] c=0;
013
014 always @( posedge clk0 )begin
015 if( c==27'd99999999 )
016 c <= 0;
017 else
018 c <= c + 1'b1;
019 end
020
021 reg[3:0] count16=4'b0;
022 always @( negedge c[26] )begin
023 count16 <= count16 + 1'b1;
024 end
025
026 endmodule
001 NET "clk0" LOC = L15; // CLK
002
003 NET "led(3)" LOC = L14; // LD3
004 NET "led(2)" LOC = N14; // LD2
005 NET "led(1)" LOC = M14; // LD1
006 NET "led(0)" LOC = U18; // LD0
LED(LD3〜LD0)は1刻みでカントアップしたでしょうか?1111の後0000に戻りましたか?動かない場合は,一度ISEを再起動してコンパイルをやり直してください.
0000→0001→0010→0011→0100→0101→0110→0111→1000→1001→1010→1011→1100→1101→1110→1111→0000
これが4ビットカウンタの基本動作です.1秒1進みますので0~15秒まで(16秒間)をカウントアップできます.
4ビットカウンタを利用して,8ビットカウンタを作成してください.8ビットカウンタは255(4分15秒)(256秒間)までカウントアップしてその後0リセットされます.
まずは,以下のヒントを見ずに自分で考えてみてください.
(1) *.vリストの021を8ビットに対応する.
reg[7:0] count16=7'b0;
(2) *.vリストの021を8ビットに対応する.
output wire [7:0] led
(3) *.ucfリストに以下を追加する.
NET "led(7)" LOC = N12; // LD7
NET "led(6)" LOC = P16; // LD6
NET "led(5)" LOC = D4; // LD5
NET "led(4)" LOC = M13; // LD4
8ビットカウンタを利用して,8ビットカウンタ加速を作成します.8ビットカウンタのカウントアップの刻みを1秒から0.1にしてスピードアップします.フルカウントで25.5秒になり(25.6秒間)その後0リセットされます.
まずは,ヒントを読む前に自分で考えてみてください.
(1) *.vリストの015の27'd99999999を一桁減らし24'd9999999にする.
(2) 012を十進数で1桁分の3ビット減らす.
reg[23:0] c=0;
(3) 022をcの最大ビットに変更する
always @( negedge c[23] )begin
しっかりマスターして,いつでもカウンタのスピードアップ,スピードダウンできるようにしてください.
10進6進カウンタは簡単ですので,ソースを読んで理解できたら,ISEに入力して実行してみてください.変更点を確認してください.
001 `timescale 1ns / 1ps
002 ///////////////////////////////////////////////////////////////////////////////
003 // Create Date: 2014,11,23
004 // Module Name: counter10
005 ///////////////////////////////////////////////////////////////////////////////
006 module counter10(
007 input wire clk0,
008 output wire [3:0] led
009 );
010
011 assign led=count16;
012 reg[26:0] c=0;
013
014 always @( posedge clk0 )begin
015 if( c==27'd99999999 )
016 c <= 0;
017 else
018 c <= c + 1'b1;
019 end
020
021 reg[3:0] count16=4'b0;
022 always @( negedge c[26] )begin
023 if( count16==4'd9 )
024 count16 <= 1'b0;
025 else
026 count16 <= count16 + 1'b1;
027 end
028
029 endmodule
001 NET "clk0" LOC = L15; // CLK
002
003 NET "led(3)" LOC = L14; // LD3
004 NET "led(2)" LOC = N14; // LD2
005 NET "led(1)" LOC = M14; // LD1
006 NET "led(0)" LOC = U18; // LD0
LED(LD3〜LD0)はカウントアップされ1001の後0000に戻ります.
0000→0001→0010→0011→0100→0101→0110→0111→1000→1001→0000
9のときリセットすることのにより次の値は0になり,10進カウンタができます.10秒ごとにリセットされ0に戻ることになります.
001 `timescale 1ns / 1ps
002 ///////////////////////////////////////////////////////////////////////////////
003 // Create Date: 2014,11,23
004 // Module Name: counter6
005 ///////////////////////////////////////////////////////////////////////////////
006 module counter6(
007 input wire clk0,
008 output wire [3:0] led
009 );
010
011 assign led=count8;
012 reg[26:0] c=0;
013
014 always @( posedge clk0 )begin
015 if( c==27'd99999999 )
016 c <= 0;
017 else
018 c <= c + 1'b1;
019 end
020
021 reg[2:0] count8=3'b0;
022 always @( negedge c[26] )begin
023 if( count8==3'd5 )
024 count8<=1'b0;
025 else
026 count8 <= count8 + 1'b1;
027 end
028
029 endmodule
001 NET "clk0" LOC = L15; // CLK
002
003 NET "led(3)" LOC = L14; // LD3
004 NET "led(2)" LOC = N14; // LD2
005 NET "led(1)" LOC = M14; // LD1
006 NET "led(0)" LOC = U18; // LD0
LED(LD3〜LD0)はカウントアップされ0101の後0000に戻ります.
000→001→010→011→100→101→000
5のときリセットすることのにより6進カウンタができます.6秒ごとにリセットされ0に戻ることになります.
6進カウンタと10進カウンタを結合して60進カウンタを作成する.10進カウンタから6進カウンタへ繰り上がるようにすること.6進部分の3ビットをLED(LD6,5,4)に10進数部分の4ビットをLED(LD3,2,1,0)に表示するようにすること.
○○○|○○○○
654|3210
6進数|10進数
このカウンタは60秒で0に戻る1分計になる.
まずは,ヒントを読む前に自分で考えてみてください.
(1)count10を4ビット(3番〜0番),count6を3ビット(2番〜0番)にする.
(2)count6は
always @( negedge count10[3] )begin
のように記述して,count10の3番ビットの立下りを繰り上がりに利用できる
(3)led[6:4]をcount6で,led[3:0]をcount10でassignする
このプログラムは2桁の7セグLEDに60進数を表示するための基礎になります.
6進,10進のドッキングに成功したら,スピードアップに挑戦してみてください.
ここでは,4桁7セグLEDのを使い方を紹介します.扱うプログラムは以下の通りです.
図2-1,-2にしたがって,ブレッドボード上に7segLED回路を作成してください.
リファレンス | 型番・値 | 数量 |
---|---|---|
LED1 | OSL40562-LG | 1 |
IC1 | TD62083APG | 3 |
R1~8 | 220Ω 1/4W | 8 |
ジャンパ | 電線 | 10本程度 |
スライドスイッチ(SW7〜SW0)のON/OFFをそのままLED(LD7〜LD0)に伝える簡単プログラムです.
001 `timescale 1ns / 1ps
002 ///////////////////////////////////////////////////////////////////////////////
003 // Create Date: 2014,11,23
004 // Module Name: sw_led
005 ///////////////////////////////////////////////////////////////////////////////
006 module sw_led(
007 input wire [7:0] sw,
008 output wire [7:0] led
009 );
010 assign led=sw;
011
012 endmodule
001 NET "led(7)" LOC = N12; // LD7
002 NET "led(6)" LOC = P16; // LD6
003 NET "led(5)" LOC = D4; // LD5
004 NET "led(4)" LOC = M13; // LD4
005
006 NET "led(3)" LOC = L14; // LD3
007 NET "led(2)" LOC = N14; // LD2
008 NET "led(1)" LOC = M14; // LD1
009 NET "led(0)" LOC = U18; // LD0
010
011 NET "sw(7)" LOC=E4; // SW7
012 NET "sw(6)" LOC=T5; // SW6
013 NET "sw(5)" LOC=R5; // SW5
014 NET "sw(4)" LOC=P12; // SW4
015
016 NET "sw(3)" LOC=P15; // SW3
017 NET "sw(2)" LOC=C14; // SW2
018 NET "sw(1)" LOC=D14; // SW1
019 NET "sw(0)" LOC=A10; // SW0
実行に成功するとスライドスイッチのON/OFFにより,LEDが点滅します.
次に,スライドスイッチにより,7セグLEDを制御します.図2-3を見ると明らかなように7セグの制御信号は12本あります.このうち,A側(アノード側)をスライドスイッチで制御するのがこのプログラムです.同時にLEDも点灯します.K側(カソード側)はwire型のlineにより固定です.
001 `timescale 1ns / 1ps
002 //////////////////////////////////////////////////////////////////////////////////
003 // Create Date: 17:33:00 10/13/2015
004 // Module Name: sw_led7seg
005 //////////////////////////////////////////////////////////////////////////////////
006 module sw_led7seg(
007 input wire [7:0] sw,
008 output wire [7:0] led,
009 output wire [7:0] seg7,
010 output wire [3:0] line
011 );
012 assign line=4'b1;
013 assign led=sw;
014 assign seg7=sw;
015 endmodule
001 NET "led(7)" LOC = N12; // LD7
002 NET "led(6)" LOC = P16; // LD6
003 NET "led(5)" LOC = D4; // LD5
004 NET "led(4)" LOC = M13; // LD4
005
006 NET "led(3)" LOC = L14; // LD3
007 NET "led(2)" LOC = N14; // LD2
008 NET "led(1)" LOC = M14; // LD1
009 NET "led(0)" LOC = U18; // LD0
010
011 NET "sw(7)" LOC = E4; // SW7
012 NET "sw(6)" LOC = T5; // SW6
013 NET "sw(5)" LOC = R5; // SW5
014 NET "sw(4)" LOC = P12; // SW4
015
016 NET "sw(3)" LOC = P15; // SW3
017 NET "sw(2)" LOC = C14; // SW2
018 NET "sw(1)" LOC = D14; // SW1
019 NET "sw(0)" LOC = A10; // SW0
020
021
022 NET "seg7(7)" LOC = T8; // IO26 h
023 NET "seg7(6)" LOC = V8; // IO28 g
024 NET "seg7(5)" LOC = V16; // IO15 f
025 NET "seg7(4)" LOC = T10; // IO24 e
026
027 NET "seg7(3)" LOC = V10; // IO25 d
028 NET "seg7(2)" LOC = N8; // IO27 c
029 NET "seg7(1)" LOC = V15; // IO16 b
030 NET "seg7(0)" LOC = V13; // IO17 a
031
032 NET "line(3)" LOC = U10; // IO11 00
033 NET "line(2)" LOC = R8; // IO12 01
034 NET "line(1)" LOC = M8; // IO13 02
035 NET "line(0)" LOC = U8; // IO14 03
ボード端子名 | VCC | GND | IO1 | IO2 | IO3 | IO4 | IO5 | IO6 | IO7 | IO8 | IO9 | IO10 | IO11 | IO12 | IO13 | IO14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
FPGAピン番号 | 3.3[V] | GND | U16 | U15 | U13 | M11 | R11 | T12 | N10 | M10 | U11 | R10 | U10 | R8 | M8 | U8 |
ボード端子名 | VU | IO15 | IO16 | IO17 | IO18 | IO19 | IO20 | IO21 | IO22 | IO23 | IO24 | IO25 | IO26 | IO27 | IO28 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
FPGAピン番号 | 5[V] | V16 | V15 | V13 | N11 | T11 | V12 | P11 | N9 | V11 | T10 | V10 | T8 | N8 | V8 |
sw(7)〜sw(0)と7セグLEDの点灯するLEDの位置との関係表にまとめてください.
前に作成した60進カウンタを利用して7セグLEDに数字を表示させることにします.プログラムはまだ不完全です.完成させてください.
001 `timescale 1ns / 1ps
002 //////////////////////////////////////////////////////////////////////////////////
003 // Create Date: 18:38:20 10/13/2015
004 // Module Name: seg7_counter10
005 //////////////////////////////////////////////////////////////////////////////////
006 module seg7_counter10(
007 input wire clk0,
008 output wire [7:0] seg7,
009 output wire [3:0] line,
010 output wire [6:0] led
011 );
012 assign line=4'b0001;
013 assign led[6:4] = count6;
014 assign led[3:0] = count10;
015 reg[26:0] c=0;
016
017 assign seg7[6:0] = disp;
018 assign seg7[7] = 0;
019
020 always @( posedge clk0 )begin
021 if( c==27'd99999999 )
022 c <= 0;
023 else
024 c <= c + 1'b1;
025 end
026
027 reg[3:0] count10=4'b0;
028 reg[6:0] disp=7'b0;
029
030 always @( negedge c[26] )begin
031 if(count10==4'd0)
032 disp<=7'b1110000;
033 else if(count10==4'd1)
034 disp<=7'b0001111;
035 else if(count10==4'd2)
036 disp<=7'b1110000;
037 else if(count10==4'd3)
038 disp<=7'b0001111;
039 else if(count10==4'd4)
040 disp<=7'b1110000;
041 else if(count10==4'd5)
042 disp<=7'b0001111;
043 else if(count10==4'd6)
044 disp<=7'b1110000;
045 else if(count10==4'd7)
046 disp<=7'b0001111;
047 else if(count10==4'd8)
048 disp<=7'b1110000;
049 else if(count10==4'd9)
050 disp<=7'b0001111;
051
052 if( count10==4'd9 )
053 count10<=1'b0;
054 else
055 count10 <= count10 + 1'b1;
056 end
057
058 reg[2:0] count6=3'b0;
059 always @( negedge count10[3] )begin
060 if( count6==3'd5 )
061 count6 <= 1'b0;
062 else
063 count6 <= count6 + 1'b1;
064 end
065
066 endmodule
001 // seg7_counter10.ucf
002 NET "clk0" LOC = L15; // CLK
003
004 NET "led(6)" LOC = P16; // LD6
005 NET "led(5)" LOC = D4; // LD5
006 NET "led(4)" LOC = M13; // LD4
007
008 NET "led(3)" LOC = L14; // LD3
009 NET "led(2)" LOC = N14; // LD2
010 NET "led(1)" LOC = M14; // LD1
011 NET "led(0)" LOC = U18; // LD0
012
013 NET "seg7(7)" LOC = T8; // IO26 h
014 NET "seg7(6)" LOC = V8; // IO28 g
015 NET "seg7(5)" LOC = V16; // IO15 f
016 NET "seg7(4)" LOC = T10; // IO24 e
017
018 NET "seg7(3)" LOC = V10; // IO25 d
019 NET "seg7(2)" LOC = N8; // IO27 c
020 NET "seg7(1)" LOC = V15; // IO16 b
021 NET "seg7(0)" LOC = V13; // IO17 a
022
023 NET "line(3)" LOC = U10; // IO11 00
024 NET "line(2)" LOC = R8; // IO12 01
025 NET "line(1)" LOC = M8; // IO13 02
026 NET "line(0)" LOC = U8; // IO14 03
以上,今回はカウンタと7セグLED表示の基礎でした.
『60進カウンタ7セグLED表示』の完成が今日の目標です.7セグLEDの表示方法について理解できるはずです.
次回は,単相同期とディジタル時計の作成を行います.
このドキュメントは http://icrus.org/fpga_atlys_design/ 上にあります.
ssatoh@
足立工科大学 工学部 情報通信工学科