0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FPGAボード Shrike Liteをお試し その2

0
Last updated at Posted at 2026-01-18

>>その3

せっかくPmodが1ポート付いているので,7セグLEDでも駆動しながら,ハマったポイントを紹介する.
Liteという名前のわりに,扱いはライトじゃありません.ヤッパリFPGAダッタヨ…

 まずは,シミュレータが欲しいので次の通り準備する.筆者の環境は Windows である.

シミュレータの準備

 Icarus Verilog と GTKWave の組み合わせでGo Configure Hubから直接呼び出せる.

準備1:Icarus Verilogインストール

Icarus Verilogをダウンロード してインストールする.ダブルクリックするだけ.筆者は v12 をインストールした.自動的にGTKWaveもインストールされる.

iveril.png

準備2:Go Configure Hubに設定

iverilog_path.png

 筆者はIcarus Verilogインストール中にPATHの設定チェックマークを外したので,Go Configure Hubのメニューから「Options」-「Settings」で開くダイアログのTools をクリックし,それぞれの実行ファイルがあるフォルダパスを設定した.
forge9.png

テストベンチを作る

tb1:新規テストベンチ

 Go Configure Hub 左側のエクスプローラで右クリックして新規テストベンチを作る.
 出来たファイル(テンプレートが生成される)に,Verilogでテストを書く.テストベンチの中で,テスト対象のモジュールをインスタンシエートすると,なぜがそのモジュールが見えないと言ってくるが,無視して進める(テスト対象のモジュール名とそのファイル名を合わせるとワーニングが消える).

forge13.png

生成されるテストベンチ

// Custom testbench

`timescale 1ns / 1ps

module top_tb;

  initial begin

    $dumpfile ("top_tb.vcd");
    $dumpvars (0, top_tb);

    $finish;
  end

endmodule

tb2:シミュレータ起動

 合成したら,Go Configure Hubのメニューにある 「Run RTL Simulation」 ボタンをクリックする.

forge10.png

 ダイアログが開き,作ったテストベンチがリストアップされる.所望のものを選んで「Simulate」ボタンをクリックするとシミュレーションが走り,しばらくするとGTKWaveが開く.

forge11.png

forge12.png

7セグ4桁駆動

ハードウェア

1.png

仕様など

 8桁あるPmodモジュールを使ったが,大きなレジスタを使うとP&RがFitしなかったため,4桁で我慢することにした.Utilizedはせいぜい10%程度なので,うまく組めば何とかはなりそう.

リソース少なめなのは致し方なし

 クロックリソースがあまり無いようなので,なるべくシステムクロック以外を使わないように組む(always の処理の中にカウンタを入れた).ドキュメントにはクロックドメインは2つまでと書いてあるので,クロック2つは使えるのかもしれない.
 Go Configure Hub内の設定で,P&Rツールのバージョンを選べる.新しいものは,物理制約ファイルに対応しているようだが,試していない.

記述できるVerilog文法は貧弱かも

 Verilog 2005に対応しているらしい.
多次元のRegisterは宣言できないので,1次元で確保して,{目的行 × 1行の桁数 + 目的桁}でアクセスすることになる.
 そして,
次の演算でハマった.

はまりポイント

 segment_select は4ビットのレジスタであるが,どうやら segment_select * 8 も4ビットになるようだ.掛ける数を明示的に 7'd8 とすることで,実機でも所望の波形となった.
 困ったことに,元の記述の場合,シミュレータでは狙った波形になっており,実機で別な挙動になるので,当初は????となり,気づくのに時間がかかった.

// bad        data <= segment_map[segment_select * 8 + counter_16bit[2:0]];
              data <= segment_map[segment_select * 7'd8 + counter_16bit[2:0]];  // good

コード全体

(* top *) module digit8_7seg(
  (* iopad_external_pin, clkbuf_inhibit *) input clk,
  (* iopad_external_pin *) output LED,
  (* iopad_external_pin *) output LED_en,
  (* iopad_external_pin *) output clk_en,
  (* iopad_external_pin *) output sclk,
  (* iopad_external_pin *) output sclk_en,
  (* iopad_external_pin *) output rclk,
  (* iopad_external_pin *) output rclk_en,
  (* iopad_external_pin *) output srclr,
  (* iopad_external_pin *) output srclr_en,
  (* iopad_external_pin *) output serial_data,
  (* iopad_external_pin *) output serial_data_en
);
// only single dimension. multi dimensional resistor is prohibited
  wire [127:0] segment_map = {8'b1000_1110,     //F
                              8'b1111_0010,
                              8'b0111_1010,
                              8'b1001_1100,     //C
                              8'b0011_1110,
                              8'b1110_1110,     //A
                              8'b1111_0110,     //9
                              8'b1111_1110,
                              8'b1110_0000,
                              8'b1011_1110,
                              8'b1011_0110,     //5
                              8'b0110_0110,
                              8'b1111_0010,     //3
                              8'b1101_1010,
                              8'b0110_0000,
                              8'b1111_1100};    //0

  reg [3:0] counter_16bit=0;
  reg [1:0] digit_select=0;   // for 4digit
  reg [3:0] segment_select=0; // for 8segment LED(this is index of segment_map)  
  reg [15:0] target_number = 16'h0000;
  reg [9:0] number=0;
  reg data=0;
  reg sclk_reg=0;
  reg rclk_reg=0;

  assign LED_en = 1'b1;   assign clk_en = 1'b1;
  assign sclk_en = 1'b1;  assign rclk_en = 1'b1;
  assign serial_data_en = 1'b1;
  assign srclr_en = 1'b1;
  assign LED = 1;
  assign serial_data = data;
  assign rclk = rclk_reg;
  assign srclr = 1;
  assign sclk = sclk_reg;

  reg [15:0] counter=0;

  always @ (posedge clk)begin
    
    if (counter == 6_250) begin  // 4000Hz
        counter <= 16'b0;
        sclk_reg <= ~sclk_reg;
        number <= number + 10'b1;
        if(number == 10'd1023)begin
            target_number <= target_number + 16'b1;
        end
        
        if(sclk_reg)begin
          if(counter_16bit == 4'd0)begin
              rclk_reg <= 1;
          end else begin
              rclk_reg <= 0;
          end

          counter_16bit <= counter_16bit + 4'b1;
    
          if(counter_16bit == 4'd0)begin          // submitting of every digit data uses 16 clocks
              digit_select <= digit_select + 2'b1;  // for next digit
          end
  
          if(counter_16bit[3])begin
              segment_select = target_number >>(digit_select*4);
//            data <= segment_map[segment_select * 8 + counter_16bit[2:0]];
              data <= segment_map[segment_select * 7'd8 + counter_16bit[2:0]];
          end else begin
            if(counter_16bit[2] && (counter_16bit[1:0] == digit_select))begin
              data <= 1'b0;
            end else begin
              data <= 1'b1;
            end

          end
        end else begin
        end
    end else if(counter == 6000)begin
        rclk_reg <= 0;
        counter <= counter + 1'b1;
    end else begin
        counter <= counter + 1'b1;
    end
  end
  
endmodule

テストベンチとか

// Custom testbench
`timescale 1ns / 1ps

module tb_tb;
reg clk=1;

digit8_7seg digit8_7seg_inst(
.clk(clk)
);

  initial begin
    $dumpfile ("tb_tb.vcd");
    $dumpvars (0, tb_tb);
    #10000000; $finish;
  end
  
  always begin
    #1; clk <= ~clk;
  end

endmodule

Pmodモジュールの電気図

v0_1.png

メモ:PLL

 今回はPLLは使っていないので,単なるメモ.
 クロックソースは3つある.PLLとオシレータ(OSC)とLaC(Logic as Clock).
 PLLとオシレータは内部クロック生成用に使える.PLLはクロックソースとしてオシレータまたはGPIO2を通して信号をを受け取る.
 内蔵オシレータの周波数は50MHzである.
 OSCとPLLとLaCsはBRAMとFPGAコアを駆動できる.
 GPIOへ外部からLaC信号を入力できる.
LaCは,コアからクロックツリー入力へ論理信号を通すために使える.
 同時に使えるクロックドメインは2つまでである.

その他

 このボードの入力電源はUSBの5Vであり,ボード上の2種のレギュレータで,

  • I/O用の3.3V
  • RP2040とForgeFPGA用の1.1V
    を作っている.
     1.1V系はコンデンサの定数設定に問題があるらしく,RP2040の電源が入ると揺れが大きい.これに伴い,FPGAのコンフィグレーションに問題が発生することがあるらしい.RP2040の動作周波数を125MHz程度まで落とすと比較的安定するらしい.
     対処する場合は,C8とC7コンデンサをそれぞれ変更することで1.1V電源が安定する.
  • C8 100nF → 2.2uF
  • C7 1uF → 100nF
    コンデンサのサイズは1005,ハンドソルダー用のパッドではないので,交換はそれなりに難しい.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?