第2回 レディーゴー(カウンタと7セグLED制御)
それにつけてもDFTの公式
\[ F_k=\frac{1}{N}\sum_{n=0}^{N-1}f_n e^{-j\frac{2\pi nk}{N}} \]は重要です

内 容


2-1. カウンタ

本日はカウンタと7セグLEDについて解説と実習を行います.先ずは,前回の「LEDチカチカ」プログラムをよく読んで,理解してください.

ここでは,カウンタをいくつか紹介し,それをもとに皆さんにその発展形を考えていってもらいます.扱うカウンタは以下の通りです.

  1. 4ビットカウンタ
  2. 8ビットカウンタ
  3. 速い8ビットカウンタ
  4. 10進カウンタ
  5. 6進カウンタ
  6. 6進10進カウンタ

参考資料

本日の実習に参考になる資料のURLを示します.

  1. Atlysマニュアル http://www.digilentinc.com/data/products/atlys/atlys_rm_v2.pdf
  2. Vmodブレッドボード回路図 https://www.digilentinc.com/Data/Documents/Product%20Documentation/VmodBB.pdf
  3. Verilog 簡易文法書 http://www.icrus.org/machida/product/verilog.pdf

4ビットカウンタ

はじめは4ビットカウンタです.4ビットですから0〜15までを数え上げることができます.ここでは,LEDチカチカを利用して1秒に1カウントアップするようにしています.先ずはリストを入力して実行しててみてください.もちろん入力前には新プロジェクトを作って,ISEを再起動するのを忘れないでください.

リスト2-1 bit_4_counter.v


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

解説

  1. 006 モジュールの開始 モジュール名 bit_4_counter
  2. 007 モジュール入力clk0 →クロック入力(100MHz)
  3. 011 led(4ビット)にcount16(4ビット)を結線する
  4. 014〜019 LEDチカチカと同じ1秒生成
  5. 021 count16を4ビット(3〜0番)のレジスタ変数に宣言する
  6. 022 c[26]の立下りで起動するalwaysブロック開始
  7. 023 無条件でcount16を1増加する

リスト2-2 bit_4_counter.ucf


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

解説

  1. 001 clk0をクロック発振器(100MHz)につながるピンに結線する
  2. 003〜006 led4ビットをLEDにつながるピンに結線する.LD3〜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秒間)をカウントアップできます.

問題 8ビットカウンタ

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

回答

リスト2-3_リスト2-4

問題 8ビットカウンタ加速

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

回答

リスト2-5_リスト2-6

しっかりマスターして,いつでもカウンタのスピードアップ,スピードダウンできるようにしてください.

10進カウンタ,6進カウンタ

10進6進カウンタは簡単ですので,ソースを読んで理解できたら,ISEに入力して実行してみてください.変更点を確認してください.

リスト2-7 counter10.v


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

解説

  1. 023 count16が9のとき,つぎの値を0にリセットします.
  2. 026 023の条件が不成立のときcount16の値を1増加します.

リスト2-8 counter10.ucf


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に戻ることになります.

リスト2-9 counter6.v


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

解説

  1. 024 023が成立のとき(count8が5)のとき,つぎの値を0にリセットします.
  2. 026 023が不成立のときcount8の値を1増加します.

リスト2-10 counter6.ucf


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進カウンタを作る

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-11_リスト2-12

このプログラムは2桁の7セグLEDに60進数を表示するための基礎になります.

6進,10進のドッキングに成功したら,スピードアップに挑戦してみてください.


2-2. 7セグLED制御

ここでは,4桁7セグLEDのを使い方を紹介します.扱うプログラムは以下の通りです.

  1. SW to LED
  2. SW to 7seg
  3. 60進カウンタ7seg表示

準備 7segLED回路作成

図2-1,-2にしたがって,ブレッドボード上に7segLED回路を作成してください.

図2-1 4桁7セグ表示回路 回路図

図2-2 4桁7セグ表示回路 作成例

図2-3 4桁7セグ表示器(OSL40562-LG)内部回路図

表2-1 4桁7セグ表示回路 部品表

リファレンス型番・値数量
LED1OSL40562-LG1
IC1TD62083APG3
R1~8220Ω 1/4W8
ジャンパ電線10本程度

SW to LED

スライドスイッチ(SW7〜SW0)のON/OFFをそのままLED(LD7〜LD0)に伝える簡単プログラムです.

リスト2-13 sw_led.v


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

解説

リスト2-14 sw_led.ucf


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が点滅します.

SW to 7セグLED

次に,スライドスイッチにより,7セグLEDを制御します.図2-3を見ると明らかなように7セグの制御信号は12本あります.このうち,A側(アノード側)をスライドスイッチで制御するのがこのプログラムです.同時にLEDも点灯します.K側(カソード側)はwire型のlineにより固定です.

リスト2-15 sw_led7seg.v


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

解説

リスト2-16 sw_led7seg.ucf


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

解説

(参考) 表2-2 ブレッドボード(VmodBB)の端子とデバイスのピン番号の対応

ボード端子名VCCGNDIO1IO2IO3IO4IO5IO6IO7IO8IO9IO10IO11IO12IO13IO14
FPGAピン番号3.3[V]GNDU16U15U13M11R11T12N10M10U11R10U10R8M8U8

ボード端子名VUIO15IO16IO17IO18IO19IO20IO21IO22IO23IO24IO25IO26IO27IO28
FPGAピン番号5[V]V16V15V13N11T11V12P11N9V11T10V10T8N8V8

問題 sw(7)〜sw(0)と7セグLEDとの関係をまとめよ

sw(7)〜sw(0)と7セグLEDの点灯するLEDの位置との関係表にまとめてください.

60進カウンタ7セグLED表示

前に作成した60進カウンタを利用して7セグLEDに数字を表示させることにします.プログラムはまだ不完全です.完成させてください.

リスト2-17 seg7_counter10.v


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

解説

リスト2-18 seg7_counter10.ucf


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@

足立工科大学 工学部 情報通信工学科