VerilogのメモリをHEXファイルで初期化したい
メモリ上のデータを $readmemh 関数を利用して初期化できるらしいので試してみる。
こんな感じ。
code:verilog
initial begin
// HEX ファイル pattern.hex で pattern 配列を初期化
$readmemh("pattern.hex", pattern);
end
メモリのデータは HEX 形式で定義する。HEX ファイルの中身はこんな感じ。
// 以降はコメントとなる。
code:pattern.hex
81 // 1000 0001
42 // 0100 0010
24 // 0010 0100
18 // 0001 1000
24 // 0010 0100
42 // 0100 0010
81 // 1000 0001
00 // 0000 0000
パターンをLEDへ表示する回路はこんな感じ。
code:top.sv
// RAM上の8ビットのパターンデータをLEDに出力する。
// 表示パターンは、1秒ごとに切り替わる。
module top(
input clk, // 25MHz のクロック
);
logic 24:0 cnt_next = (cnt < 25000000) ? cnt + 1
: 0;
logic 2:0 idx_next = (cnt == 0) ? idx + 1
: idx;
logic 7:0 led_next = patternidx; initial begin
// HEX ファイル pattern.mem からパターンを読み込む
$readmemh("pattern.mem", pattern);
end
always @(posedge clk) begin
cnt <= cnt_next;
idx <= idx_next;
led <= led_next;
end
endmodule
制約ファイル。
code:ulx3s_v20.lpf
BLOCK RESETPATHS;
BLOCK ASYNCPATHS;
## ULX3S v2.x.x and v3.0.x
# Clock
LOCATE COMP "clk" SITE "G2";
IOBUF PORT "clk" PULLMODE=NONE IO_TYPE=LVCMOS33;
FREQUENCY PORT "clk" 25 MHZ;
## LED
LOCATE COMP "led7" SITE "H3"; LOCATE COMP "led6" SITE "E1"; LOCATE COMP "led5" SITE "E2"; LOCATE COMP "led4" SITE "D1"; LOCATE COMP "led3" SITE "D2"; LOCATE COMP "led2" SITE "C1"; LOCATE COMP "led1" SITE "C2"; LOCATE COMP "led0" SITE "B2"; IOBUF PORT "led0" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led1" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led2" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led3" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led4" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led5" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led6" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; IOBUF PORT "led7" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4; ## Pushbuttons "blinkey", "flash", "power", "gpdi" sheet
LOCATE COMP "btn_up" SITE "R18"; # UP
LOCATE COMP "btn_down" SITE "V1"; # DOWN
IOBUF PORT "btn_up" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF PORT "btn_down" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
Makefile
code:Makefile
all: ulx3s.bit
clean:
rm -rf readmemh-test.json ulx3s_out.config ulx3s.bit
ulx3s.bit: ulx3s_out.config
ecppack ulx3s_out.config ulx3s.bit
ulx3s_out.config: readmemh-test.json
nextpnr-ecp5 --85k --json readmemh-test.json --lpf ulx3s_v20.lpf --textcfg ulx3s_out.config
readmemh-test.json: top.sv
yosys -p "hierarchy -top top" -p "proc; opt" -p "synth_ecp5 -noccu2 -nomux -nodram -json readmemh-test.json" top.sv
prog: ulx3s.bit
fujprog ulx3s.bit
動かしてみる
以下のコマンドで書き込み。
code:sh
make prog
指定したパターン通りに点灯してたので、ちゃんと初期化できてるみたい。
https://gyazo.com/0bd5a2bbe73b2ac1e15a8e87edbc0e64
https://gyazo.com/8878a8fe46a312066971dd95766e9998
https://gyazo.com/25bebc184a24b3aecba870fa0a78cf68
(メモ)メモリの初期化
「ECP5 and ECP5-5G Memory User Guide」の「10. Initializing Memory」
LatticeのIDE上で、ASCIIファイルでメモリを初期化可能
3種類のフォーマット
Binary file
Hex File
Addressed Hex
メモリ初期化ファイルのファイル名は「*.mem」
バイナリファイル(20 * 8)
code:binary file
00100000010000000010000001000000
00000001000000010000000100000001
00000010000000100000001000000010
00000011000000110000001100000011
00000100000001000000010000000100
00000101000001010000010100000101
00000110000001100000011000000110
00000111000001110000011100000111
HEXファイル
code:hex file
A001
0B03
1004
CE06
0007
040A
0017
02A4
Addressed Hex
code:addressed hex
A0 : 03 F3 3E 4F
B2 : 3B 9F
参考
ECP5 and ECP5-5G Memory User Guide
Initialize Memory in Verilog