記事概要
- PolarFire SoC Discovery Kitの7SEG LED回路作成
- PolarFire SoC Discovery KitのHDL作成
- PolarFire SoC Discovery Kitの7SEG点灯実機確認
7SEG LED回路
自宅に転がっていた7セグ(実際は7セグ+小数点表示用ドット)のカソードコモンのLEDを利用します。大昔に購入したラズパイスターターキットに入っていたものです。どこのメーカの製品なのかはわかりませんが、奇跡的にデータシートだけは保存していたので、下記のようにブレッドボード上で回路を作成しました。
7セグLED ピン | コネクタピン | SoC外部ピン | 抵抗 | 備考 |
---|---|---|---|---|
1 | IO5 | W16(HSIO73PB0) | 220Ω | 左下(E) |
2 | IO4 | T17(HSIO55PB0) | 220Ω | 下(D) |
3 | GND | - | - | GND |
4 | IO3 | Y19(HSIO67PB0) | 220Ω | 右下(C) |
5 | IO8 | Y15(HSIO74PB0) | 220Ω | ドット(DP) |
6 | IO2 | W20(HSIO68PB0) | 220Ω | 右上(B) |
7 | IO1 | V18(HSIO57PB0) | 220Ω | 上(A) |
8 | GND | - | - | GND |
9 | IO7 | V15(HSIO75PB0) | 220Ω | 左上(F) |
10 | IO6 | AA17(HSIO68PB0) | 220Ω | 中央(G) |
また、ラズパイで7セグLEDを試した際と同じ電圧(GPIO:3.3V)で駆動させるために、ジャンパ設定(J49)を1-2closedとして、3.3V出力としました。評価ボードでは8bit電圧変換ICで1.8Vから3.3Vに昇圧されています。
FPGAデザイン作成
HDLソースコード
1秒ごとに1ずつカウントアップする回路を作成しました。
module led_7seg(
input i_clk,
input i_rst_n,
output [6:0] o_led_7seg,
output o_dot
);
// parameter
parameter P_W_CTR = 28; // width of counter
parameter P_W_NUM = 4; // width of number
parameter P_CTR_1SEC = 28'd200000000; // 200MHz
// variables
reg [P_W_CTR-1:0] r_ctr;
reg [P_W_NUM-1:0] r_num;
wire w_count_up;
// counter
always @(posedge i_clk or negedge i_rst_n) begin
if (~i_rst_n) r_ctr <= 28'h0;
else if (w_count_up) r_ctr <= 28'h0;
else r_ctr <= r_ctr + 28'h1;
end
// increment number
always @(posedge i_clk or negedge i_rst_n) begin
if (~i_rst_n) r_num <= 4'h0;
else if (w_count_up) r_num <= r_num + 4'h1;
end
// timing count up
assign w_count_up = (r_ctr == (P_CTR_1SEC - 28'd1)) ? 1'b1 : 1'b0;
// output
//// convert number to 7 seg
assign o_led_7seg = f_num2seg(r_num);
//// fix dot to 1
assign o_dot = 1'b1;
// convert a number to 7 seg
function [6:0] f_num2seg(
input [3:0] i_num
);
case (i_num)
// LED ABCDEFG
4'h0: f_num2seg = 7'b1111110; // 0
4'h1: f_num2seg = 7'b0110000; // 1
4'h2: f_num2seg = 7'b1101101; // 2
4'h3: f_num2seg = 7'b1111001; // 3
4'h4: f_num2seg = 7'b0110011; // 4
4'h5: f_num2seg = 7'b1011011; // 5
4'h6: f_num2seg = 7'b1011111; // 6
4'h7: f_num2seg = 7'b1110000; // 7
4'h8: f_num2seg = 7'b1111111; // 8
4'h9: f_num2seg = 7'b1111011; // 9
4'hA: f_num2seg = 7'b1110111; // A
4'hB: f_num2seg = 7'b0011111; // b
4'hC: f_num2seg = 7'b1001110; // C
4'hD: f_num2seg = 7'b0111101; // d
4'hE: f_num2seg = 7'b1001111; // E
4'hF: f_num2seg = 7'b1000111; // F
default: f_num2seg = 7'b0000000;
endcase
endfunction
endmodule
シミュレーションコード
クロックとリセット信号を駆動させて、内部信号を出力するテストベンチを作成しました。
`timescale 1ns/100ps
module test_led_7seg;
// signal for DUT
logic clk;
logic rst_n;
logic [6:0] led_7seg;
logic led_dot;
// simulate clock and reset
initial begin
clk = 1'b0;
forever begin
#2.5 clk = ~clk;
end
end
initial begin
rst_n = 1'b0;
#100 rst_n = 1'b1;
end
// display
initial begin
$display("=== Seven Segment Decoder Test Start ===");
#0
$monitor("led_7seg.r_num = %h, led_7seg = %b, led_dot = %h at %t", dut.r_num, led_7seg, led_dot, $time);
// stop after 31 seconds
#15000;
$stop;
end
// DUT
led_7seg #(
.P_CTR_1SEC (28'd100)
) dut (
.i_clk (clk),
.i_rst_n (rst_n),
.o_led_7seg (led_7seg),
.o_dot (led_dot)
);
endmodule
DUTは1秒ごとにカウントアップするため、普通にシミュレーションを作成すると数十秒オーダのシミュレーションになってしまいます。これではシミュレーション実行時間が長すぎるので、モジュールのパラメータを以下のように上書きして、100クロック(=500ns)でインクリメントするように変更しました。
パラメータ | 変更前 | 変更後 |
---|---|---|
P_CTR_1SEC | 28'd200000000 | 28'd100 |
Libero SoCプロジェクト
#1で作成したプロジェクトをベースにして作成します。
SmartDesignで下記のようなデザインを作成しました。
HDLソースのインポート
以下2つのHDLソースをSmartDesignにインポートします。Debounce回路では、リセット入力用のスイッチがチャタリングして極短期間に複数回のリセットが繰り返されることを防止できるようです。
- Debounce回路(デモデザインからの流用回路)
- 7SEG LED回路(先ほど作成した回路)
- Design Flowタブの[Create Design > Create HDL]を右クリックして、Import Files...を選択し、インポート対象のファイルを指定する。インポートに成功すると、Design HierarchyタブのUser HDL Source Files直下にHDLが追加される。
- 追加されたHDLファイルをSmartDesignタブ上にドラッグ&ドロップすると、IPがインスタンスされる。
- 必要な接続を追加する。
- その後は#2と同様に、Design Check, Generate Component, Build Hierarchy, Select a rootを実施する。
シミュレーションコードのインポート
- Design Flowタブの[Create Design > Verify Pre-Synthesized Design > Simulate]を右クリックして、Import Files...を選択し、対象のテストベンチファイルをインポートする。
- stimulus HierarchyタブのBuild Hierarchをクリックする。
- Design Flowタブの[Create Design > Verify Pre-Synthesized Design > Simulate]を右クリックして、[Organize Input Files > Organize Simulation Files]を選択する。
- 表示されたウィンドウでUserを選択した後に、テスト対象のファイルをStimulus filesからAssociated Stimules filesにAddする。
- [Project > Project Setting]を選択し、表示されたウィンドウで[Simulation options DO file]を選択し以下のように設定を変更して、Saveして、Closeする。
項目 | 設定 |
---|---|
Testbench module name | テストベンチのトップモジュール名(今回はtest_led_7seg) |
Simulation runtime | -all |
シミュレーション実行
- Design Flowタブの[Create Design > Verify Pre-Synthesized Design > Simulate]を右クリックして、Runをクリックする。
- シミュレーションが実行され、ログが表示される。
# === Seven Segment Decoder Test Start ===
# led_7seg.r_num = 0, led_7seg = 1111110, led_dot = 1 at 0
# led_7seg.r_num = 1, led_7seg = 0110000, led_dot = 1 at 598000
# led_7seg.r_num = 2, led_7seg = 1101101, led_dot = 1 at 1098000
# led_7seg.r_num = 3, led_7seg = 1111001, led_dot = 1 at 1598000
# led_7seg.r_num = 4, led_7seg = 0110011, led_dot = 1 at 2098000
# led_7seg.r_num = 5, led_7seg = 1011011, led_dot = 1 at 2598000
# led_7seg.r_num = 6, led_7seg = 1011111, led_dot = 1 at 3098000
# led_7seg.r_num = 7, led_7seg = 1110000, led_dot = 1 at 3598000
# led_7seg.r_num = 8, led_7seg = 1111111, led_dot = 1 at 4098000
# led_7seg.r_num = 9, led_7seg = 1111011, led_dot = 1 at 4598000
# led_7seg.r_num = a, led_7seg = 1110111, led_dot = 1 at 5098000
# led_7seg.r_num = b, led_7seg = 0011111, led_dot = 1 at 5598000
# led_7seg.r_num = c, led_7seg = 1001110, led_dot = 1 at 6098000
# led_7seg.r_num = d, led_7seg = 0111101, led_dot = 1 at 6598000
# led_7seg.r_num = e, led_7seg = 1001111, led_dot = 1 at 7098000
# led_7seg.r_num = f, led_7seg = 1000111, led_dot = 1 at 7598000
# led_7seg.r_num = 0, led_7seg = 1111110, led_dot = 1 at 8098000
# led_7seg.r_num = 1, led_7seg = 0110000, led_dot = 1 at 8598000
# led_7seg.r_num = 2, led_7seg = 1101101, led_dot = 1 at 9098000
# led_7seg.r_num = 3, led_7seg = 1111001, led_dot = 1 at 9598000
# led_7seg.r_num = 4, led_7seg = 0110011, led_dot = 1 at 10098000
# led_7seg.r_num = 5, led_7seg = 1011011, led_dot = 1 at 10598000
# led_7seg.r_num = 6, led_7seg = 1011111, led_dot = 1 at 11098000
# led_7seg.r_num = 7, led_7seg = 1110000, led_dot = 1 at 11598000
# led_7seg.r_num = 8, led_7seg = 1111111, led_dot = 1 at 12098000
# led_7seg.r_num = 9, led_7seg = 1111011, led_dot = 1 at 12598000
# led_7seg.r_num = a, led_7seg = 1110111, led_dot = 1 at 13098000
# led_7seg.r_num = b, led_7seg = 0011111, led_dot = 1 at 13598000
# led_7seg.r_num = c, led_7seg = 1001110, led_dot = 1 at 14098000
# led_7seg.r_num = d, led_7seg = 0111101, led_dot = 1 at 14598000
タイミング制約
#2では作成しませんでしたが、今回は作成します。といっても、インスタンスしたIPで自動に設定されるタイミング制約を利用しているだけです。
- Design Flowタブの[Constraints > Manage Constraints]を右クリックし、Open Constraint Manager viewを選択する。
- 表示されたview画面でTimingタブを開く。
- Derive Constraintsをクリックすると、自動的に制約ファイル(top_derived_constraints.sdc)が生成される。
中身を確認してみると、クロック制約が与えられているだけのようでした。
create_clock -name {REF_CLK_0} -period 20 [ get_ports { REF_CLK_0 } ]
create_generated_clock -name {PF_CCC_C0_0/PF_CCC_C0_0/pll_inst_0/OUT0} -multiply_by 4 -source [ get_pins { PF_CCC_C0_0/PF_CCC_C0_0/pll_inst_0/REF_CLK_0 } ] -phase 0 [ get_pins { PF_CCC_C0_0/PF_CCC_C0_0/pll_inst_0/OUT0 } ]
論理合成
#2と同様。
ピン制約
以下のようなピン制約を与えました。
ポート名 | SoC外部ピン | 方向 |
---|---|---|
LED_DOT | Y15 | OUTPUT |
LED_SEG[0] | AA17 | OUTPUT |
LED_SEG[1] | V15 | OUTPUT |
LED_SEG[2] | W16 | OUTPUT |
LED_SEG[3] | T17 | OUTPUT |
LED_SEG[4] | Y19 | OUTPUT |
LED_SEG[5] | W20 | OUTPUT |
LED_SEG[6] | V18 | OUTPUT |
REF_CLK | R18 | INPUT |
switch_i | T19 | INPUT |
配置配線
#2と同様。
タイミング検証
タイミング制約を追加したので、タイミング検証も実施します。
- Design Flowタブの[Implement Design > Verify Post Layout Implementation > Verify Timing]を右クリックし、Runを選択する。タイミング検証が実施される。
- Design Flowタブの[Implement Design > Verify Post Layout Implementation > Open SmartTime]をダブルクリックする。
- 表示されたSmartTimeのウィンドウでSummaryを確認すると、各クロックの動作周波数を確認できる。
今回はPF_CCC_Cから出力されるクロックの動作周波数が500MHzとなっており、200MHzを下回っているので問題ないと思われます。ただ、ちょうど500MHzになっているため、正しくタイミング検証できているか疑わしいです。タイミングがシビアになりそうなデザインに取り組む際には、タイミング検証についてより詳細に確認・調査したいと思います。
書き込み
#2と同様。
実機動作確認
以下の写真のように設計通りに光ってカウントアップされました。
SW1を押すと再度0からカウントアップされました。
今後したいこと
-
デモデザイン([#1]
(https://qiita.com/tatsu11/items/9dd004fa788b029f0976)で完了) - FPGA開発(#2と今回で完了)
- Baremetal Application開発
- Linux Application開発
- AXI4によるMSS-Fabricの協調動作開発
- mikroBusインタフェースの活用
- Raspberry piインタフェースの活用