絶望の証
何も見えない
進捗は出ないけど知見が増えたので SystemVerilogが一ミリもわからない人向け
Queueは論理合成できない
module Test(); byte q[$]; //<--できない initial begin q.push_back(12); //<--できない end endmodule
SystemVerilogのQueueはQueueというより双方向Queueで、C++の感覚で使えるので便利だと思ってわくわくしてたけど現行のQuartus Prime 17.0でも論理合成できない。
同じくわくわくしてた連想配列も論理合成できない
//KeyがbyteでValueがintの連想配列 int dic[byte]; // <--できない
structとenumは論理合成できる
でもstructとenumは論理合成できる。enumは値に名前を付けれて便利 enumはデータ型を指定できる。以下はbyteを指定した例
typedef enum byte {TINO=0,KOKOA=1,RIZE=2} RABBITHOUSE;
enum
のあとを省略すると32bit?(たぶんint
)になる。
さらに代入を省略すると0からの連番になる、先頭に値を
指定するとそこからの連番になる
//zero=0から始まる連番が順番に割り当てになる typedef enum {zero,one,two,three,four} num;
SystemVerilogのenumはスコープがない・・・というか全部グローバルに宣言される感じ
なので使うときは名前をそのまま書けば使える
typedef enum byte {TINO=3,KOKOA,RIZE} RABITHOUSE; initial begin $display("Data : ",KOKOA); //<-- Data : 4って出力される end
名前が一緒だったら既にあるっておこられる
typedef enum {TINO} TINOCHAN; typedef enum {TINO,KOKOA,RIZE} RABBITHOUSE; //<--既にTINOが定義されてるので死ぬ
structも使える
typedef struct packed { byte x; byte y; } Vector2; Vector2 pos; //<--宣言するときはこう byte tmp=pos.x; //<--xを読み出したいときはこう
初期化?もC++みたいにかける。
Vector2 pos={8'h01,8'h02}; //<-- xに1 yに2
pragma once
インクルードするときC言語みたいに多重定義すると死ぬ
これを書いてる間にSystemVerilogにはC++みたいにpragma once
を指定すれば1度だけインクルードされて多重定義を防げる
//test.sv `pragma once module test(); dark zone endmodule //second.sv `include "test.sv" modeule second(); second dark zone endmodule //top.sv `include "test.sv" `include "second.sv" module top(); 天衣無縫 endmodule
test.sv
にpragma once
がないとsecond.sv
の解析中に多重定義で死亡する
これを見つけるまではifdef-else define -endif
でやってた。バカス
2017年11月15日追記
なんかやっぱりpragma once
はダメだったのでこれは無かったことに
僕が見たのは幻覚か
一回だけいんくるするならやっぱりifdefを使う
`ifdef REG_ONCE `else `define REG_ONCE module register(); endmodule `endif
これでめでたく解決!(長くてめんどい)
automatic
SystemVerilogは急に変数を宣言できない。回路はstaticだから
変数宣言するならModuleの先頭かinitialブロックの中でしかできない。Moduleの先頭で宣言するとstaticな変数になる。アクセスはModule内ならどこからでもできる
しかしコードを書いてると急に変数を宣言したくなるでしょ
そういう時はautomatic
キーワードを使えば動的な変数が定義できる
module test(); byte abc;//<--これはstatic test内ならどこからでもアクセスできる initial begin byte k; //<--initialの中ではOKでもスコープはこのブロックの中だけ end function void abc(); byte abc=0; //<--これはダメ automatic byte edf=0; //<--これはOK edf=123; //なんか処理かく automatic byte cc=0; //<--これはダメ、automaticをつかって宣言しても結局スコープの先頭でしかできない endfunction //automaticを使わないといけないのはtaskやalwaysも endmodule
変数の種類
japan.xilinx.comhttps://japan.xilinx.com/support/answers/51327.html
ここが詳しい
書いててたまに不便だと思うのがbyte
とかが符号付きなところ
二進数世界なのに符号付とかいみわかんなくない?でもプログラム書くとき的には普通じゃないってなってて板挟み
符号なしの多bit幅型を使うときはlogic[15:0]
とかって書けば16bitの型が書けるけどこれはいちいち面倒なのでよく使うのはtypedef
すればいいと思う
//16bit型 typedef logic[15:0] d_byte; //ちなみにunsignedを付ければ符号なしにできる typedef byte unsigned ubyte;
typedef
はmoduleの外とかでもできるから全体的によく使うやつとかは別ファイルにまとめて使うときにincludeすると便利かもね。
interface
よく使うポートとかをまとめられる神機能。しかも論理合成できる よくわかんないだろうから例
interface clk_rst; bit clk; bit rst; endinterface module top(clk_rst c); // ↑こんな風にclkとrstをまとめられる always @(posedge c.clk) begin //<--アクセスはstructを同じようにやる end endmodule
fork-joinブロック
taskをforkできる
sites.google.com
ここが詳しい
event
やforever
と組み合わせるとalways
の代わりが作れるけどこのfork-join
ブロックは論理合成できない残念!
これが役に立つと個人的に思うのはテストベンチでクロックを無限に出したいとき
module TB(); bit clk,rst,endofrun; Test test(.*); task clkgen(); while(!endofrun)begin #50 clk<=0; #50 clk<=1; end endtask initial begin fork begin clkgen(); join_none //~~~なんか処理 end endmodule
このテクニックはネットのどこかで見たから使ってる。どこだったか忘れたので出典はかけない・・・ごめんなさい
まだ何個かある気がするけど思い出すも書くのも疲れたのでここまで
気が向いたらまた書くかもしれないし、マサカリもお願いしたい