Skip to content

Instantly share code, notes, and snippets.

@geodenx
Last active April 28, 2024 08:07
Show Gist options
  • Select an option

  • Save geodenx/6708afa4ea5ea811b6f3f593b98fbefe to your computer and use it in GitHub Desktop.

Select an option

Save geodenx/6708afa4ea5ea811b6f3f593b98fbefe to your computer and use it in GitHub Desktop.
Learning CPLD using Verilog

CQ出版『VHDLで学ぶCPLD学習セット』を Quartus II と Verilog-HDL で開発する方法

CQ出版 DesignWave 『VHDLで学ぶCPLD学習セット』は、 Altera の CPLD (MAX7032) を用い、VHDL を Max+PlusII で合成し、実際に動かしてみるという学習セットです。現在(2003年12月)、LeonardoSpectrum-Altera のライセンスが切れてしまったためか、この学習セットは販売されていません。ライセンスが切れたからといって使えないというのももったいないので、Max+PlusII の代わりに Quartus II を用いて利用する方法を紹介します。

image

学習セットでは VHDL での開発方法が記載されていますが、ここでは Verilog を用いています。

「毎日コミュニケーションズ『CPUの創り方』に掲載されている TD4 CPU を CQ出版『DesignWave 2003年1月号』付録 CPLD 上に実装」は geodenx/td4 に移しました。

Quartus II setup

Quartus II web edition 3.0 のライセンスセットアップをします。詳細は省略。

  • DesignWave 2003年1月号 (付録: CPLD基板) Max+PlusII
  • DesignWave 2003年10月号 (付録: FPGA基板) Quartus II web edition 3.0 を参考に設定。

特に Quartus II のライセンスセットアップ方法を解説している後者。

HOWTO make

  1. New Project Quartusを起動し、File -> New Project Wizerd
  2. New Project Wizerd: Introduction -> Next
  3. New Project Wizerd: Directory, Name, and Top-Level Entity working directoryとprojectの名前、top-level entity (後述 Verilog 中のトップモジュール)を指定。

image

  1. New Project Wizerd: Add Files まだファイルを作っていないので、空欄。

  2. New Project Wizerd: EDA Tool Settings Quartusのみを利用するので、何も指定しない。

  3. New Project Wizerd: Device Family

image

Family: MAX7000S と Yesを選択

  1. New Project Wizerd: Select a Target Device

image

EPM7032SLC44-10 を選択

  • New Project Wizerd: Summary -> Finish
  • Assign Pins 回路図を参考にしながら、Verilog 内の pin の名前と実際のデバイスの pin の対応表を作る。

Assignments -> Assign Pins... Number 1 の pin を選択して、Pin name に GCLK1 (Verilog 内での名前)と入力し、Add。

image

同様に、すべての I/O pin に名前を付ける。 しかし、このダイアログで入力するのは大変なので、一旦 Quartus を終了し、un1001b.csf というテキストファイルを直接編集(公式な方法かどうかは不明)

CHIP(UN1001B)
{
(省略)
        GCLR : LOCATION = Pin_1;
(ここに追加。例えば、)
        OE2 : LOCATION = Pin_2;
}

というように、すべての pin に名前を付ける。

参考: $ grep LOCATION un1001b.csf > grep.csf grep.csf

  1. Verilog ファイルを作成。 例: sample.v (pin 名は上記の grep.csf を利用)

Project -> Add/Remove Files in Project で Verilog ファイルを追加します。

image

  1. Compilation compile, fitting

Processing -> Start Compilation

  1. Program CPLD に回路を書き込む。

Tools -> Programmer

書き込みツールを設定します。

Hardware...

Hardware Setting タブ で Add Hardware...

image

Hardware type: ByteBlasterMV or ByteBlaster II Port LPT1 (プリンタケーブルを繋いでいるポート) を選択。-> OK

image

ByteBlasterMV を選択し、Select Hardware -> Close

image

対応する *.pof ファイルの Program/Configure のチェックボックスを有効化。 プリンタケーブルとボードを接続し、ボードの電源を入れておきます。 Processing -> Start Programming

sample.v では DSW2-3DSW2-4 の2ビットで指定した値を加算しながらインクリメントする 16-bit カウンタが7セグメントLEDに表示される。

Reference

  1. CQ出版 DesignWave 『VHDLで学ぶCPLD学習セット』解説書
  2. CQ出版 『トランジスタ技術』 2001年7月号-2002年1月号 連載 (上記解説書の元記事)
  3. CQ出版 『DesignWave』 2003年10月号
GCLR : LOCATION = Pin_1;
OE2 : LOCATION = Pin_2;
DSW1[1] : LOCATION = Pin_4;
DSW1[2] : LOCATION = Pin_5;
DSW1[3] : LOCATION = Pin_6;
TDI : LOCATION = Pin_7;
DSP_DP : LOCATION = Pin_8;
DSP_G : LOCATION = Pin_9;
DSP_F : LOCATION = Pin_11;
DSP_E : LOCATION = Pin_12;
TMS : LOCATION = Pin_13;
DSP2 : LOCATION = Pin_14;
BZ : LOCATION = Pin_16;
DSW2[0] : LOCATION = Pin_17;
D[0] : LOCATION = Pin_18;
D[1] : LOCATION = Pin_19;
D[2] : LOCATION = Pin_20;
D[3] : LOCATION = Pin_21;
D[4] : LOCATION = Pin_24;
D[5] : LOCATION = Pin_25;
D[6] : LOCATION = Pin_26;
D[7] : LOCATION = Pin_27;
DSP_D : LOCATION = Pin_28;
DSP1 : LOCATION = Pin_29;
DSP_C : LOCATION = Pin_31;
TCK : LOCATION = Pin_32;
DSP_B : LOCATION = Pin_33;
DSP_A : LOCATION = Pin_34;
DSW2[1] : LOCATION = Pin_36;
DSW1[4] : LOCATION = Pin_37;
TDO : LOCATION = Pin_38;
DSW1[5] : LOCATION = Pin_39;
DSW1[6] : LOCATION = Pin_40;
DSW1[7] : LOCATION = Pin_41;
GCLK1 : LOCATION = Pin_43;
DSW1[0] : LOCATION = Pin_44;
module UN1001B(GCLK1, GCLR, OE2,
DSW1, DSW2,
D,
DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP, DSP1, DSP2,
BZ);
input GCLK1, GCLR, OE2;
input [7:0] DSW1; // dip switch 1
input [1:0] DSW2; // dip switch 2
output [7:0] D; // LED
output DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP, DSP1, DSP2; // 7seg
output BZ; // buzzer
assign BZ = 1'b1; // silent
assign D = DSW1;
reg [7:0] seg;
wire [1:0] dot;
always @(posedge GCLK1) begin
seg <= seg + DSW2;
end
assign dot = 2'b01;
led7seg led7seg(OE2, seg, dot,
DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP, DSP1, DSP2);
endmodule // UN1001B
module led7seg(clock, seg, dot,
DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP, DSP1, DSP2);
input clock; // for dynamic light
input [7:0] seg; // two 7segment value
input [1:0] dot; // two 7segment dot
output DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP, DSP1, DSP2;
wire [3:0] wBCD;
wire wDOT;
assign wBCD = clock ? seg[7:4] : seg[3:0];
assign wDOT = clock ? dot[1] : dot[0];
assign DSP1 = clock ? 1'b1 : 1'b0;
assign DSP2 = clock ? 1'b0 : 1'b1;
assign {DSP_A, DSP_B, DSP_C, DSP_D, DSP_E, DSP_F, DSP_G, DSP_DP} = bcd2seg(wBCD, ~wDOT);
function [7:0] bcd2seg;
input [3:0] bcd;
input dot;
case (bcd)
4'h0: bcd2seg <= {7'b0000001, dot};
4'h1: bcd2seg <= {7'b1001111, dot};
4'h2: bcd2seg <= {7'b0010010, dot};
4'h3: bcd2seg <= {7'b0000110, dot};
4'h4: bcd2seg <= {7'b1001100, dot};
4'h5: bcd2seg <= {7'b0100100, dot};
4'h6: bcd2seg <= {7'b0100000, dot};
4'h7: bcd2seg <= {7'b0001111, dot};
4'h8: bcd2seg <= {7'b0000000, dot};
4'h9: bcd2seg <= {7'b0000100, dot};
4'ha: bcd2seg <= {7'b0001000, dot};
4'hb: bcd2seg <= {7'b1100000, dot};
4'hc: bcd2seg <= {7'b1110010, dot};
4'hd: bcd2seg <= {7'b1000010, dot};
4'he: bcd2seg <= {7'b0110000, dot};
4'hf: bcd2seg <= {7'b0111000, dot};
endcase
endfunction // bcd2seg
endmodule // seg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment