FC2ブログ

[LM32](4).mem生成(Micosystem Builder)

久しぶりにやったら.elfから.hexが作れない。

host: x1 carbon
OS: Windows 10 Pro
Cygwin: 64bit

objcopy.exe -S -O $swname/Debug/$swname.elf $swname.srec

以前はこれをCygwinで実行すると.srecが生成出来たのに。効かない。
.srecが生成されたら、後はDesign Wave Magazine付属のプログラムで.mifと.hexへ変換していた。
以下どちらのobjcopyでも何も生成されず、エラーも出ず。

c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/bin/lm32-elf-objcopy.exe
c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/lm32-elf/bin/objcopy


Micosystem BuilderのSoftware Deploymentを使う
流れとしては、launchmicosystem.exeでEclipseのLattice Mico System(LMS) Builderを起動して、
メニューバー下の、LMS 1.0 D3.10画面で、HWプラットフォーム(ether.msb)を作り、
その隣の、C/C++画面で、ソフトウェアをビルドし.elfを作り、
その次に、SoftwareのDeploymentへ進む。

具体的には、
LMSメニュー > Tools > Software Deployment
 > 左のメニューから「Mico32 Multi On Chip Memory Deployment」をダブルクリック
 > 新規の設定画面に対して以下を入力してから、Startで.memが生成された。

Name : ether_soft
Project: Browseで開くと、C/C++画面で作ってビルドしたプロジェクト名を選択
C/C++ Application: Debug/ether_soft.elf を選択
Save Memory Initialization Files to directory: 保存先DIRを指定
Memory Initialization Files Prefix: これを何か入力しないとエラーが出た。


尚、「Mico32 On Chip Memory Deployment」の方も試してみたが、Startボタンが押せなかった。
おそらく今回の回路では、Inst RAMとData RAMが別々になっているので、Multiの方を使うべきのようだ。

ここまでで.memが出来たが、このままではINTEL FPGAのMemoryで初期値として渡せない。

0000407c
0000407c
0000407c
 :

なので、対応するINTEL HEX形式へ変換する。

過去に作ったRobyプログラムで変換できる。記事の最後の方のソースを使う。

[LM32].mem to Intel-Hex変換Ruby
http://bobgosso.blog13.fc2.com/blog-entry-338.html

あとはCygwinから以下を実行して、.hexへ変換し、さらにそれをシミュレーション場所へコピーして読み込めるようにする。

ruby ../../../../common/ruby/mem2intel_hex_v01.rb ether_soft_Data_IM.mem ether_soft_Data_IM.hex
ruby ../../../../common/ruby/mem2intel_hex_v01.rb ether_soft_Instruction_IM.mem ether_soft_Instruction_IM.hex

\cp ether_soft_Data_IM.hex ../../../../board/de2-115/
\cp ether_soft_Instruction_IM.hex ../../../../board/de2-115/



デバッグ用にobjdumpも作っておく


以下で生成可能。しかし、Cygwin64bitでは動作せず。32bitで実行したら成功した。

lm32-elf-objdump.exe -D ether_soft.elf > ether_soft.elf.objdump
スポンサーサイト

[LM32]仕様

汎用レジスタ

lm32_cpu.v
reg [`LM32_WORD_RNG] registers[0:(1<<`LM32_REG_IDX_WIDTH)-1]; // Register file



スタートアップルーチン

ether.elf:     file format elf32-lm32

Disassembly of section .boot:

00000000 <_reset_handler>:
0: 98 00 00 00 xor r0,r0,r0 > r0同士でXORすると必ず一致するから結果は0。これをr0へ格納するので0クリアになる。

<LatticeMico32 Processor Reference Manual>
After reset, the values in all of the above 32-bit registers are undefined. To
ensure that register 0 contains 0, the first instruction executed after reset
should be xor r0, r0, r0.


4: d0 00 00 00 wcsr IE,r0 > wcsr(Write Control or Status Register)でIE(Interrupt Enable)を0(Disable)にする。
8: d0 20 00 00 wcsr IM,r0 > IM(Interrupt Mask)を0(Disable)にする。
c: 78 01 00 00 mvhi r1,0x0 > mvhi(move high)で即値0x0を16bit左シフトした値をr1へ代入する。
10: 38 21 02 a8 ori r1,r1,0x2a8 > ori(bitwise logical OR)で、16bit即値0x2a8に上位16bitに0拡張(zero-extended)した32bit値とr1(32bit)のビット毎のORを取って、結果をr1へ格納。
14: d0 e1 00 00 wcsr EBA,r1 > EBA(Exception Base Address)へr1の値(つまり0x2a8)を代入。
18: f8 00 00 3a calli 100 <_crt0>
1c: 34 00 00 00 nop





汎用レジスタ

IEは1でEnable。IMより優先順位が高い。

<LatticeMico32 Processor Reference Manual>
IE – Interrupt Enable
1 – Interrupts enabled
IE, that determines whether interrupts are enabled. This flag has priority over the IM CSR.



IMはActive High。つまり、1でマスクされる。

<LatticeMico32 Processor Reference Manual>
The LatticeMico32 microprocessor supports up to 32 maskable, active-low,
level-sensitive interrupts. Each interrupt line has a corresponding mask bit in
the IM CSR. The mask enable is active high.








exitルーチンってなんだ?


  :
614: 34 02 00 06 mvi r2,6
618: 30 22 00 00 sb (r1+0),r2
61c: 78 01 80 00 mvhi r1,0x8000
620: 38 21 04 00 ori r1,r1,0x400
624: 34 02 00 07 mvi r2,7
628: 30 22 00 00 sb (r1+0),r2
62c: 78 01 80 00 mvhi r1,0x8000
630: 38 21 04 00 ori r1,r1,0x400
634: 34 02 00 44 mvi r2,68
638: 30 22 00 00 sb (r1+0),r2
63c: e3 ff ff fc bi 62c

00000640 <_exit>:
640: 34 08 00 01 mvi r8,1
644: ac 00 00 07 scall

00000648 :
648: 37 9c ff e8 addi sp,sp,-24
64c: 5b 9b 00 08 sw (sp+8),fp
  :

[LM32]トラブルシューティング

MSB = Mico System Builderでのエラー

[MSB] Couldn't compute FAST_CWD pointer.

micosystemのソフト(C/C++画面)のビルド時にこれが出たら、LMS画面の方に切り替えて、
何かしら変更して保存する。(例えば変更箇所なければ、一度変えて保存、戻して保存、という方法)
Generate AddressからRun Generatorまで実行し直す。それからビルドし直すとエラー無くビルド出来るようになった。
(Windows 10の場合)
しかし、Windows 8.1でも同様の方法で解決していたが、ある時から解決しなくなった。
8.1ではCygwinの問題だという指摘を掲示板で見つけた。

make all
0 [main] make 28276 find_fast_cwd: WARNING: Couldn't compute FAST_CWD pointer. Please report this problem to
the public mailing list cygwin@cygwin.com

make[1]: Entering directory `/cygdrive/c/user/work/quartus/DE2-115/micosystem/sw/ether/ether/Debug'
make[1]: Leaving directory `/cygdrive/c/user/work/quartus/DE2-115/micosystem/sw/ether/ether/Debug'





[Cygwin] objdumpが効かない

Windows 10上のCygwin64から以下いずれも実行しても何も返って来ないで終わる。
/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/bin/lm32-elf-objdump.exe -d ether.elf
/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/lm32-elf/bin/objdump.exe -d ether.elf

コマンドプロンプトから実行すると、以下を言われる。

cygwin1.dllが見つからないため、コードの実行を続行できません。プログラムを再インストール
すると、この問題が解決する可能性があります。


あ、でもこれは当たり前か。Cygwin用のプログラムobjdumpをコマンドプロンプトで実行しようとするのがダメか。

さらに試してみたら、
C:\cygwin64\Cygwin.bat
を使ってたために、この症状が起こったが、
C:\cygwin\Cygwin.bat
を使えば、正常に実行出来た。
Lattice DiamondインストールDIRのGNUツールは、Cygwin 32bit用実行ファイルという事だった。


[Cygwin] gcc: error trying to exec 'cc1': execvp: No such file or directory

memcvt.exeが効かなかったので、以前cygwin64bitのgccで生成したものだからと考え、
再度ビルドしてみたらこのエラー。
ごめんなさい、単にgccのパスを以下に間違えてただけでした。
/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/lm32-elf/bin/gcc
正しくは/bin/gccでした。これでエラー消えた。



[Cygwin] /tmp/ccmUUqJZ.s:2: Fatal error: unrecognized .section attribute: want a,w,x,M,S,G,T

/bin/gcc memcvt_171125.c -o memcvt_171125.exe


上に続き、/bin/gccでビルドしようとしたらこのエラー。

/tmp/ccmUUqJZ.s: Assembler messages:
/tmp/ccmUUqJZ.s:2: Fatal error: unrecognized .section attribute: want a,w,x,M,S,G,T



原因は$PATHの前に、
/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/lm32-elf/bin
を追加した事が原因だった。

export PATH=/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/lm32-elf/bin:$PATH:/cygdrive/c/user/onedrive/user/app/vim74-kaoriya-win64:/cygdrive/c/user/tool/lattice/memcvt:/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/bin



memcvt_171125.cをビルドする時は以下に戻す事で成功した。

export PATH=$PATH:/cygdrive/c/user/onedrive/user/app/vim74-kaoriya-win64:/cygdrive/c/user/tool/lattice/memcvt:/cygdrive/c/lscc/diamond/3.10_x64/micosystem/gtools/lm32/bin





inst_ram_data.ver Access Error accessing address=1000 min_address=fff max_address=0
In module:tb_DE2_115.uut.ether1.LM32.cpu.instruction_unit.ram.ram.m_default.altsyncram_inst;



[Cygwin] C:/lscc/diamond/3.10_x64/micosystem/gtools/lm32/libexec/gcc/lm32-elf/4.3.0/cc1.exe: error while loading shared libraries: cyggmp-3.dll: cannot open shared object file: No such file or directory

Cygwin32bit環境で以下を実行した際に出たエラー。

lm32-elf-gcc -c $src_name.c






[Quartus] object "GSR_INST" is not declared.

Error (10161): Verilog HDL error at DP16KD.v(157): object "GSR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.
Error (10161): Verilog HDL error at DP16KD.v(158): object "PUR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.



PUR PUR_INST (.PUR(1'b1)); > 追加
GSR GSR_INST (.GSR(1'b1)); > 追加


tri1 GSR_sig = GSR_INST.GSRNET;
tri1 PUR_sig = PUR_INST.PURNET;





[Quartus] Error (10200): Verilog HDL Conditional Statement error at wb_spi.v(338): cannot match operand(s) ...

Error (10200): Verilog HDL Conditional Statement error at wb_spi.v(338): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct




always @(posedge CLK_I or posedge RST_I)
if (RST_I || (c_status == ST_IDLE))  > ここがエラー箇所
clock_cnt <= 0;
else if (clock_cnt == CLOCK_SEL)
clock_cnt <= 0;
else
clock_cnt <= clock_cnt + 1;



always @(posedge CLK_I or posedge RST_I)
if (RST_I)
clock_cnt <= 0;
else if (c_status == ST_IDLE)  > RST_Iとは別にif文追加した。
clock_cnt <= 0;
else if (clock_cnt == CLOCK_SEL)
clock_cnt <= 0;
else
clock_cnt <= clock_cnt + 1;





[Veritak] ether_top.vo::Error: CLOCK2_50~input.bus_holdパラメータが見つかりません

Quartus生成ネットリストをVeritakでコンパイルするとこのエラー。

C:\user\work\quartus\DE2-115\ether\soc\simulation\custom\ether_top.vo(113291)::Error: CLOCK2_50~input.bus_holdパラメータが見つかりません



C/intelFPGA_lite/17.0/quartus/eda/sim_lib/altera_primitives.v
C/intelFPGA_lite/17.0/quartus/eda/sim_lib/altera_mf.v
C/intelFPGA_lite/17.0/quartus/eda/sim_lib/cycloneiv_atoms.v > 後述するが、ivではなく、iveが正解だった。


220_model.vじゃなく、altera_primitives.vを追加したらエラーが消えて、今度は以下が出た。


../../../../../../intelFPGA_lite/17.1/quartus/eda/sim_lib/altera_primitives.v(34):: Error: Macro name=begin_keywords is not defined.
../../../../../../intelFPGA_lite/17.1/quartus/eda/sim_lib/altera_primitives.v(44):: Error: Macro name=end_keywords is not defined.
../../../../../../intelFPGA_lite/17.1/quartus/eda/sim_lib/altera_primitives.v(84):: Error: Macro name=begin_keywords is not defined.
../../../../../../intelFPGA_lite/17.1/quartus/eda/sim_lib/altera_primitives.v(93):: Error: Macro name=end_keywords is not defined.



エラーの箇所は以下。

//if simulator dees not support begin_keywords/end_keywords pragmas then define macro SKIP_KEYWORDS_PRAGMA to skip them.
//pragmas are required to prevent "global" from being treated as a systemverilog 1800-2009 keyword
`ifndef SKIP_KEYWORDS_PRAGMA
`begin_keywords "1364-1995"
`endif



altera_primitives.vのコメント通り、以下を宣言してみる。

tb_ether_top.v内に追加
// 2017.12.29 to prevent error of altera_primitives.v for veritak
`define SKIP_KEYWORDS_PRAGMA



しかし、テストベンチに追記しても、下位モジュールに適用されないのでエラーは出た。
なので、Veritakで以下設定を行う。

Veritak > Verilogプロジェクト > プロジェクト設定 > Define Propagationの設定を変える。
  > 現状=Per File → 変更後=Throughout Project



すると、SKIP_KEYWORDS_PRAGMA関連エラーが消えた代わりに、元のエラーが出た。
つまり、altera_primitives.vが対策ではなかったようだ。

Loading vpi
スコープを生成中です。
C:\user\work\quartus\DE2-115\ether\soc\simulation\custom\ether_top.vo(113291)::Error: CLOCK2_50~input.bus_holdパラメータが見つかりません

C:\user\work\quartus\DE2-115\ether\soc\simulation\custom\ether_top.vo(113292)::Error: CLOCK2_50~input.simulate_z_asパラメータが見つかりません
  :



ネットリストでエラー箇所を見てみる。
// Location: LCCOMB_X112_Y36_N24
cycloneive_lcell_comb \led_cnt[9]~41 ( > cycloneivじゃなくて、cycloneiveだった。
  :
// synopsys translate_off
defparam \led_cnt[9]~41 .lut_mask = 16'hC30C; > このdefparamはcycloneive_lcell_comb宣言があればエラーにならない。
defparam \led_cnt[9]~41 .sum_lutc_input = "cin";
// synopsys translate_on



結論
以下条件でネットリストでゲート(GATE)シミュレーションが出来た。

<読み込むファイル>

GSR.v
PUR.v
tb_ether_top.v
simulation/custom/ether_top.vo > simulation/custom/ether_top.sdo
C/intelFPGA_lite/17.0/quartus/eda/sim_lib/altera_primitives.v
C/intelFPGA_lite/17.0/quartus/eda/sim_lib/altera_mf.v
C/intelFPGA_lite/17.0/quartus/eda/sim_lib/cycloneive_atoms.v



<設定>
Veritak > Verilogプロジェクト > プロジェクト設定 > Compile Mode = Altera SDF

<準備>
simulation/custom/*.sdo をVeritakのプロジェクトファイル(=実行場所)に保存する。

<結果>
SDFを実行場所に保存する前はこれ。

ERROR: can not open $sdf_annotate



ちゃんとSDF保存したらエラーが消えて、以下が出た。

------------- シミュレーションを開始します。--------------------
SDF: timing check[0] HOLD[Spec.186ps] FAILS at simtime 87ps <- 87ps: posedge tb_ether_top.uut.ether1|LM32|cpu|load_store_unit|irom_select_m.clk ==> tb_ether_top.uut.ether1|LM32|cpu|load_store_unit|irom_select_m.d
SDF: timing check[0] HOLD[Spec.186ps] FAILS at simtime 87ps <- 87ps: posedge tb_ether_top.uut.ether1|LM32|cpu|load_store_unit|d_we_o.clk ==> tb_ether_top.uut.ether1|LM32|cpu|load_store_unit|d_we_o.d
SDF: timing check[0] HOLD[Spec.186ps] FAILS at simtime 87ps <- 87ps: posedge tb_ether_top.uut.ether1|spi|wait_one_tick_done.clk ==> tb_ether_top.uut.ether1|spi|wait_one_tick_done.d






[Quartus] Mico32のゲート(GATE)シミュレーションが動かない

動く、の定義は、ソフトでLEDがチカチカすること。HWで組んだカウンタではチカチカしてる。

実験1

以前2014/11に動かなかったブログの後に、以下を自分でやってた。
[Quartus]グローバルクロック設定と確認方法
http://bobgosso.blog13.fc2.com/blog-entry-370.html
でも今回はこれだけでは動かず。



[Quartus] Mico32のデータ用SRAMがマッピングされない?


Quartus > Analysis & Synthesis > View Report > LPM Parameter Settings > RAMs
 > asyncram Parameter Settings by Entity instance
 > これで見ると、以下2つのRAMが表示されている。

ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_instruction_unit:instruction_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram
ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram

 > load_store_unit内のデータ用RAMも認識されている。



Quartus > Fitter > View Report > Resource Section > RAM Summary
ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_instruction_unit:instruction_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram|altsyncram_bni1:auto_generated|ALTSYNCRAM

 > ここでは、instruction_unit内の命令用RAMしか認識されてない。



Fitterレポート(*.fit.rpt)には以下のようにinstruction_unitのみRAMになってる。
; Fitter RAM Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         

; Name ; Type ; Mode ; Clock Mode ; Port A Depth ; Port A Width ; Port B Depth ; Port B Width ; Port A Input Registers ; Port A Output Registers ; Port B Input Registers ; Port B Output Registers ; Size ; Implementation Port A Depth ; Implementation Port A Width ; Implementation Port B Depth ; Implementation Port B Width ; Implementation Bits ; M9Ks ; MIF ; Location ; Mixed Width RDW Mode ; Port A RDW Mode ; Port B RDW Mode ; ECC Mode ; ECC Pipeline Registers ; Fits in MLABs ;

; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_instruction_unit:instruction_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram|altsyncram_hni1:auto_generated|ALTSYNCRAM ; AUTO ; True Dual Port ; Single Clock ; 2048 ; 32 ; 2048 ; 32 ; yes ; no ; yes ; no ; 65536 ; 2048 ; 32 ; 2048 ; 32 ; 65536 ; 8 ; inst_ram_data.mif ; M9K_X51_Y35_N0, M9K_X64_Y35_N0, M9K_X64_Y32_N0, M9K_X51_Y36_N0, M9K_X64_Y33_N0, M9K_X51_Y33_N0, M9K_X51_Y37_N0, M9K_X51_Y34_N0 ; Don't care ; New data with NBE Read ; New data with NBE Read ; Off ; No ; No - Unknown ;

Note: Fitter may spread logical memories into multiple blocks to improve timing. The actual required RAM blocks can be found in the Fitter Resource Usage section.



Mapレポート(*.map.rpt)を見ると、lm32_load_store_unitのRAMの扱われ方がinstruction_unitのRAMとは違うようだ。
Warning (14284): Synthesized away the following node(s):
Warning (14285): Synthesized away the following RAM node(s):
Warning (14320): Synthesized away node "ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram|altsyncram_dmi1:auto_generated|q_a[0]" File: C:/user/work/quartus/DE2-115/ether/soc/db/altsyncram_dmi1.tdf Line: 43
Warning (14320): Synthesized away node "ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram|altsyncram_dmi1:auto_generated|q_a[1]" File: C:/user/work/quartus/DE2-115/ether/soc/db/altsyncram_dmi1.tdf Line: 79
  :
Warning (14320): Synthesized away node "ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|pmi_ram_dp_true_altera:ram|altsyncram:ram|altsyncram_dmi1:auto_generated|q_a[31]" File: C:/user/work/quartus/DE2-115/ether/soc/db/altsyncram_dmi1.tdf Line: 1159



実機でLM32が動かない原因(これが動かない原因か不明だが、データ用RAMがマッピングされない事)は、
`define SIMULATION を宣言してるのが問題か?
以前どんな判断したか忘れたが、SIMULATIONをdefineしてた。
FPGAにインプリするためには、これdefineしてはダメなのでは?



[Quartus] Warning (xx): Synthesized away the following RAM node(s)

上に書いた流れでデバッグしてみた。
QuartusのAdvanced Settings(Synthesis)やAdvanced Settings(Fitter)のオプションを見直したが、これでは直らず。

以下のコメントをヒントに、load_store_unitのRAM出力をFPGAトップまで引き上げて信号出してみた。
結果、Synthesized awayのWarningは消えた!

https://www.alteraforum.com/forum/showthread.php?t=21882
A signal is synthesized away, if it's not used in the design, more exactly, if no FPGA output signal depends on it.





pmi_ram_dp_true_altera > Lattice用RAMからAltera用RAMへ個人的に変えてる
#(
// ----- Parameters -------
.pmi_family (`LATTICE_FAMILY),
.pmi_addr_depth_a (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1),
.pmi_addr_width_a (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)),
.pmi_data_width_a (`LM32_WORD_WIDTH),
.pmi_addr_depth_b (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1),
.pmi_addr_width_b (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)),
.pmi_data_width_b (`LM32_WORD_WIDTH),

.pmi_regmode_a ("noreg"),
.pmi_regmode_b ("noreg"),
.pmi_gsr ("enable"),
.pmi_resetmode ("sync"),
.pmi_init_file (`CFG_DRAM_INIT_FILE),
.pmi_init_file_format (`CFG_DRAM_INIT_FILE_FORMAT),
.module_type ("pmi_ram_dp_true")
)
ram (
.ClockA (clk_i),
   :
.QA (dram_data_out),
.QB (load_store_unit_ram_out) > 元は接続無しだったが、この信号に接続して上の階層へ引き出す。
);


lm32_load_store_unit.v > 上の階層へ引き出す
lm32_cpu.v        > 上の階層へ引き出す
ether.v          > 上の階層へ引き出す(これがMico System Builderで生成するRTLトップ)
ether_top.v       > ここがFPGAトップ。以下のように、てきとーに信号をLEDR[1](FPGA出力)へ出してる。

assign LEDR[1] = !load_store_unit_ram_out ;





[MSB] 割り込みハンドラに飛ばない

しょーもない話だけど、MSBで構成変更したりして、
 A = Generate Base Address
 I  = Generate IRQ
 D = Run DRC
 G = Run Generator
とやった時、Generatorでファイルが生成されない時は、
コンソールにばらばらと表示されずに、1行とかで終わる時がある。
これはたぶんファイルを生成しようと思ったら上書き出来ずに失敗した時とかだと思う。

対策として、既存のcomponentを改名して、一からcomponentフォルダを作らせるとちゃんとGeneratorが走る。
これをさぼってて、RTLが更新されなかった事が原因で、割り込みハンドラにジャンプしない原因になったらしい。



[Quartus] lpm_mltもSynthesized away nodeになった


Warning (14284): Synthesized away the following node(s):
Warning (14285): Synthesized away the following DSP element node(s):
Warning (14320): Synthesized away node "ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_multiplier:multiplier|lpm_mult:Mult0|mult_7dt:auto_generated|mac_mult7" File: C:/user/work/quartus/DE2-115/ether/soc/db/mult_7dt.tdf Line: 66
Warning (14320): Synthesized away node "ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_multiplier:multiplier|lpm_mult:Mult0|mult_7dt:auto_generated|mac_out8" File: C:/user/work/quartus/DE2-115/ether/soc/db/mult_7dt.tdf Line: 90





[Quartus] sysresetが内部FF駆動でGlobal Signalになってない?

<ether.vの中身>

reg [2:0] counter;
wire sys_reset = !counter[2];


Mico System Builderで生成されたRTLトップ見ると、リセット信号は内部カウンタから生成されてる。
これがあると、Global Signalとして扱われるのか?

Quartus > Fitter > View Report > Resource Section > Global & Other Fast Signals
ここでGlobal Signalを調べられる。

CLOCK_50  Location=PIN_Y2  Fan-Out=2107
KEY[0]    Location=PIN_M23  Fan-Out=2092

Fan-Outが2000以上あるから、counterというFF(FlipFlop)を超えてGlobal Signalが適用されてるみたい。




[Quartus] LM32動かない箇所シミュレーション

instruntion_unit/ramはRTLと同じ動きしてるように見えるが、load_store_unit/ramは同じでない。
しかもPOATB/WEは信号が消えてる。

ネットリストでの信号名

◆ether1|LM32|cpu|load_store_unit{ramの信号
// Location: M9K_X51_Y25_N0
cycloneive_ram_block \ether1|LM32|cpu|load_store_unit|ram|ram|auto_generated|ram_block1a28 (
.portawe(gnd),
.portare(vcc),
.portaaddrstall(gnd),
.portbwe(gnd),  > PORTBのWEはなぜGNDになってる?
.portbre(vcc),
.portbaddrstall(gnd),
.clk0(\CLOCK_50~inputclkctrl_outclk ),
.clk1(\CLOCK_50~inputclkctrl_outclk ),
.ena0(\ether1|LM32|cpu|stall_x~3_combout ),
.ena1(\ether1|LM32|cpu|stall_m~combout ),
.ena2(vcc),
.ena3(vcc),
.clr0(gnd),
.clr1(gnd),
.portadatain({\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout }),
.portaaddr({\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout ,\~GND~combout }),
.portabyteenamasks(1'b1),
.portbdatain({ \ether1|LM32|cpu|load_store_unit|dram_store_data_m[31]~63_combout , \ether1|LM32|cpu|load_store_unit|dram_store_data_m[30]~61_combout , \ether1|LM32|cpu|load_store_unit|dram_store_data_m[29]~59_combout , \ether1|LM32|cpu|load_store_unit|dram_store_data_m[28]~57_combout }),
.portbaddr({\ether1|LM32|cpu|operand_m [12],\ether1|LM32|cpu|operand_m [11],\ether1|LM32|cpu|operand_m [10],\ether1|LM32|cpu|operand_m [9],\ether1|LM32|cpu|operand_m [8],\ether1|LM32|cpu|operand_m [7],\ether1|LM32|cpu|operand_m [6],\ether1|LM32|cpu|operand_m [5],\ether1|LM32|cpu|operand_m [4],
\ether1|LM32|cpu|operand_m [3],\ether1|LM32|cpu|operand_m [2]}),
.portbbyteenamasks(1'b1),
.devclrn(devclrn),
.devpor(devpor),
.portadataout(\ether1|LM32|cpu|load_store_unit|ram|ram|auto_generated|ram_block1a28_PORTADATAOUT_bus ),
.portbdataout(\ether1|LM32|cpu|load_store_unit|ram|ram|auto_generated|ram_block1a28_PORTBDATAOUT_bus ));


portbweがGND固定になってる。RTLでは信号入れてるのに。動いてない、と判断されたのか?

.WrA (`FALSE),
.WrB (store_q_m & dram_select_m),




; Registers Removed During Synthesis

; Register name ; Reason for Removal

; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|d_stb_o ; Merged with ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|d_cyc_o ;
; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|dram_select_m ; Stuck at GND due to stuck port data_in ;
; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|wb_select_m ; Stuck at GND due to stuck port data_in ;
; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|wb_load_complete ; Lost fanout ;
; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|byte_enable_m[1] ; Merged with ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|byte_enable_m[0] ;
; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|size_m[1] ; Merged with ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|byte_enable_m[2] ;



; Removed Registers Triggering Further Register Optimizations

; Register name ; Reason for Removal ; Registers Removed due to This Register ;

; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|dram_select_m ; Stuck at GND ; ether:ether1|lm32_top:LM32|lm32_cpu:cpu|lm32_load_store_unit:load_store_unit|wb_load_complete ;
; due to stuck port data_in ;


load_store_unitのRAM/portbweがGNDにスタックされているので、論理が動いてないからかと思い、
FPGA出力まで引き出して見たが変わらず。

load_store_unit|dram_select_m ; Stuck at GND due to stuck port data_in

よくよく見ると、RAM/WrBに入力されているstore_q_m & dram_select_mの方ではなくて、
「due to stuck port data_in」って、WrBがDisable?

load_store_unit.ramのパラメータを調べると、

defparam ram.width_byteena_a= 1;
defparam ram.width_byteenb_a= 1;

が抜けてた。これが原因か?
bit幅はてきとーに1bitにした。
 :
試すが、これでもLM32ソフトによるLEDチカチカは動作せず。
シミュレーションだと意図した動きになってるのに、なぜかQuartusでDE2-115にインプリすると、Mico32のプログラムが動作しない。




[LM32] system_conf.v LATTICE_FAMILYは"EC"でなく"SC"を使え。

ソース追ってないので理由は不明だが、system_conf.vで
`define LATTICE_FAMILY "EC"
から
`define LATTICE_FAMILY "SC"
にしたら、Mico32のプログラムによるLEDチカチカした!

ちなみにsystem.confの最初の数行は以下設定。

//`define LATTICE_FAMILY "EC"
// 2018.1.4
`define LATTICE_FAMILY "SC"
`define LATTICE_FAMILY_EC
`define LATTICE_DEVICE "All"
`ifndef SYSTEM_CONF
`define SYSTEM_CONF
  :



変更した箇所として、厳密にはLATTICE_FAMILYをSCにしたら、
components/uart_core/rtl/verilog/rxcver_fifo.v
components/uart_core/rtl/verilog/txcver_fifo.v
で使ってるpmi_fifo_dcが無いと言われ、同等回路をQuartusのIP CatalogでFIFO作った(中身はdcfifo)。




1.85us付近からLM32のINST RAMアドレス0x1a4から0xb4のループになる


問題?が起こる前にやった事
ソースの置き場所をgitへまとめた後、DE2-115でMico32の動作を確認しようとしたら、
IROM=BASE 0x0, Size 0x2000、 DRAM=BASE 0x2000, Size 0x2000
ではelfがオーバーした。なので、
IROM=BASE 0x0, Size 0x4000、 DRAM=BASE 0x4000, Size 0x4000
に変えた。


症状

ループとなるアドレスは、
tb_ether_top.uut.ether1.LM32.cpu.instruction_unit.ram.ram.address_a
の信号でいうと、0x69から0x6dの間。
1アドレス32bit(4バイト)のため、4倍すると、0x1a4から0xb4になる。
elfからobjdumpした中身で見ると、このアドレスの期間は以下になる。


1a0: 38 63 44 7c ori r3,r3,0x447c

000001a4 <.ClearBSS>:
1a4: 44 23 00 04 be r1,r3,1b4 <.CallConstructor>
1a8: 58 20 00 00 sw (r1+0),r0
1ac: 34 21 00 04 addi r1,r1,4
1b0: e3 ff ff fd bi 1a4 <.ClearBSS>

000001b4 <.CallConstructor>:
1b4: 78 04 00 00 mvhi r4,0x0


何やらmain関数に行く前にループしてるような感じ。


解決するまでにやった事

・system_conf.vを古い方を読んでいた。不要なsystem_conf.vを削除して1つだけにした。さらに以下。
  > LATTICE_FAMILYは"SC"になってるので問題なし。
  > `define CFG_IROM_LIMIT 32'h1fff から 32'h3fff へ変更した。
  > `define CFG_DRAM_BASE_ADDRESS 32'h2000 から 32'h4000 へ変更した。
  > `define CFG_DRAM_LIMIT 32'h3fff から 32'h7fff へ変更した。

・IROMとDRAMのアドレスを12ビット(4096バイト)にしたので、Verilogソースもアドレス12ビットになっているか確認した。

・memory.def を修正。
  > .rdata 0x00002000: { のアドレスを 0x00004000 に変更した。
  > スタックポインタの . = 0x00004000 + (1024*8) - 4; の加える値を (2048*8) に変更した。

・シミュレーションを175usまで進めたら、main関数の先頭コードまで進んだ。


IROM/DRAMサイズを変えた事で、上記の変更は必要になったが、加えて、シミュレーション時間を175usまで
待たずに、途中の動きを見て、勝手に問題視したようだ。
main関数まで進めた設定で、1.85us付近を見ると、やはり.address_a信号は、
1.8us付近から、0x69から0x6dの間のループが始まり、17.17us付近まで続いていた。
なのでこの動きは全く問題無いみたい。

[LM32](3)interrupt_handlerにjumpしない原因解析

ether.elfをobjdumpで逆アセンブルした。
シミュレーション波形と見比べてみると、
INSTメモリは0x0番地から実行される。


00000000 <_reset_handler>:
0: 98 00 00 00 xor r0,r0,r0
4: d0 00 00 00 wcsr IE,r0
8: d0 20 00 00 wcsr IM,r0
c: 78 01 00 00 mvhi r1,0x0
10: 38 21 02 a8 ori r1,r1,0x2a8
14: d0 e1 00 00 wcsr EBA,r1
18: f8 00 00 3a calli 100 <_crt0> > ここで_crt0(0x100)へjump
1c: 34 00 00 00 nop > 0x18 calliで実際にjumpする前にフェッチされた。

00000020 <_breakpoint_handler>:
20: 90 e0 38 00 rcsr r7,EBA > 0x18 calliで実際にjumpする前にフェッチされた。
   :
fc: 34 00 00 00 nop > ここ0xfcへjumpした。なぜ0x100に直接jumpしないか不明。

00000100 <_crt0>:
100: 98 00 00 00 xor r0,r0,r0
104: 78 1c 20 00 mvhi sp,0x2000
108: 3b 9c 1f fc ori sp,sp,0x1ffc
10c: 78 1a 20 00 mvhi gp,0x2000
110: 3b 5a 80 00 ori gp,gp,0x8000
114: 78 01 00 00 mvhi r1,0x0
118: 38 21 02 a4 ori r1,r1,0x2a4
11c: 78 02 00 00 mvhi r2,0x0
120: 38 42 02 a4 ori r2,r2,0x2a4
124: 44 22 00 04 be r1,r2,134 <_crt0+0x34>
128: 78 03 00 00 mvhi r3,0x0
12c: 38 63 08 f8 ori r3,r3,0x8f8
130: f8 00 00 30 calli 1f0 <_relocate_text>
134: 78 01 20 00 mvhi r1,0x2000
138: 38 21 00 00 ori r1,r1,0x0
13c: 78 02 00 00 mvhi r2,0x0
140: 38 42 08 f8 ori r2,r2,0x8f8
144: 44 22 00 08 be r1,r2,164 <_crt0+0x64>
148: 78 03 20 00 mvhi r3,0x2000
14c: 38 63 00 04 ori r3,r3,0x4
150: 44 23 00 05 be r1,r3,164 <_crt0+0x64>
154: c8 61 18 00 sub r3,r3,r1
158: 78 04 00 00 mvhi r4,0x0
15c: 38 84 06 88 ori r4,r4,0x688
160: d8 80 00 00 call r4 > ここで0x688へjump。
164: 78 01 20 00 mvhi r1,0x2000 > jumpする前にフェッチされた。
168: 38 21 00 04 ori r1,r1,0x4 > jumpする前にフェッチされた。
16c: 78 02 00 00 mvhi r2,0x0
   :
684: c3 a0 00 00 ret

00000688 :
688: b8 20 38 00 mv r7,r1 > 今度のjumpは0x688に直接jumpした。
68c: b8 40 28 00 mv r5,r2
690: b8 20 20 00 mv r4,r1
694: 34 06 00 0f mvi r6,15
698: 50 c3 00 19 bgeu r6,r3,6fc
69c: b8 41 08 00 or r1,r2,r1
6a0: 20 21 00 03 andi r1,r1,0x3
6a4: 5c 20 00 16 bne r1,r0,6fc
6a8: b8 c0 28 00 mv r5,r6
6ac: 28 41 00 00 lw r1,(r2+0)
6b0: 34 63 ff f0 addi r3,r3,-16
6b4: 58 81 00 00 sw (r4+0),r1
6b8: 34 42 00 04 addi r2,r2,4
6bc: 28 41 00 00 lw r1,(r2+0)
6c0: 34 84 00 04 addi r4,r4,4
6c4: 58 81 00 00 sw (r4+0),r1
6c8: 34 42 00 04 addi r2,r2,4
6cc: 28 41 00 00 lw r1,(r2+0)
6d0: 34 84 00 04 addi r4,r4,4
6d4: 58 81 00 00 sw (r4+0),r1
6d8: 34 42 00 04 addi r2,r2,4
6dc: 28 41 00 00 lw r1,(r2+0)
6e0: 34 84 00 04 addi r4,r4,4
6e4: 58 81 00 00 sw (r4+0),r1
6e8: 34 42 00 04 addi r2,r2,4
6ec: 34 84 00 04 addi r4,r4,4
6f0: 50 a3 00 0f bgeu r5,r3,72c
6f4: e3 ff ff ee bi 6ac
6f8: b8 40 28 00 mv r5,r2
6fc: 34 63 ff ff addi r3,r3,-1
700: 64 61 ff ff cmpei r1,r3,-1
704: 5c 20 00 08 bne r1,r0,724
708: 40 a1 00 00 lbu r1,(r5+0)
70c: 34 63 ff ff addi r3,r3,-1
710: 64 62 ff ff cmpei r2,r3,-1
714: 30 81 00 00 sb (r4+0),r1
718: 34 a5 00 01 addi r5,r5,1
71c: 34 84 00 01 addi r4,r4,1
720: 44 40 ff fa be r2,r0,708
724: b8 e0 08 00 mv r1,r7
728: c3 a0 00 00 ret
72c: 34 01 00 03 mvi r1,3
730: 50 23 ff f2 bgeu r1,r3,6f8  > ここで何かが起こり、0x0番地へ戻った。simulation時間62us地点。

その後、IROMのアドレスを見ると。0x0から順次実行
  > 0x168まで行った後、0x688へjump
  > そのまま0x730まで実行した後、0x0へ戻る。2回目のこの地点でsim時間118us地点。
これがずっと繰り返されるようだ。



0x730での命令bgeuが原因のようだ。何が起こったのか。

LatticeMico32 Processor Reference Manual で調べると、
r1がr3以上であれば、PC + へ分岐する。
という事らしい。

bgeu r1,r3,6f8
Syntax = bge rX, rY, imm16
Semantics = if (gpr[rX] >= gpr[rY]) PC = PC + sign_extend(imm16 << 2)




■memcvt.c設定を疑う

#define INST_BASE_ADDR 0x00000000
#define INST_SIZE_LIMIT (1024*16)
#define RWDATA_BASE_ADDR 0x20000000
#define RWDATA_SIZE_LIMIT (1024*8)
#define TARGET_MEM_WIDTH (256/8) > これは.mifではなく.v用かな?
#define TARGET_MEM_WIDTH_MIF 4

system_conf.v内の設定 `define CFG_IROM_LIMIT 32'h3fff
system_conf.v内の設定 `define CFG_DRAM_LIMIT 32'h20003fff


上の設定で、
#define TARGET_MEM_DEPTH_MIF 2048
こうすると、data_ram_data.mifは全て0x00データになる。これは以前正常動作してた時と同じ。
しかし今はリセット番地0x0へのループが発生。

#define TARGET_MEM_DEPTH_MIF 4096
ちなみにこうすると、data_ram_data.mifは0x801辺りから最後0xfffまで初期値が存在するようになった。
こちらもリセット番地0x0へのループが発生。

[LM32](2)LEDチカチカ

ターゲット評価ボード= Terasic社 Atlas-SOC
 ※ 途中からVEEK(別名tPAD、DE2-115+LCD)をターゲットに変えて作業してる。


Quartusのqpf、qsfのひな型を作る


http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=165&No=941&PartNo=4

Terasic社Atlas-SOCページから、
DE0-Nano-SoC CD-ROM (rev.B0 / rev.C0 Board) 1.1.0 - 2015-12-29
のCDROMアイコンをクリック。

DE0-Nano-SoC_v.1.1.0_HWrevB0_revC0_SystemCD.zip
を入手した。

解凍後、
DE0-Nano-SoC_v.1.1.0_HWrevB0_revC0_SystemCD\Tools\SystemBuilder

DE0_Nano_SoC_SystemBuilder.exe
を実行する。

欲しい希望だけチェックして、Generateすると、qpfやqsfが生成される。


//=======================================================
// This code is generated by Terasic System Builder
//=======================================================

module ether_top(

//////////// CLOCK //////////
input FPGA_CLK1_50,
input FPGA_CLK2_50,
input FPGA_CLK3_50,

//////////// KEY //////////
input [1:0] KEY,

//////////// LED //////////
output [7:0] LED,

//////////// SW //////////
input [3:0] SW,

//////////// GPIO_0, GPIO connect to LT24 - 2.4" LCD and Touch //////////
input LT24_ADC_BUSY,
output LT24_ADC_CS_N,
output LT24_ADC_DCLK,
output LT24_ADC_DIN,
input LT24_ADC_DOUT,
input LT24_ADC_PENIRQ_N,
output LT24_CS_N,
output [15:0] LT24_D,
output LT24_LCD_ON,
output LT24_RD_N,
output LT24_RESET_N,
output LT24_RS,
output LT24_WR_N
);

wire [23:0] dummy_led ;


//=======================================================
// REG/WIRE declarations
//=======================================================




//=======================================================
// Structural coding
//=======================================================

ether ether1 (
.clk_i ( FPGA_CLK1_50 )
,.reset_n ( SW[0] )
,.sramsram_wen ( )
,.sramsram_data ( )
,.sramsram_addr ( )
,.sramsram_csn ( )
,.sramsram_be ( )
,.sramsram_oen ( )
,.uartSIN ( )
,.uartSOUT ( )
,.gpioPIO_OUT ( { dummy_led, LED } )
,.spiMISO_MASTER ( )
,.spiMOSI_MASTER ( )
,.spiSS_N_MASTER ( )
,.spiSCLK_MASTER ( )
,.i2cm_ocSDA ( )
,.i2cm_ocSCL ( )
);

endmodule


最後にインスタンスされたether1は、LatticeMico32と合体するために追加したもの。




Mico System Builderでシステムを作る

File > New Platform > PlatformHを選択。
イーサネットMAC入りだが、バージョン?のエラーが出てTri speed MACがあるとGenerate出来ない。
なので削除して、別途、Opencoresから入手したRTLを手作業で追加する事にする。

さらに、命令メモリとデータメモリはLM32のInline Memoryを使う事にする。
Mico System Builder > LMS1.0 D3.10タブ > ether.msbのシステムツリー
 > LM32をダブルクリック > ウィンドウ開く
 > Generalタブ > Instruction Cache、Data Cacheのチェック外す
 > Inline Memoryタブ
 > Instruction Inline MemoryのEnableにチェック、
    Base Addressを0x00004000、
    Size of Memoryを0x00002000、
    Initialization File Nameをinst_ram_data.v、File FormatをHEXへ。
     ※ Base Addressはシステムツリーで割り当てたアドレスを設定。
 > Data Inline MemoryのEnableにチェック、
    Base Addressを0x00008000、
    Size of Memoryを0x00002000、
    Initialization File Nameをdata_ram_data.v、File FormatをHEXへ。
 > LM32の設定は完了。
 > システムツリーの中で、Asyncramを削除。

構成が決まったら、
Platform Tools > Generate Address
Platform Tools > Generate IRQ
Platform Tools > Run DRC
Platform Tools > Run Generator
を順番に実行。

これで
soc/* ・・・ システムトップのRTL
component/* ・・・ 各コンポーネットのRTL
が生成された。



Mico System Builderでソフトをビルド

Mico System Builder > 画面左上のC/C++、に切り替え > 右クリック
 > New > mico Managed Make C Project
 > LED Test small size、を選択してプロジェクトを生成。

システムツリーでAsyncramを削除し、Inline MemoryをEnableしたので、プログラムデータの配置場所も変更する必要がある。
左上のプロジェクト名(今回はether)で右クリック > Properties
 > Platform
 > Linker Script > Program memory = Instructoin_IM ※ LM32設定で決めたInline Memory名。
 > Linker Script > Read-only data memory = Data_IM ※ LM32設定で決めたInline Memory名。
 > Linker Script > Read/write data memory = Data_IM
 > Stdio Redirection > stdin = RS-232(uart) ※ JTAG-UARTから変えておく。後でUARTも設定予定。
 > Stdio Redirection > stdout = RS-232(uart) ※ JTAG-UARTから変えておく。後でUARTも設定予定。
 > Stdio Redirection > stderr = RS-232(uart) ※ JTAG-UARTから変えておく。後でUARTも設定予定。

このまま右クリック > Build Projectでビルドすると、
LED_BASE_ADDRESSが無い
とエラーになる。

GPIOのアドレスを以下の通り設定する。
#define LED_BASE_ADDRESS 0x80000300

これでBuild Projectをやると、
C:\user\work\quartus\atlas-soc\micosystem\sw\ether\Debug\ether.elf
が生成された。




elf -> srec -> mifへ変換
ALTERA製SRAMで初期値として読み込むために、mifに変換する。

elfからsrecはこれで実行。
/usr/bin/objcopy.exe -S -O srec ether.elf ether.srec

srecからmifへの変換は、以前デザインウェーブ?で特集あった際の山際さん作成memcvt.cを使う。
今回のメモリアドレス、サイズに合わせて以下だけ修正。

#define INST_BASE_ADDR 0x00004000
#define INST_SIZE_LIMIT (1024*16)
#define RWDATA_BASE_ADDR 0x00008000
#define RWDATA_SIZE_LIMIT (1024*16)



gcc memcvt_171021.c -o memcvt_171021.exe
これでexeが出来た。

memcvt_171021.exe ether.srec
を実行すると、以下mif形式のファイルが生成される。
ファイル名はmemcvt_171021.cで指定したもの。

data_ram_data.mif
inst_ram_data.mif

これでALTERA製SRAM初期値として読めるmif形式になった。



SRAMをALTERA製に置き換える

今回、Terasic社Atlas-SOCにて実機評価するため、メモリはALTERA製に置き換える必要がある。




ALTERA製SRAM初期値をセット




Veritakでシミュレーション準備1

フォルダの位置関係は以下。

C:\user\work\quartus\atlas-soc\micosystem\ether ・・・ Mico System Builderでの生成場所
C:\user\work\quartus\atlas-soc\micosystem\ether\soc ・・・ Veritak実行場所
C:\user\work\quartus\atlas-soc\micosystem\ether\component ・・・ Lattice Mico32システムの各コンポーネント場所
C:\user\work\quartus\atlas-soc\quartus ・・・ Quartusコンパイル場所

この相対位置において、いちいちVeritakにRTLを登録するのは面倒。
なので、必要ファイルパスを書いたVerilogを作成し、このファイルをVeritakで読み込む事にする。

<lm32_file_include.v の内容>

`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/VHI.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/VLO.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/GSR.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/PUR.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/DP8KA.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/BB.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ecp3/DP16KC.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/lptm2/DP8KC.v"
`include "../../../../../../../lscc/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u/DP16KD.v"
`include "../components/gpio/rtl/verilog/tpio.v"
`include "../components/lm32_top/rtl/verilog/lm32_include.v"
`include "../components/lm32_top/rtl/verilog/lm32_include_all.v"
`include "../../../quartus/ether_top.v"
`include "ether.v"
`include "../../../quartus/tb_ether_top.v"



これ以外の設定は以下のみ

Veritak > Verilogプロジェクト > プロジェクトの編集 > 上で登録するフォルダまで行き、「Add Include Dir」
ボタンで追加する。
追加したフォルダは以下3つ。

-include_dir ../component/uart_core/rtl/verilog
-include_dir ../component/lm32_top/rtl/verilog
-include_dir ../component/i2cm_opencores/rtl/verilog



Lattice Mico32の各コンポーネントRTL内でincludeされているRTLがある。
上記の設定が無いとパスが分からずエラーになる。
なので、RTLの存在フォルダを登録する事で自動的にincludeされてエラーが無くなった。

 ※ 必要なファイルは全てlm32_file_include.vにまとめて書けば、include_dirの設定は不要になってシンプルになる。
    また後で改善する事にして、とりあえずこれで進める。



Veritak向けRTL修正: gpio.v

Mico System Builderで生成したRTLのうち、そのままVeritakで読めないものがある。

components\gpio\rtl\verilog\gpio.v
赤字のようにラベル?を付けないとエラーになった。
けっこうな数があって面倒だが一回だけ我慢して修正版は保存しておこう。

generate
if (OUTPUT_PORTS_ONLY == 1) begin
if (GPIO_WB_DAT_WIDTH == 8) begin
genvar ipd_idx;
for (ipd_idx = 0; (ipd_idx < DATA_WIDTH) && (ipd_idx < 8); ipd_idx = ipd_idx + 1)
begin: hoge1
always @(posedge CLK_I or posedge RST_I)
if (RST_I)
PIO_DATA[ipd_idx] <= #UDLY 0;
else if (GPIO_STB_I && !GPIO_ACK_O && GPIO_WE_I && GPIO_ADR_I[3:0] == 4'b0000)
PIO_DATA[ipd_idx] <= #UDLY GPIO_DAT_I_switch[ipd_idx];
end
if (DATA_WIDTH > 8) begin
genvar jpd_idx;
for (jpd_idx = 8; (jpd_idx < DATA_WIDTH) && (jpd_idx < 16); jpd_idx = jpd_idx + 1)
begin: hoge2
always @(posedge CLK_I or posedge RST_I)
if (RST_I)
PIO_DATA[jpd_idx] <= #UDLY 0;
else if (GPIO_STB_I && !GPIO_ACK_O && GPIO_WE_I && GPIO_ADR_I[3:0] == 4'b0001)
PIO_DATA[jpd_idx] <= #UDLY GPIO_DAT_I_switch[jpd_idx-8];
end
end





Veritak向けRTL修正: lm32_load_store_unit.v

Inline MemoryをEnableすると以下エラーが出た。

C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(200)::Error: irom_store_data_m複数のレンジの記述方法を統一してください
moduleを評価中です。
C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(482)::Error: irom_store_data_m [ ]内が宣言でのレンジを超えています。
C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(483)::Error: irom_store_data_m [ ]内が宣言でのレンジを超えています。
C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(484)::Error: irom_store_data_m [ ]内が宣言でのレンジを超えています。
C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(485)::Error: irom_store_data_m [ ]内が宣言でのレンジを超えています。
C:\user\work\quartus\atlas-soc\micosystem\ether\components\lm32_top\rtl\verilog\lm32_load_store_unit.v(111)::Error: irom_store_data_m port宣言が見つかりません。



これは以下が原因だった。修正する。
micosystem/ether/components/lm32_top/rtl/verilog/lm32_load_store_unit.v

199行目から。
`ifdef CFG_IROM_ENABLED

output irom_store_data_m; // Store data to Instruction ROM
wire [`LM32_WORD_RNG] irom_store_data_m;
  ↓
output [`LM32_WORD_RNG] irom_store_data_m; // Store data to Instruction ROM
wire [`LM32_WORD_RNG] irom_store_data_m;





VeritakでRAMデータ内容見たい時

Veritak > Verilogプロジェクト > プロジェクト設定 > Limit Memory Size = 32KBytesに設定

それから、コンパイル後に、メモリアレイ信号を波形ビューワに追加してから、シミュレーション開始する。
すると、内容が見れるようになった。



pmi_def.vは使うな!中身が無い。

lm32_load_store_unit.v
で以下エラー出てない?
それならpmi_addsub.vを疑え!

Warning: Non-aligned word access. Address: 0xzzzzzzzz Time: 5070000.
Instruction bus error. Address: 00000784
Instruction bus error. Address: 00000788
Instruction bus error. Address: 0000078c



このエラーの理由は
lm32_load_store_unit.v load_store_address_m
がsize_m=2の時にHizになる事が原因のようだ。
なぜHizになるか追ってみると、addsubからHizの結果が出るからだ。
pmi_addsubの実態を見ると、pmi_def.vに宣言されているが、中身が無い。これが原因のようだ。

pmi_addsub.vの実態あるやつは以下にある。
c/lscc/diamond/3.10_x64/cae_library/simulation/verilog/pmi/pmi_addsub.v

しかし、lm32_include_all.v を読み込むと、pmi_def.vを読まれてしまう。
micosystem/ether/components/lm32_top/rtl/verilog/lm32_include_all.v:`include "pmi_def.v"

けど、lm32_include_all.vを使わないと面倒なので、lm32_include_all.vの内容から、
SIMULATIONのdefineをすれば、pmi_def.vはincludeされないようだ。これで解決。

`ifndef SIMULATION
`include "pmi_def.v"
`endif






Quartus向けRTL修正: wb_spi.v


Error (10200): Verilog HDL Conditional Statement error at wb_spi.v(339): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct



337行目

always @(posedge CLK_I or posedge RST_I)
修正前: if (RST_I || (c_status == ST_IDLE))
修正後: if (RST_I )
clock_cnt <= 0;
追加  : else if (c_status == ST_IDLE)
追加  : clock_cnt <= 0;




Quartus向けRTL修正: lm32_cpu.v



Error (10257): Verilog HDL error at lm32_cpu.v(2021): unsized constants are not allowed in concatenations



2021行目

assign cfg = {
`LM32_REVISION,
watchpoints[3:0],
breakpoints[3:0],
interrupts[5:0],
`ifdef CFG_JTAG_UART_ENABLED
`TRUE,  > ★原因はこれ。1'b1にしたらエラー消えた。altera_mf.vにも同じ宣言が整数(32bit?)でされてるのが原因?
`else
`FALSE,  > ★原因はこれ。1'b0にしたらエラー消えた。altera_mf.vにも同じ宣言が整数(32bit?)でされてるのが原因?
`endif
 :



2087行目
cfgの下のcfg2も同じ原因。

assign cfg2 = {





Quartus向けRTL修正: lm32_cpu.v


Error (10207): Verilog HDL error at altera_mf.v(48976): can't resolve reference to object "convert_to_ver_file"






Quartus向けRTL修正: DP16KD.v


Error (10161): Verilog HDL error at DP16KD.v(160): object "GSR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.
Error (10161): Verilog HDL error at DP16KD.v(161): object "PUR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.
Error (10161): Verilog HDL error at DP8KA.v(117): object "GSR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.
Error (10161): Verilog HDL error at DP8KA.v(118): object "PUR_INST" is not declared. Verify the object name is correct. If the name is correct, declare the object.



C/lscc/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u/DP16KD.v

GSR GSR_INST( .GSR(GSR) ); > ★追加
PUR PUR_INST( .PUR(PUR) ); > ★追加

//tri1 GSR_sig = GSR_INST.GSRNET;
//tri1 PUR_sig = PUR_INST.PURNET;

tri1 GSR_sig, PUR_sig;
`ifndef mixed_hdl
assign GSR_sig = GSR_INST.GSRNET;
assign PUR_sig = PUR_INST.PURNET;
`else
gsr_pur_assign gsr_pur_assign_inst (GSR_sig, PUR_sig);
`endif



C/lscc/diamond/3.10_x64/cae_library/simulation/verilog/ec/DP8KA.v

GSR GSR_INST( .GSR(GSR) ); > ★追加
PUR PUR_INST( .PUR(PUR) ); > ★追加

tri1 GSR_sig = GSR_INST.GSRNET;
tri1 PUR_sig = PUR_INST.PURNET;



なんか面倒くさい
以前やった時はこんな事しなかったな。
探したらlm32_monitor_ram_altera.vを発見。
latticeのDP8とかのRAMは使わずに、lm32_monitor_ramをアルテラ用に変えてました。今回もこれを採用。



Quartus向けRTL修正: lm32_monitor_ram.v


以前作ったlm32_monitor_ram_altera.vを使う事に。

`include "system_conf.v"

module lm32_monitor_ram_altera (DataInA, DataInB, AddressA, AddressB, ClockA,
ClockB, ClockEnA, ClockEnB, WrA, WrB, ResetA, ResetB, QA, QB);
input [31:0] DataInA;
input [31:0] DataInB;
input [8:0] AddressA;
input [8:0] AddressB;
input ClockA;
input ClockB;
input ClockEnA;
input ClockEnB;
input WrA;
input WrB;
input ResetA;
input ResetB;
output [31:0] QA;
output [31:0] QB;

altsyncram ram_0 (
.address_a ({AddressA,2'b00})
, .clock0 (ClockA )
, .data_a (DataInA[7:0] )
, .wren_a (WrA )
, .q_a (QA[7:0] )
, .rden_a (1'b1)
, .rden_b (1'b1)
, .address_b ({AddressB,2'b00})
, .clock1 (1'b1 )
, .data_b (DataInB[7:0] )
, .wren_b (WrB )
, .q_b (QB[7:0] )
, .addressstall_a (1'b0 )
, .addressstall_b (1'b0 )
, .byteena_a (1'b1)
, .byteena_b (1'b1)
, .clocken0 (1'b1 )
, .clocken1 (1'b1 )
, .clocken2 (1'b1)
, .clocken3 (1'b1)
, .eccstatus ()
, .aclr0 ()
, .aclr1 ()
);
defparam
ram_0.clock_enable_input_a = "BYPASS",
ram_0.clock_enable_output_a = "BYPASS",
ram_0.init_file = "inst_ram_data.hex",
ram_0.intended_device_family = "Cyclone III",
ram_0.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
ram_0.lpm_type = "altsyncram",
ram_0.maximum_depth = 512,
ram_0.numwords_a = 512,
ram_0.operation_mode = "SINGLE_PORT",
ram_0.outdata_aclr_a = "NONE",
ram_0.outdata_reg_a = "CLOCK0",
ram_0.power_up_uninitialized = "FALSE",
ram_0.ram_block_type = "M9K",
ram_0.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
ram_0.widthad_a = 11,
ram_0.widthad_b = 11,
ram_0.width_a = 8,
ram_0.width_b = 8,
ram_0.width_byteena_a = 1,
ram_0.width_byteena_b = 1;

altsyncram ram_1 (
.address_a ({AddressA,2'b00})
, .clock0 (ClockA )
, .data_a (DataInA[15:8] )
, .wren_a (WrA )
, .q_a (QA[15:8] )
, .rden_a (1'b1)
, .rden_b (1'b1)
, .address_b ({AddressB,2'b00})
, .clock1 (1'b1 )
, .data_b (DataInB[15:8] )
, .wren_b (WrB )
, .q_b (QB[15:8] )
, .addressstall_a (1'b0 )
, .addressstall_b (1'b0 )
, .byteena_a (1'b1)
, .byteena_b (1'b1)
, .clocken0 (1'b1 )
, .clocken1 (1'b1 )
, .clocken2 (1'b1)
, .clocken3 (1'b1)
, .eccstatus ()
, .aclr0 ()
, .aclr1 ()
);
defparam
ram_1.clock_enable_input_a = "BYPASS",
ram_1.clock_enable_output_a = "BYPASS",
ram_1.init_file = "inst_ram_data.hex",
ram_1.intended_device_family = "Cyclone III",
ram_1.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
ram_1.lpm_type = "altsyncram",
ram_1.maximum_depth = 512,
ram_1.numwords_a = 512,
ram_1.operation_mode = "SINGLE_PORT",
ram_1.outdata_aclr_a = "NONE",
ram_1.outdata_reg_a = "CLOCK0",
ram_1.power_up_uninitialized = "FALSE",
ram_1.ram_block_type = "M9K",
ram_1.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
ram_1.widthad_a = 11,
ram_1.widthad_b = 11,
ram_1.width_a = 8,
ram_1.width_b = 8,
ram_1.width_byteena_a = 1,
ram_1.width_byteena_b = 1;

altsyncram ram_2 (
.address_a ({AddressA,2'b00})
, .clock0 (ClockA )
, .data_a (DataInA[23:16])
, .wren_a (WrA )
, .q_a (QA[23:16] )
, .rden_a (1'b1)
, .rden_b (1'b1)
, .address_b ({AddressB,2'b00})
, .clock1 (1'b1 )
, .data_b (DataInB[23:16])
, .wren_b (WrB )
, .q_b (QB[23:16] )
, .addressstall_a (1'b0 )
, .addressstall_b (1'b0 )
, .byteena_a (1'b1)
, .byteena_b (1'b1)
, .clocken0 (1'b1 )
, .clocken1 (1'b1 )
, .clocken2 (1'b1)
, .clocken3 (1'b1)
, .eccstatus ()
, .aclr0 ()
, .aclr1 ()
);
defparam
ram_2.clock_enable_input_a = "BYPASS",
ram_2.clock_enable_output_a = "BYPASS",
ram_2.init_file = "inst_ram_data.hex",
ram_2.intended_device_family = "Cyclone III",
ram_2.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
ram_2.lpm_type = "altsyncram",
ram_2.maximum_depth = 512,
ram_2.numwords_a = 512,
ram_2.operation_mode = "SINGLE_PORT",
ram_2.outdata_aclr_a = "NONE",
ram_2.outdata_reg_a = "CLOCK0",
ram_2.power_up_uninitialized = "FALSE",
ram_2.ram_block_type = "M9K",
ram_2.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
ram_2.widthad_a = 11,
ram_2.widthad_b = 11,
ram_2.width_a = 8,
ram_2.width_b = 8,
ram_2.width_byteena_a = 1,
ram_2.width_byteena_b = 1;

altsyncram ram_3 (
.address_a ({AddressA,2'b00})
, .clock0 (ClockA )
, .data_a (DataInA[31:24])
, .wren_a (WrA )
, .q_a (QA[31:24] )
, .rden_a (1'b1)
, .rden_b (1'b1)
, .address_b ({AddressB,2'b00})
, .clock1 (1'b1 )
, .data_b (DataInB[31:24])
, .wren_b (WrB )
, .q_b (QB[31:24] )
, .addressstall_a (1'b0 )
, .addressstall_b (1'b0 )
, .byteena_a (1'b1)
, .byteena_b (1'b1)
, .clocken0 (1'b1 )
, .clocken1 (1'b1 )
, .clocken2 (1'b1)
, .clocken3 (1'b1)
, .eccstatus ()
, .aclr0 ()
, .aclr1 ()
);
defparam
ram_3.clock_enable_input_a = "BYPASS",
ram_3.clock_enable_output_a = "BYPASS",
ram_3.init_file = "inst_ram_data.hex",
ram_3.intended_device_family = "Cyclone III",
ram_3.lpm_hint = "ENABLE_RUNTIME_MOD=NO",
ram_3.lpm_type = "altsyncram",
ram_3.maximum_depth = 512,
ram_3.numwords_a = 512,
ram_3.operation_mode = "SINGLE_PORT",
ram_3.outdata_aclr_a = "NONE",
ram_3.outdata_reg_a = "CLOCK0",
ram_3.power_up_uninitialized = "FALSE",
ram_3.ram_block_type = "M9K",
ram_3.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
ram_3.widthad_a = 11,
ram_3.widthad_b = 11,
ram_3.width_a = 8,
ram_3.width_b = 8,
ram_3.width_byteena_a = 1,
ram_3.width_byteena_b = 1;

endmodule






USB-Blasterドライバ適用


VEEK電源ON > PCにUSBつなぐ > 不明なデバイスになる > デバイスマネージャ
 > 以下を指定し、サブフォルダも検索、にチェックした上で進むと自動的にドライバ入った。
C:\intelFPGA_lite\17.0\quartus\drivers

 ※ 以下のフォルダを指定したら、見つかりません、と言われた。
   どっから持ってきたか不明だが、上記のdriversフォルダを指定して自動検索にしたら成功した。
C:\intelFPGA_lite\17.0\quartus\drivers\usb-blaster\x64
C:\intelFPGA_lite\17.0\quartus\drivers\usb-blaster-ii\x64
C:\intelFPGA_lite\17.0\quartus\drivers\wdrvr\windows64




ProgrammerでsofをVEEKへダウンロード


Quartusでコンパイルが成功したら、.sofが生成されているはず。
Quartus > Tools > Programmer > 左上のHardware Setup
 > USB-Blasterドライバが適用されるとAltera USB-Blasterが見えた。それを選んでclose。
 > これでStartボタンクリックすると、右上のProgressバーが進み、Successfulになった。

 Hardware Setup = Altera USB-Blaster
 Mode       = JTAG
 File        = DE2-115.sof
 接続チェーン図 = TDI -> EP4CE115F29 -> TDO となっている。







MicosystemのBuildエラー

latticemicosystem.exe > C/C++ウィンドウ > プロジェクトを右クリック
 > Build Project

これで以下のエラーが出る。

make all
0 [main] make 4652 find_fast_cwd: WARNING: Couldn't compute FAST_CWD pointer. Please report this problem to
the public mailing list cygwin@cygwin.com
43556 [main] make 7788 child_info_fork::abort: C:\lscc\diamond\3.10_x64\micosystem\cygwin\bin\cygiconv-2.dll: Loaded to different address: parent(0x4D0000) != child(0x600000)
make: vfork: Resource temporarily unavailable
80141 [main] make 6636 child_info_fork::abort: C:\lscc\diamond\3.10_x64\micosystem\cygwin\bin\cygiconv-2.dll: Loaded to different address: parent(0x4D0000) != child(0x20C0000)
make: vfork: Resource temporarily unavailable



調べると、Windows 8.1におけるCygwinの問題らしい。

同じデータを使って、Win 10のPCでBuildしたらエラーは出なかった。Win 8.1の問題と判断し、PC変えて作業しよう。

Windows 10 Pro
LMS_1.0_for_Diamond3.10.exe.zip
3.10.0.111.2_Diamond_x64.zip
uname -a の結果
CYGWIN_NT-10.0 x1 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin

カレンダー
10 | 2018/11 | 12
- - - - 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 30 -
累積訪問者
現在の訪問者
現在の閲覧者数:
最新記事
最新トラックバック
最新コメント
月別アーカイブ
カテゴリ
プロフィール

bobgosso

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

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

この人とブロともになる

QRコード
QRコード