FC2ブログ

[LM32](1)環境構築

ホスト = ThinkPad X1 Windows 10 Pro
もしくは
ホスト = ThinkPad X230 Windows 8.1 Pro


Lattice Diamond Softwareインストール

http://www.latticesemi.com/en/Products/DesignSoftwareAndIP/FPGAandLDS/LatticeDiamond.aspx

上記にアクセス > Download Software Below でWindowsをクリック
  > Lattice Diamond をクリック
  > LatticeアカウントへSign In
  > ライセンスチェックを入れて、Downloadボタンで入手。

これで
3.10.0.111.2_Diamond_x64.zip
がダウンロードされた。

解凍すると
\3.10.0.111.2_Diamond_x64\3.10.0.111.2_Diamond_x64.exe
が生成されるので実行。
あとはウィザードに従ってインストールを進める。


Lattice Micosystemインストール

http://www.latticesemi.com/ja-JP/Products/DesignSoftwareAndIP/EmbeddedDesignSoftware/LatticeMicoSystem
ここのページから以下をクリック。
LatticeMico System for Diamond 3.10 Windows

LMS_1.0_for_Diamond3.10.exe.zip
をダウンロードし、解凍後、インストールする。



Cygwinインストール

コマンドラインでいろいろ操作したいのでCygwinをインストールする。
環境変数として以下を設定。

CYGWIN ntsec
HOME /home/xxx
MAKE_MODE UNIX
SHELL /bin/bash



また、.bashrcの設定としてとりあえず以下。

alias lm='ls -lst'
export PATH=$PATH:/bin:/sbin:/cygdrive/c/user/app/vim80-kaoriya-win64-8.0.0596-20170502
alias WORK='cd /cygdrive/c/user/work/quartus/atlas-soc/quartus'
alias USER='cd /cygdrive/c/user'





シミュレータ(Veritak)インストール

無償のModelSim Starterが遅すぎるので、Veritakを使う。
veritakwin384D.exe
をインストール。


エディタ(Gvim)インストール

ウィンドウ分割で複数ファイルを開いて、次回同じ構成で開く時、
:mks!
とやれば、
Session.vim
が生成される。

次回作業再開する場合は、Cygwinから
gvim -S Session.vim
とやれば、複数ファイル開いた状態のまま復元出来る。

[LM32]MSBでSoftware Deployment時「WARNING: Couldn't compute FAST_CWD pointer.」

0 [main] bin_to_verilog 5956 find_fast_cwd: WARNING: Couldn't compute FAST_CWD pointer. Please report this problem to
the public mailing list cygwin@cygwin.com
Failed to open tmp.bin for reading
No such file or directory


https://cygwin.com/ml/cygwin/2014-09/msg00164.html
ここ見るとこんな投稿があった。

I experienced the same thing when I upgraded to Windows 8.1. The messages went away when I upgraded to the latest and greatest Cygwin.


どうやらWindows 8.1で発生する問題のようで、Cygwinを更新すると直るらしいが、
MicoSystemBuilderのCygwinってどうやって更新するんだ?

インストール先を、MSBのCygwin場所に指定すれば良いのかな?

C:\lscc\diamond\3.4_x64\micosystem\cygwin


setup-x86.exeで更新出来たようだが、Software Deloyment実行しても、
Warningは出なくなったが、.memのサイズが0KB・・・なぜだ。

<terminated> uart_int2[Mico32 On Chip Memory Deployment] C:\lscc\diamond\3.4_x64\micosystem\utilities\bin_to_verilog


ConsoleタブのバーにこんなMSGが出た。

[LM32]wb_spi.vがSEL_I未サポート(MicoSystem v3.4.0.80)

構造体、共用体を使って、SPIコアのレジスタへBYTEでもBITでも両方アクセス可能にしたい。

struct st_spi { /* struct SPI */
 :
union { /* CTRL */
unsigned int DWORD;
struct {
unsigned int RESV1 :21;
unsigned char SSO :1;
unsigned char RESV4 :1;
unsigned char IE :1;
unsigned char IRRDY :1;
unsigned char ITRDY :1;
unsigned char RESV5 :1;
unsigned char ITOE :1;
unsigned char IROE :1;
unsigned char RESV6 :3;
} BIT;
} CTRL;
 :
};


ところが、SPI.CTRL.BIT.IE = 0; のようにbitアクセスすると、目的のbitのみの操作が出来ない。
micosystem_spi_not_support_for_SEL
上の波形で、一番上のled_out_regの値を逐一変えて、順番にレジスタアクセス動作を見ている。
SPI.CTRL.BIT.IE = 0;したのが、led_out_reg=19のところ。

この波形の通り、bit操作するためには、まずは対象のアドレス(SPIコアControllレジスタ)の値を読みだして、
その値を基準にして、操作対象のbitのみを変更している(と理解)。
波形図では見えないが、SPI_DAT_Oはreg_controlのリード値=0x140が出ていた。

Mico32は32bitデータバスなので、SEL[3:0]を使って、アクセス対象のBYTEを指定する。
IEビットはbit8なので、SEL_I[1]のみがHになる。
そのため、上の波形におけるSPI_SEL_Iは、fから2([1]のみHになった)へ値が変わっている。
この動作は正しい。

期待の動作は、reg_control[8]のみH->Lへ変化するはずが、[6]も変化してしまっている。
MicoSystemが生成したwb_spi.vを見たら、SPI_SEL_Iは未接続。
SEL_I制御が効いてないから、無関係のbitまで変更してしまった。これが原因だ。

よくよく見ると、MicoSystemで生成したSPIコアは、WISHBONEのSEL_I信号に未対応だって。
SPIコアデータシートpage8 I/O Portsにしっかり書いてあるが。
MicoSystemで生成されるRTLはWISHBONE完全準拠かと勝手に思ってた。

wb_spi.vをSEL信号対応に修正しよう。

[LM32]DE0 nanoでLEDチカチカしない原因解析 → 解決

XilinxのML501では動いていたソース(DWM200710のやつ)をもってきて、
コンパイラ等もDWM200710付属のデータを使い、DE0 nano上で
Lattice Mico32を動かそうとしてる。

メモリをXilinxからAlteraへ変えるだけで、確かこの前LEDチカチカ出来てたんだが、
また動かなくなった。ソースの取り違いの可能性大だが、こんな場合に、
どんな確認すれば良いのか考えてみる。
(単に動くソースを探して差し替えれば動くのかもしれないけど、そもそもCPUはどこがどうなると
 正常動作になるのか?というのを、ほんの触りだけでも探ってみる、という意味です)

■命令用SRAMから最初にどのデータが読まれるのか?
 main関数の前はスタートアップルーチンだ、くらいは知ってるけど、
 外部リセットを入れてから、どこからSRAMが読まれ、どんな値が出たらOKなのか?を確認したい。

 まずはobjdumpでelfを解析してみる。

$ lm32-elf-objdump.exe -d uart_int | more

uart_int: file format elf32-lm32

Disassembly of section .start:

00000000 <_sstarttext>:
0: e0 00 00 40 bi 100 <__startup>
...
20: e0 00 00 6d bi 1d4 <__break_interrupt>
...
40: e0 00 00 61 bi 1c4 <__interrupt>
...
60: e0 00 00 59 bi 1c4 <__interrupt>
...
80: e0 00 00 51 bi 1c4 <__interrupt>
...
a0: e0 00 00 49 bi 1c4 <__interrupt>
...
c0: e0 00 00 41 bi 1c4 <__interrupt>
...
e0: e0 00 00 39 bi 1c4 <__interrupt>
...

00000100 <__startup>:
100: 78 1c 20 00 mvhi sp,0x2000
104: 3b 9c 1f fc ori sp,sp,0x1ffc
108: e0 00 01 41 bi 60c



0000010c :
10c: 37 9c ff c8 addi sp,sp,-56
110: 5b 81 00 04 sw (sp+4),r1
114: 5b 82 00 08 sw (sp+8),r2
118: 5b 83 00 0c sw (sp+12),r3
11c: 5b 84 00 10 sw (sp+16),r4
120: 5b 85 00 14 sw (sp+20),r5
124: 5b 86 00 18 sw (sp+24),r6
128: 5b 87 00 1c sw (sp+28),r7
12c: 5b 88 00 20 sw (sp+32),r8
130: 5b 89 00 24 sw (sp+36),r9
     :



 まずリセット直後に読まれるアドレスは0x00番地(のはず)。
 Webでぐぐっても0番地と書いてあるが、保有してるRTLの設定が本当にそうなってるのか?
 が確認出来てないから「はず」を付けた。

00000000 <_sstarttext>:
0: e0 00 00 40 bi 100 <__startup>



 0番地から始まり、そこではbi命令で、_startupラベルの番地へ飛ぶ。
 __startupラベルは100番地を指していて、__startupの記述を見ると次のようになってた。

00000100 <__startup>:
100: 78 1c 20 00 mvhi sp,0x2000
104: 3b 9c 1f fc ori sp,sp,0x1ffc
108: e0 00 01 41 bi 60c



 mvhiって何だ?と思ったら以下を見る。ここにアセンブラの仕様がのってる。
 http://www.latticesemi.com/~/media/Documents/UserManuals/JL/LatticeMico32ProcessorReferenceManual34.pdf?document_id=50900

少なくとも0番地からスタートする事は正しそうだし、hexファイルを見ても、0番地に下の命令がある。

00000000 <_sstarttext>:
0: e0 00 00 40 bi 100 <__startup>


ただし、シミュレーションしても、addr=0でrden=Hなのにデータ出力はAll 0のまま。なぜ?

命令メモリ単体でシミュレーションしても同じでwren=0、rden=1、addr=0、be=0xfにしても0番地が読まれない。
QuartusII 14.1でIP Catalog画面へD&DしてMegaWizardを起動し、パラメータを確認してみると・・・

目的と違って出力がレジスタ付になってる。詳細な論理は不明だが、単にレジスタ1段入ってたって、
ずっと出力が変わらないって事は無いだろう、とは思いつつも、ここを出力レジスタ無にした。
そうすると、リードデータが出力されるようになった。
ソースでいうと、以下の設定。UNREGISTEREDなので出力レジスタ無って事らしい。

altsyncram_component.outdata_reg_a = "UNREGISTERED",



MegaWizardの画面で見る限り、単に1クロック遅れて出力させるための出力レジスタだと思ってたが、
このレジスタ動作には他の論理が絡んでるって事かな?
LUTでなく、BLOCK RAMを使われると物理LAYOUTにおいて、BLOCK RAMからその後段の論理が遠くなり、
セットアップ違反になるケースを回避するための役目程度にしか考えてなかった。今後注意しよう。


とりあえずhexはちゃんとかどうか不明だが、見る限り先頭の100アドレスくらいは初期値として読まれている。
そして、SRAMからデータも出力されるようになった。
SRAM単体のシミュレーションからMico32のシミュレーションに戻ってみると、命令アドレスは、
0x000、0x004、0x008、0x100、0x104、0x108・・・
と進んで行く。

リセット解除後に、0x000に進むのは納得。ここがスタートアップルーチンの開始ポイントだから。

00000000 <_sstarttext>:
0: e0 00 00 40 bi 100 <__startup>
...
20: e0 00 00 6d bi 1d4 <__break_interrupt>
...
40: e0 00 00 61 bi 1c4 <__interrupt>
...


次の0x004、0x008に行くのはなぜ?と思ったが、
よくよく考えると以下が理由だよね。納得。

  ・32bit CPUなので、データは4バイト毎読まれる。だから0、4、8と進む。
  ・今シミュレーションで見ているのはSRAMへのアドレス入力。
   つまりパイプライン内の命令フェッチステージの動作。
   さらに0x000にbi命令(Unconditional branch)があるため、無条件分岐するのだが、
   パイプライン上の命令フェッチステージでは次から次への先取りしてアドレスを進める。
  ・0x000のbi命令が、IF、DECODE、EXEとパイプラインを進むうちに分岐命令が実行され、
   0x008の次にbi命令で指定した0x100へジャンプした。



アドレスは想定通りに進んでいるが、0x100へ飛んだ後、そこでもまたメモリ出力がおかしく、
hexファイル上では

:10010000781c20003b9c1ffce0000141379cffc88D


「781c2000」が0x100の命令なのに、シミュレーションではALL 0出力。
またどこかおかしいらしい。次はこの解析。

っと思ったら、.hexのパスが間違ってた。DWM200710付属のmemcvt.exeで.hex生成してから、
hex内のアドレスをRubyで修正していて、修正版の.hexを使ってなかった事が原因でした。

■.hexのアドレス数間違ってる?
Veritakでこんなエラーが。

readmemb(h) ./inst_ram_data.ver Access Error accessing address=800 min_address=7ff max_address=0
In module:tb_mico32_neek.uut.mico32.inst_rom32_core.inst_ram.altsyncram_component.m_non_arria10.altsyncram_inst;
C:\user\onedrive\vm_share\de0_nano\mico32\rtlsim\rtl\altera_mf.v(48133)::
readmemb(h) ./data_ram_data.ver Access Error accessing address=800 min_address=7ff max_address=0
In module:tb_mico32_neek.uut.mico32.data_ram32_core.data_ram.altsyncram_component.m_non_arria10.altsyncram_inst;
C:\user\onedrive\vm_share\de0_nano\mico32\rtlsim\rtl\altera_mf.v(48133)::



Mico32命令メモリとして使ってるアルテラメモリIPの初期値ファイルを試しにQuartusで作ってみる。

Quartus II 14.1 > File > New > Memory Initialization File
 > Number of Word=2047, Word size=32
 > メモリアレイ内で右クリック > Custom Fill Cell...
 > Starting Address=0、Ending Address=2048、Starting Value=0、Increment by=1
 > OKを押して値がセットされた。保存するとmifファイルが生成される。

.hexしか使えないと思ってたが、.mifが使えるなら、その方が記述簡単そうだ。

.mifを使う方向で再度、おさらい。
・DWM200710付属memcvt.exeでelfから.mifを生成。
・そこで生成された.mifは以下のフォーマットだった。

DEPTH=1024;
WIDTH=32;
ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
BEGIN
00000000:e0000040;
00000001:00000000;
00000002:00000000;
00000003:00000000;
00000004:00000000;
00000005:00000000;
00000006:00000000;
00000007:00000000;
00000008:e000006d;
00000009:00000000;
  :
000003fd:00000000;
000003fe:00000000;
000003ff:00000000;
END;


・Word=1024になってるが、実際に今使ってるQuartusのRAM IPは2048にしてた。
 RAM IPをWord=1024に変更して、生成した.mifがそのまま読み込めるようにした。
・Veritakで確認してみても、シミュレーション開始時エラー無く.mifが読めてる。
・先のVeritakでのエラー(inst_ram_data.ver Access Error accessing address=800・・・)
 の原因は初期値ファイルのアドレスサイズと実際のRAM定義が違っていた模様。

■0x60c配置mainプログラムはどこにある?
・Mico32用にビルドしたelfのobjdump -d .elf結果では、以下だった。

uart_int: file format elf32-lm32

Disassembly of section .start:

00000000 <_sstarttext>:
0: e0 00 00 40 bi 100 <__startup>
...
20: e0 00 00 6d bi 1d4 <__break_interrupt>
  :
00000100 <__startup>:
100: 78 1c 20 00 mvhi sp,0x2000
104: 3b 9c 1f fc ori sp,sp,0x1ffc
108: e0 00 01 41 bi 60c


  :
0000060c <main>:
60c: 37 9c ff ec addi sp,sp,-20
610: 5b 9b 00 08 sw (sp+8),fp
614: 5b 9d 00 04 sw (sp+4),ra
618: 34 1b 00 14 mvi fp,20
 ※ mainのかっこは全角<>にしてます。
   半角だとHTML記述?に関係して表示されなかったため。


・リセット解除後、0x000 > 0x100(__startup) > 0x60c(main)と進む。
・mainが配置されるべき0x60c=dec1548なので、生成したRAMのword=1024をこえてる。
・.mifの中身を追うと、以下を発見出来る。

00000183:379cffec;
00000184:5b9b0008;
00000185:5b9d0004;
00000186:341b0014;
00000187:b77cd800;
00000188:78012000;
00000189:38210000;
0000018a:28210000;
0000018b:5b61fffc;
0000018c:78012000;
0000018d:38210004;
0000018e:34020000;


これはobjdumpして確認出来るmain関数の最初と命令コードが全て一致。

0000060c <main>:
60c: 37 9c ff ec addi sp,sp,-20
610: 5b 9b 00 08 sw (sp+8),fp
614: 5b 9d 00 04 sw (sp+4),ra
618: 34 1b 00 14 mvi fp,20
61c: b7 7c d8 00 add fp,fp,sp
620: 78 01 20 00 mvhi r1,0x2000
624: 38 21 00 00 ori r1,r1,0x0
628: 28 21 00 00 lw r1,(r1+0)
62c: 5b 61 ff fc sw (fp+-4),r1
630: 78 01 20 00 mvhi r1,0x2000
634: 38 21 00 04 ori r1,r1,0x4
638: 34 02 00 00 mvi r2,0


・.mifにおけるmain開始位置は0x183=dec387と分かった。
 387*4=1548であり、0x60c=dec1548と一致。
・そういえばDWM200710付属のRTLは命令メモリアドレスは下位2bitを抜かしてRAMへ接続していた。
 そういう事か。
 下位2bitを抜かす事で、実際の命令アドレス信号の1/4サイズのRAMで対応させてると。

■これでLEDチカチカが動いた!
 以上の事を踏まえ、system_top.v(Mico32のトップmodule)の以下を修正し、LEDチカチカ出来た。

inst_ram_altera inst_rom32_core (
// .addr(inst_sram_addr[9:0]), // 2015.2.1
.addr(inst_sram_addr[11:2]), // 2015.2.1

[LM32]gpio.vのPIO_DATAはどこから来る?

mico32でLEDチカチカのRTLシミュレーションは動く。
mico32でLEDチカチカのGATEシミュレーションや実機は動かない。

動いているRTLシミュレーションでgpio.vの中を追って行くと、外部LEDPIO_OUTの前段を探ると、
  gpio/PIO_DATA > gpio/PIO_OUT > FPGAトップ/LEDPIO_OUT
とデータが出てくる。

gpio/PIO_DATAへのデータ入力を見ると、

genvar ipd_idx;
 :
PIO_DATA[ipd_idx] <= #UDLY GPIO_DAT_I_switch[ipd_idx];


のみ。それ以外は0入力なので、値はGPIO_DAT_I_switchから来るはず。
しかし、RTLシミュレーションではGPIO_DAT_I_switch=0のまま。
でもPIO_DATAはソフトで書いた即値に変化してる。

では、PIO_DATAはどこから代入されたんだ??
実機でなんでLEDチカチカしないんだ?と思ってたけど、そもそもRTLシミュレーションの挙動がおかしい??
カレンダー
01 | 2020/02 | 03
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
累積訪問者
現在の訪問者
現在の閲覧者数:
最新記事
最新トラックバック
最新コメント
月別アーカイブ
カテゴリ
プロフィール

bobgosso

Author:bobgosso
FPGAのブログへようこそ!

検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード