verilog

2021年12月13日 (月)

verilog事始め(sample#4 @Gowin RUNBER board)

2021/12/13
初版

verilog事始め(sample#4 @Gowin RUNBER board)

verilog事始め(sample#4 @Gowin RUNBER board)

概要

本記事は「verilog事始め(Gowin RUNBER board で始める)」の続きとしてverilogの追加サンプルを紹介したものである。

sample#4(stopwatch)

例として、sample#3をベースに以下を追加して、stopwatchを実現する。
(一部、インタフェースの付録のものを参考にした)

top_stopwatch.v

module top_stopwatch ( input clk, input [7:0] sw, input [7:0] btn, output [7:0] seg, output [3:0] seg_dig, output [7:0] led ); wire rst, key1, key2; wire tgl, zrst; // all LEDs off // assign led = 8'b0000_0000; // for binary to BCD convert reg [3:0] ones, tens, huns, thous; integer i; wire [7:0] seg_a, seg_b, seg_c, seg_d; wire [3:0] a, b, c, d; reg [3:0] tim_a, tim_b, tim_c, tim_d; reg [15:0] timer_count; assign a = {sw[0],sw[1],sw[2],sw[3]}; assign b = {sw[4],sw[5],sw[6],sw[7]}; assign c = ~{btn[0],btn[1],btn[2],btn[3]}; assign d = ~{btn[4],btn[5],btn[6],btn[7]}; wire clk0_1s; clkdiv(.clk(clk), .rst(1'b0), .max(24'd119999_99), .tc(clk0_1s)); debounce dbnc_1 (.clk(clk), .rst(rst), .key_in(btn[0]), .key_out(key1)); debounce dbnc_2 (.clk(clk), .rst(rst), .key_in(btn[7]), .key_out(key2)); toggle tgl_2 (.clk(clk), .rst(rst), .in(key2), .out(tgl)); assign led[3] = ~key1; // for debug assign zrst = ~key1; assign led[7] = ~tgl; // for debug always @ (posedge(clk0_1s)) begin if (tgl == 1'b1) begin timer_count = timer_count + 1; end else begin if (zrst == 1'b1) begin timer_count = 16'd00; end end //<<--------------------------------------------------- // binary to BCD convert // algorithm reference: // https://bravo-fpga.blogspot.com/2010/10/bin2bcd_29.html //reg [3:0] ones, tens, huns, thous; //integer i; thous = 0; huns = 0; tens = 0; ones = 0; for(i=15; i>=0; i=i-1) begin {thous, huns, tens, ones} = {thous[2:0],huns,tens,ones,timer_count[i]}; if(ones >= 5 && i > 0) ones = ones + 3; if(tens >= 5 && i > 0) tens = tens + 3; if(huns >= 5 && i > 0) huns = huns + 3; if(thous >= 5 && i > 0) thous = thous + 3; end //>>--------------------------------------------------- // case1: binary to BCD tim_a <= thous; tim_b <= huns; tim_c <= tens; tim_d <= ones; // case2: hex counter /* tim_a <= timer_count[15:12]; tim_b <= timer_count[11:8]; tim_c <= timer_count[7:4]; tim_d <= timer_count[3:0]; */ end /* always */ drv7seg seg_1 (.in(tim_a), .dp(1'b0), .seg(seg_a)); // leftmost digit drv7seg seg_2 (.in(tim_b), .dp(1'b0), .seg(seg_b)); drv7seg seg_3 (.in(tim_c), .dp(1'b1), .seg(seg_c)); drv7seg seg_4 (.in(tim_d), .dp(1'b0), .seg(seg_d)); mux7seg mux7seg_1 ( .clk(clk), .seg_a(seg_a), .seg_b(seg_b), .seg_c(seg_c), .seg_d(seg_d), .seg(seg), .seg_dig(seg_dig) ); endmodule

debounce.v

module debounce ( input clk, input rst, input key_in, output key_out ); //reg [3:0] key_n; reg [7:0] key_n; wire clk400Hz; clkdiv clkdiv_1 (.clk(clk), .rst(rst), .max(2999), .tc(clk400Hz)); always @(posedge(clk400Hz) or posedge(rst)) begin if (rst == 1'b1) begin key_n = 4'd0; end else begin key_n[7] <= key_n[6]; key_n[6] <= key_n[5]; key_n[5] <= key_n[4]; key_n[4] <= key_n[3]; // key_n[3] <= key_n[2]; key_n[2] <= key_n[1]; key_n[1] <= key_n[0]; key_n[0] <= key_in; end end assign key_out = & key_n; // key_n[1] | key_n[2] | key_n[3] endmodule

toggle.v

module toggle ( input clk, rst, in, output reg out ); reg prev_in; always @(posedge rst or posedge clk) begin if (rst == 1'b1) begin out <= 1'b0; prev_in <= 1'b0; end else begin prev_in <= in; if ({prev_in, in} == 2'b10) out <= ~out; else out <= out; end end /* always */ endmodule

仕様:

stopwatch (1)最右端のボタンは、start/stopになっており、トグルになっている。 (2)最左端のボタンは、resetになっており、stop状態で押すと、カウンターがゼロになる。 (3)7セグメントLEDの最右端は、0.1秒のカウンターになっている。 課題: ・7セグメント表示のリフレッシュタイミングが不適切なようで、  最右端の7セグメントLEDは、スムーズに表示できていない。 ・タイマー精度は、あまり高くない。 ・bib2bcdは、moduleのままでは、文法エラーで組み込むことができなかったので、  top_stopwatch.vの本体に組み込んだ。

参照情報

verilog samples:
神のBIN2BCD
【問題1】 Verilog HDLをマスターしよう!!
【問題2】 4ビット加算器をVerilog HDLで記述しよう
【問題11】 パラメタライズによる回路の記述
Verilog Full Adder

ボード関係:
Gowin RUNBER FPGA Development Board
RUNBER Development Board - Hardware Instructions
RUNBER Development Board - Instructions for Experiments
Gowin_device&Software User Guide
Gowin_RUNBER_BOARD Source Code
Runber_Development_Board_Schematics
GOWIN RUMBERのLチカを階層に分割してみる

linuxツール関係:
GOWIN GW1N-UV4LQ144C6/I5を動かす

verilog関係:
Verilog-HDL入門
Verilog入門(alwaysなど)
Getting Started with a free Verilog Simulator
Icarus Verilog - Getting Started
Icarus Verilogの導入とAND回路のシミュレーション
Icarus Verilogコンパイラを使う

Tools関連:
Analyzer Oscilloscopeの使い方
Tang Nanoで内部信号のモニタリング

以上

続きを読む "verilog事始め(sample#4 @Gowin RUNBER board)"

| | コメント (0)

2021年12月 1日 (水)

Gowin Analyzer Oscilloscope の使い方

2021/12/1
初版

Gowin Analyzer Oscilloscope の使い方

Gowin Analyzer Oscilloscope の使い方

概要

verilog事始め(Gowin RUNBER board で始める)」 の続編として、Gowinのツールの「Gowin Analyzer Oscilloscope」の使い方について 説明する。
このツールは、シミュレーションではなく、実際のFPGAボードから信号を取り出し、パソコン画面に信号を表示するツールになっている。

使用方法

1.gaoファイル作成

(0)あらかじめ調査するソースをビルトしておく。 (1)File/Newで GAO Config Fileを選択する。 (2)ダイアログが現れるので以下に設定する: Type:for RTL Design Mode:Lite  LiteとStandardが選択できるが、Standardは設定が多いので  最初はLiteにしたほうが良い。 (3)[Next]をクリックする。 (4)Nameを設定する。(デフォルトでかまわない) (5)[Next]をクリックする。 (6)[Finish]をクリックする。 FinishでDesignビューに*.raoができる。 (*.gaoとなるべきだと思うが*.raoになる。 バグのような気がするが特に機能的に問題がないようだ)

2.gaoファイル編集

(1)Design/GAO Config Files/*.raoをクリックする。 (2)「Caputure Option」の設定画面が開く。 (Liteなので「Trigger Option」は無い) ・Sample Clock  トリガーとなる信号を指定する、  「...」をクリックして指定したい信号名を[Search]で検索して設定する。 ・Capture Signals  測定した信号を指定する。  [Add]をクリックして指定する信号名を[Search]で検索して設定する。  [Ctrl]を押しながらクリックすると複数の信号名を指定できる。 (3)File/Saveで設定を保存する。

3.再コンパイル

DesignペインのProcessタブで (1)論理合成(Synthesize)をダブルクリックする。 (2)配置配線(Place & Route)をダブルクリックする。 以上で配置配線まで実行する。

4.Oscilloscope起動

(1)Tools/GOWIN Analyzer Oscilloscopeを選択して、Oscilloscopeを起動する。 (2)Enable Programmerをチェックする(プログラマー画面がプルダウンする) (3)Downloadをクリックすると赤い「Please Program fs filr first」が 緑の「Ready to acquire」になる。 (このときにプログラムがボード書き込まれる) (4)[Ready to acquire]の右隣のPlayアイコンをクリックする。 (データを収集している間は赤い四角のアイコンが有効になる) (5)トリガーがかかるとキャプチャー結果が表示される。(オシロ画面) [+]や[-]アイコンで画面の拡大/縮小ができる。 (キャプチャー直後は全体が表示されていないので [-]アイコンをクリックして全体を表示したほうが良いかもしれない) (6)DIP-SWなどを変更した場合、再キャプチャー(再度、Playアイコンをクリックする)すると その状態が取り込まれる。 (7)Oscilloscopeを使い終わったら、 そのままだとキャプチャーのためのゲートが組み込まれているので不要な遅延などが生じている場合があるので、 *.raoファイルを削除して、再コンパイルしたほうが良いようだ。 .gaoファイル作成時に「mode:Standard」を選択した場合は *.raoの選択時にでTrigger Optionの設定が追加になる:  ダブルクリックでダイアログが開くので設定できる。  (1)Trigger Ports 「+」クリックでSearch Netsが開くので、トリガー信号する。  (2)Match Units   トリガ条件を設定する(Match Typeを"Basic w/edges"とする)  (3)Expressions トリガ条件の組み合わせを指定する            (ここは取り合えず"M0"だけ) 設定後の操作は上に記述したとおりになる。

以上

参照情報

Gowin Analyzer Oscilloscope - User Guide

Analyzer Oscilloscopeの使い方
Tang Nanoで内部信号のモニタリング

Program Your First FPGA With GOWIN GW1N-4
Intro to GoWin FPGA’s with built in microprocessors

以上

続きを読む "Gowin Analyzer Oscilloscope の使い方"

| | コメント (0)

2021年11月24日 (水)

verilog事始め(Gowin RUNBER board で始める)

2021/11/28
adder4を追加した。

2021/11/27
dsphex関連を追加した。

2021/11/25
blink関連を追加した。

2021/11/22
初版

verilog事始め(Gowin RUNBER board で始める)

verilog事始め(Gowin RUNBER board で始める)

概要

FPGAのプログラミングができる開発ボードとして以下を購入した。

Gowin RUNBER FPGA Development Board

注意:
現時点では、このボードはPCからフラッシュメモリへの書き込みをサポートしていないので SRAMへの書き込みを使用することになる。

インタフェース2021年12月号別冊付録にこのボードの使用方法があるので、これを参照する。
Interface2021年12月号

ツールのインストールと起動

インタフェース2021年12月号別冊付録にインストール方法があるので それを参照してインストールする。
以下がツールのダウンロードのURLになる。

https://www.gowinsemi.com/ja/support/home/
GOWIN EDA ホーム ここからツールをダウンロードできる。(linux用もあり)
ツール関係のドキュメントもダウンロードできる。 (アカウント登録必要)

付録にあるライセンス申請URLがアクセスできなかったので 本家サイトでライセンス申請した。
数日後、代理店の丸文経由でライセンス・ファイルが送られてきたので これを利用してツールが有効になった。

ツールの使用方法

付録にある使用方法を以下のように動作サンプルを元に使用方法を纏めた:

ツールは、Designer, PloorPlanner,Programmerの3つのウィンドウから構成される。

1.プロジェクト作成

ツールを起動する。 File/Newを選択して以下を選択する: FPGA Desing Project # Chip選択する 以下を設定する: Name:hwtest (任意) Crate in:C:\Gowin\ws (任意) Nextをクリックする。 以下を設定する: Series: GOW1N Device: GW1N-4B Package: LQFP144 Speed: Any Part Number: GW1N-UV4LQ144C6/15 Nextをクリックする。 Fishをクリックする。 # 以上でChipの設定が完了する

2.verilogファイル作成

File/Newから以下を選択する: Verilog File 以下を設定する: Name: hwtest (任意) ディレクトリ設定はそのまま 以上で空のhwtest.vができる。 オンボードのハード(DISP-SW,LED,RGB-LED,7seg-LED)のテスト用に以下のhwtest.vを作成する:

hwtest.v

module test( input [7:0] sw, input [7:0] btn, output [7:0] seg, output [3:0] seg_dig, output [7:0] led, output [2:0] rgb0, output [2:0] rgb1, output [2:0] rgb2, output [2:0] rgb3 ); assign rgb0 = 3'b110; // Red assign rgb1 = 3'b101; // Blue assign rgb2 = 3'b011; // Green //assign rgb3 = 3'b000; // White assign rgb3 = sw; assign seg_dig = sw; assign seg = ~btn; assign led = btn; endmodule

継続:

File/Saveで保存する。

3.論理合成

consoleウィンドウの上のメニューから以下を選択する: Process 左のペインから以下を選択する: Sythesizeで右クリックしてRunを選択する。 論理合成が実行される。

4.FloorPlanner(ピン配置の設定)

consoleウィンドウの上のメニューから以下を選択する: Process 左のペインから以下を選択する: User Constraints/Floor Planner で左クリックしてRunを選択する。 ファイルを作るか聞いてきたら、そのままOKにする (FloorPlannerの)画面の最下行のメニューから「I/O Constraints」をクリックする 設定画面が出るので設定する: (画面が小さい場合、ドラッグで画面を大きくする) Location,Pull Mode を仕様に合わせて設定する File/Saveで保存する。

(DesignerのConsole画面の上のメニューの)Designをクリックすると左のペインに 現在のプロジェクトのファイル・ディレクトリが出るので ここから、*.cstを選択して、編集しても良い。
上のGUIで設定するよりもテキストをコピー&ペーストするほうが手っ取り早いかもしれない。

以下はオンボードのデバイスを設定した例である:
hwtest.cst

//Copyright (C)2014-2021 Gowin Semiconductor Corporation. //All rights reserved. //File Title: Physical Constraints file //GOWIN Version: 1.9.8.01 //Part Number: GW1N-UV4LQ144C6/I5 //Device: GW1N-4B //Created Time: Tue 11 23 10:51:34 2021 IO_LOC "led[7]" 30; IO_PORT "led[7]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[6]" 29; IO_PORT "led[6]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[5]" 28; IO_PORT "led[5]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[4]" 27; IO_PORT "led[4]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[3]" 26; IO_PORT "led[3]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[2]" 25; IO_PORT "led[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[1]" 24; IO_PORT "led[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "led[0]" 23; IO_PORT "led[0]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg_dig[3]" 7; IO_PORT "seg_dig[3]" PULL_MODE=UP DRIVE=8; IO_LOC "seg_dig[2]" 141; IO_PORT "seg_dig[2]" PULL_MODE=UP DRIVE=8; IO_LOC "seg_dig[1]" 140; IO_PORT "seg_dig[1]" PULL_MODE=UP DRIVE=8; IO_LOC "seg_dig[0]" 137; IO_PORT "seg_dig[0]" PULL_MODE=UP DRIVE=8; IO_LOC "seg[7]" 10; IO_PORT "seg[7]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[6]" 8; IO_PORT "seg[6]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[5]" 139; IO_PORT "seg[5]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[4]" 12; IO_PORT "seg[4]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[3]" 11; IO_PORT "seg[3]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[2]" 9; IO_PORT "seg[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[1]" 142; IO_PORT "seg[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "seg[0]" 138; IO_PORT "seg[0]" PULL_MODE=NONE DRIVE=8; IO_LOC "sw[7]" 83; IO_PORT "sw[7]" PULL_MODE=NONE; IO_LOC "sw[6]" 82; IO_PORT "sw[6]" PULL_MODE=NONE; IO_LOC "sw[5]" 81; IO_PORT "sw[5]" PULL_MODE=NONE; IO_LOC "sw[4]" 80; IO_PORT "sw[4]" PULL_MODE=NONE; IO_LOC "sw[3]" 79; IO_PORT "sw[3]" PULL_MODE=NONE; IO_LOC "sw[2]" 78; IO_PORT "sw[2]" PULL_MODE=NONE; IO_LOC "sw[1]" 76; IO_PORT "sw[1]" PULL_MODE=NONE; IO_LOC "sw[0]" 75; IO_PORT "sw[0]" PULL_MODE=NONE; IO_LOC "btn[5]" 63; IO_PORT "btn[5]" PULL_MODE=UP; IO_LOC "btn[4]" 62; IO_PORT "btn[4]" PULL_MODE=UP; IO_LOC "btn[3]" 61; IO_PORT "btn[3]" PULL_MODE=UP; IO_LOC "btn[2]" 60; IO_PORT "btn[2]" PULL_MODE=UP; IO_LOC "btn[7]" 65; IO_PORT "btn[7]" PULL_MODE=UP; IO_LOC "btn[6]" 64; IO_PORT "btn[6]" PULL_MODE=UP; IO_LOC "btn[0]" 58; IO_PORT "btn[0]" PULL_MODE=UP; IO_LOC "btn[1]" 59; IO_PORT "btn[1]" PULL_MODE=UP; IO_LOC "rgb3[2]" 100; IO_PORT "rgb3[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb3[1]" 99; IO_PORT "rgb3[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb3[0]" 98; IO_PORT "rgb3[0]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb2[2]" 104; IO_PORT "rgb2[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb2[1]" 102; IO_PORT "rgb2[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb2[0]" 101; IO_PORT "rgb2[0]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb1[2]" 111; IO_PORT "rgb1[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb1[1]" 110; IO_PORT "rgb1[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb1[0]" 106; IO_PORT "rgb1[0]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb0[2]" 114; IO_PORT "rgb0[2]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb0[1]" 113; IO_PORT "rgb0[1]" PULL_MODE=NONE DRIVE=8; IO_LOC "rgb0[0]" 112; IO_PORT "rgb0[0]" PULL_MODE=NONE DRIVE=8;

5.Place&Route(マッピング)

consoleウィンドウの上のメニューから以下を選択する: Process 左のペインから以下を選択する: Place & Route で右クリックしてRunを選択する。

6.書き込み

ボードをPCに接続する。 consoleウィンドウの上のメニューから以下を選択する: Process 左のペインから以下を選択する: Program Device で右クリックしてRunを選択する。 Programmer画面から書き込み(Program/Configure)アイコンをクリックする。 コンソールログ例: Info: "SRAM Program" starting on device-1... Warn: Compatible cable found Warn: Compatible cable found Info: User Code: 0x0000C642 Info: Status Code: 0x0001F020 Info: Cost 6.48 second(s) 以上で全ての完了してプログラム(verilog)が動作する。

今回のhwtest.vの仕様:

(1)DIP-SWはデフォルトはONでSW1-SW4のうち有効にしたい桁の SWをOFFにする。 (2)特定のボタンを押すと、それに対応したLEDはオフになり、7セグメントは対応したセグメントが光る。 # 通称で7セグメントというが実際には小数点があるので # 実際のセグメント数は8になる。 (3)RGB-LEDは上から以下のように光る: 1番目:赤 2番目:青 3番目:緑 4番目:SW1-SW3に連動していて SW1-RED SW2-Blue SW3-Green に対応している。 負論理なのでOFFにすると対応しているLEDが光る。

別のプログラム例としてLEDを点滅させてみる。

プロジェクトを上の例を参考に作成する。

blink.v

module blink( input clk, input tc, input [7:0] sw, input [7:0] btn, output [7:0] seg, output [3:0] seg_dig, output [7:0] led, output [2:0] rgb0, output [2:0] rgb1, output [2:0] rgb2, output [2:0] rgb3 ); wire clk10KHz; reg [7:0] leds; // generate blinking pluse //clkdiv(.clk(clk), .rst(1'b0), .max(24'd1200), .tc(clk10KHz)); clkdiv(.clk(clk), .rst(1'b0), .max(24'd1200_000_10), .tc(clk10KHz)); always@(posedge(clk10KHz)) begin if (tc == 0) begin leds <= 0; end else begin leds <= ~leds; end end /* always */ /* // RGB-LEDs blink assign rgb0 = 3'b110 & leds; // Red assign rgb1 = 3'b101 & leds; // Blue assign rgb2 = 3'b011 & leds; // Green assign rgb3 = sw & leds; */ // 7seg-LEDa blink assign seg_dig = sw; assign seg = leds & ~btn; // LEDs blink assign led = leds & btn; endmodule

全てのLEDを点滅することができるが、ドライブ能力の問題があるので RGB-LEDの部分はコメントアウトしている。

clkdiv.v

module clkdiv( input clk, input rst, input [23:0] max, output tc ); reg [23:0] count; always @(posedge clk or posedge rst) begin if (rst == 1'b1) begin count <= 24'd0; end else begin if (tc == 1'b1) count <= 24'd0; else count <= count + 24'b1; end end /* always */ assign tc = (count >= max) ? 1'b1 : 1'b0 ; endmodule

clkdiv.vは、インタフェースの付録のものを参考にした。

blink.cst (従来のcstに以下の部分を追加する)

IO_LOC "clk" 4; IO_PORT "clk" PULL_MODE=NONE; <省略>

仕様:

hwtest.vの仕様にLEDの点滅を追加した仕様になるので 以下のようになる(RGB-LED部分はコメントアウトしているので機能しない) (1)DIP-SWはデフォルトはONでSW1-SW4のうち有効にしたい桁の SWをOFFにする。 (2)特定のボタンを押すと、それに対応したLEDはオフになり、7セグメントは対応したセグメントが光る。 # 通称で7セグメントというが実際には小数点があるので # 実際のセグメント数は8になる。 (3)従来、LEDが単に光っていたところが点滅になる。

sample#2(dsphex)

別の例として、スイッチとボタンの内容を読み込み、7seg-LEDに16進で表示するプログラムを作成する。以下のプログラム(*.v)を用意する。 これらの他に、clkdiv.vが必要となるは、それはsample#1のものと同じものを使用する。(ここでは、インタフェースの付録のものを参考にした)

top_dsphex.v

module top_dsphex ( input clk, input [7:0] sw, input [7:0] btn, output [7:0] seg, output [3:0] seg_dig, output [7:0] led ); // all LEDs off assign led = 8'b0000_0000; wire [7:0] seg_a, seg_b, seg_c, seg_d; wire [3:0] a, b, c, d; assign a = {sw[0],sw[1],sw[2],sw[3]}; assign b = {sw[4],sw[5],sw[6],sw[7]}; assign c = ~{btn[0],btn[1],btn[2],btn[3]}; assign d = ~{btn[4],btn[5],btn[6],btn[7]}; drv7seg seg_1 (.in(a), .dp(1'b0), .seg(seg_a)); // leftmost digit drv7seg seg_2 (.in(b), .dp(1'b0), .seg(seg_b)); drv7seg seg_3 (.in(c), .dp(1'b0), .seg(seg_c)); drv7seg seg_4 (.in(d), .dp(1'b0), .seg(seg_d)); mux7seg mux7seg_1 ( .clk(clk), .seg_a(seg_a), .seg_b(seg_b), .seg_c(seg_c), .seg_d(seg_d), .seg(seg), .seg_dig(seg_dig) ); endmodule

mux7seg.v

module mux7seg ( input clk, input [7:0] seg_a, input [7:0] seg_b, input [7:0] seg_c, input [7:0] seg_d, output [7:0] seg, output [3:0] seg_dig ); wire clkdig; reg [2:0] seg_no; // generate clock for digit display clkdiv(.clk(clk), .rst(1'b0), .max(24'd120), .tc(clkdig)); always @ (posedge(clkdig)) begin seg_no <= ((seg_no + 3'd1) % 8); end /* always */ function [7:0] sel_seg; input [7:0] a, b, c, d; input [1:0] seg_no; case(seg_no) 2'd0: sel_seg = a; 2'd1: sel_seg = b; 2'd2: sel_seg = c; 2'd3: sel_seg = d; endcase endfunction function [3:0] sel_dig; input [1:0] seg_no; case(seg_no) 2'd0: sel_dig = 4'b1110; 2'd1: sel_dig = 4'b1101; 2'd2: sel_dig = 4'b1011; 2'd3: sel_dig = 4'b0111; endcase endfunction assign seg = sel_seg(.a(seg_a), .b(seg_b), .c(seg_c), .d(seg_d), .seg_no(seg_no[1:0])); assign seg_dig = sel_dig(.seg_no(seg_no[1:0])); endmodule

drv7seg.v

module drv7seg ( input [3:0] in, input dp, output [7:0] seg ); function [6:0] f; input [3:0] sw; begin case(sw) 4'h0: f = 7'h3F; 4'h1: f = 7'h06; 4'h2: f = 7'h5B; 4'h3: f = 7'h4F; 4'h4: f = 7'h66; 4'h5: f = 7'h6D; 4'h6: f = 7'h7D; 4'h7: f = 7'h27; 4'h8: f = 7'h7F; 4'h9: f = 7'h6F; 4'hA: f = 7'h77; 4'hB: f = 7'h7C; 4'hC: f = 7'h58; 4'hD: f = 7'h5E; 4'hE: f = 7'h79; 4'hF: f = 7'h71; endcase end endfunction assign seg = {dp,f(in)}; endmodule

制約ファイルdsphex.cstはsample#1のものと同じ内容になる。

仕様:

DIPのSW1-SW4,SW5-SW8, ボタンの#1-#4,#5-#6が 7セグメントLEDの左から順に対応している。 SWやボタンの内容に対応して7セグメントLEDに16進で表示される。 (目障りなので)緑のLEDは消灯している。

sample#3(adder4)

例として、sample#2をベースに以下を追加して、4ビット加算器を実現する。

top_dsphex.vを以下のように変更する:

top_adder4.v

module top_adder4 ( input clk, input [7:0] sw, input [7:0] btn, output [7:0] seg, output [3:0] seg_dig, output [7:0] led ); // all LEDs off assign led = 8'b0000_0000; wire [7:0] seg_a, seg_b, seg_c, seg_d; wire [3:0] a, b, c, d; wire c_out; wire [3:0] sum; assign a = {sw[0],sw[1],sw[2],sw[3]}; assign b = {sw[4],sw[5],sw[6],sw[7]}; //assign c = ~{btn[0],btn[1],btn[2],btn[3]}; //assign d = ~{btn[4],btn[5],btn[6],btn[7]}; // d = a + b fulladder fa_1 (.a(a), .b(b), .c_in(1'b0), .c_out(c_out), .sum(sum) ); assign c = {3'b000, c_out}; assign d = sum; drv7seg seg_1 (.in(a), .dp(1'b0), .seg(seg_a)); // leftmost digit drv7seg seg_2 (.in(b), .dp(1'b0), .seg(seg_b)); drv7seg seg_3 (.in(c), .dp(1'b0), .seg(seg_c)); drv7seg seg_4 (.in(d), .dp(1'b0), .seg(seg_d)); mux7seg mux7seg_1 ( .clk(clk), .seg_a(seg_a), .seg_b(seg_b), .seg_c(seg_c), .seg_d(seg_d), .seg(seg), .seg_dig(seg_dig) ); endmodule

以下を追加する:

fulladder.v

module fulladder( input [3:0]a, input [3:0]b, input c_in, output reg c_out, output reg [3:0] sum ); always @(a or b or c_in) begin {c_out, sum} = a + b + c_in; end endmodule

仕様:

DIPのSW1-SW4,SW5-SW8が入力のa,bに対応して 7セグメントLED#1,#2に、その内容が表示され 加算結果が、7セグメントLED#3,#4に16進で表示される。 (目障りなので)緑のLEDは消灯している。

参照情報

ボード関係:
Gowin RUNBER FPGA Development Board
RUNBER Development Board - Hardware Instructions
RUNBER Development Board - Instructions for Experiments
Gowin_device&Software User Guide
Gowin_RUNBER_BOARD Source Code
Runber_Development_Board_Schematics
GOWIN RUMBERのLチカを階層に分割してみる

linuxツール関係:
GOWIN GW1N-UV4LQ144C6/I5を動かす

verilog関係:
Verilog-HDL入門
Verilog入門(alwaysなど)
Getting Started with a free Verilog Simulator
Icarus Verilog - Getting Started
Icarus Verilogの導入とAND回路のシミュレーション
Icarus Verilogコンパイラを使う

verilog samples:
【問題1】 Verilog HDLをマスターしよう!!
【問題2】 4ビット加算器をVerilog HDLで記述しよう
【問題11】 パラメタライズによる回路の記述
Verilog Full Adder

Tools関連:
Analyzer Oscilloscopeの使い方
Tang Nanoで内部信号のモニタリング

以上

続きを読む "verilog事始め(Gowin RUNBER board で始める)"

| | コメント (0)

2021年11月14日 (日)

verilog事始め(Tang Primer board で始める)

2021/11/8

verilog事始め(Tang Primer board で始める)

verilog事始め(Tang Primer board で始める)

概要

FPGAのプログラミングができる開発ボードとして以下を購入した。

Sipeed Tang PriMER FPGA Dev.Board

このボードはデモとしてRISC-Vのコードが書き込まれており それを書き換えることができる。ここではツールのインストール方法とverilogのプログラミング方法について紹介する。

ツールのインストールと起動

1.downloads https://dl.sipeed.com/TANG/Primer/IDE/
上のurlから以下のファイルをダウンロードする:
TD1910_win.zip (windows10の場合)
TD1909_linux.rar (ubuntuの場合)
Anlogic_20220130.lic(共通)

2.Install
ubuntuの場合

0.開発ボードの確認
ボードが認識しているかどうかの確認

~$ lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 005: ID 138a:0097 Validity Sensors, Inc. Bus 001 Device 004: ID 04f2:b5ce Chicony Electronics Co., Ltd Integrated Camera Bus 001 Device 002: ID 1199:9079 Sierra Wireless, Inc. Sierra Wireless EM7455 Qualcomm Snapdragon X7 LTE-A Bus 001 Device 007: ID 0547:1002 Anchor Chips, Inc. Python2 WDM Encoder Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub PCのハード状況で色々表示されるが以下の行があればボードが認識されていることになる: Bus 001 Device 007: ID 0547:1002 Anchor Chips, Inc. Python2 WDM Encoder これが表示されない場合、ボードが不良の可能性がある。(1度(ボード1枚)、経験あり)

1.Install TD driver on Linux
以下でドライバーを設定する:

sudo nano /etc/udev/rules.d/91-anlogic-jtag.rules

編集内容:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0547", ATTRS{idProduct}=="1002", GROUP="plugdev", MODE="0660"

UDEVの再起動:

sudo service udev restart

2.Install Application

cd ~/Downloads sudo unrar x TD1909_linux.rar -d /opt/ sudo ln -s /opt/TD_RELEASE_September2019_r4.6.2/bin/td /usr/bin/td sudo chmod a+x /opt/TD_RELEASE_September2019_r4.6.2/bin/td sudo ln -s /opt/TD_RELEASE_September2019_r4.6.2/arch /usr/arch # ライセンスファイルを最新にする cd /usr sudo mkdir license cd license/ sudo cp ~/Downloads/Anlogic_20220130.lic Anlogic.lic # ツールの起動 td -gui

windows10の場合

(1)TD1910_win.zipを解凍する (2)解凍したmsiファイルをインストールする (3)以下のライセンスファイルを新しいもの(Anlogic_20220130.lic)に差し替えてリネームする。 C:\Anlogic\TD4.6.3\license\Anlogic.lic (5)以下のinfをインストールする C:\Anlogic\TD4.6.3\driver\win8_10_64\cyusb.inf #「署名無し」の警告が出るという情報があったが特に警告はでなかった。 起動する場合、アイコンをクリックする

サンプル(blinky)の動作

https://tang.sipeed.com/en/getting-started/getting-to-blinky/ に沿って、サンプルを動作させてみる。

downloads:

mkdir tang_primer cd tang_primer git clone https://github.com/Lichee-Pi/Tang_FPGA_Examples

build:
ツールを起動し
(1)[Project/Open Project] で [~/TangPrimer/Tang_FPGA_Examples/0.LED/prj] の下の led.al を開く。
(2)[Process/Run] またはメニューボタンの中の Runアイコンをクリックすると、ビルドが行われ led.bit が生成される。

書き込み:
(1)downloadアイコンを押すとウィンドウがポップアップするので、そのなかでAddアイコンで書き込みたい*.bitファイルを指定する。
(2)(電源が切れると消える)揮発状態で書き込むときはModeを「JTAG」、フラッシュに書き込むときは「FROGRAM FLASH」にして、Runアイコンを押すと書き込みが開始される。

デバッグ中で何度も書き込む場合は、書き込み速度が速いので「JTAG」を使用する。なお、RESETボタンを押すとフラッシュに書き込んだものが動作する。
(注意:JTAGで書き込んだのにRESETボタンを押すと別のものが動作することになる)

Hummingbird E203 port on LicheeTang(Anlogic EG4SBG256)

RISC-V(32bits)のverilogをビルドしてみる。

download:

cd tang_primer git clone https://github.com/Lichee-Pi/Tang_E203_Mini.git https://github.com/riktw/Tang_E203_Mini

RISC-V デバッガでの書き込みができないバグがいるようなので 以下のように修正する:

Constraits/e203egmini_new.sdc

修正前: 9行目 create_clock -name clk_16M -period 62.5 [get_nets {CLKIN}] 修正後: #create_clock -name clk_16M -period 62.5 [get_nets {CLKIN}] create_clock -name clk_16M -period 62.5 [get_nets {clk_16M}]

修正後、通常のやり方でビルドと書き込むを行う。

2.sdk
RISC-V用のSDKを使用してみる。

(1)RISC-V デバッガ(Sipeed USB-JTAG/TTL)の設定

sudo usermod -a -G plugdev $USER sudo nano /etc/udev/rules.d/45-dt2232.rules

編集内容:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", GROUP="plugdev", MODE="0660"

以下でudevを再起動する

sudo service udev restart

(2)sdk

HUMMINGBRID CORE wget https://github.com/kprasadvnsi/tang-doc/releases/download/1.0.0/sirv-e-sdk.tar.lrz sudo apt install lrzip lrzuntar sirv-e-sdk.tar.lrz cd sirv-e-sdk # upload(RISC-Vプログラムの書き込み) make upload PROGRAM=demo_gpio BOARD=sirv-e203-lichee # Debugging the Demo #(1) Run the OpenOCD GDB server with the following command and leave it running. make run_openocd PROGRAM=demo_gpio BOARD=sirv-e203-lichee #(2) In the other Terminal run the following command to debug your code using familiar GDB Debugger. make run_gdb PROGRAM= demo_gpio BOARD=sirv-e203-lichee

参照情報

getting started with Tang Primer board.
Tang Primer Documentation
TangPrimer(RISC-V)をArduinoIDEで開発する・・・OpenOCDの再コンパイル対応方法
Tang Primer 開発環境をセッティング
話題のFPGAボード: Tang PrimerをWindows10でLチカする
Tang Primer FPGA ボード & RISC-V

Icarus Verilog - Getting Started
Icarus Verilogの導入とAND回路のシミュレーション
Icarus Verilogコンパイラを使う
[電子工作]Tang Primer:中国製FPGAでRISC-Vの設計に挑戦

以上

続きを読む "verilog事始め(Tang Primer board で始める)"

| | コメント (0)