試著把最基礎的部份引入正在寫的 code 裡面
並且整理了一些使用心得
interface MemoryInterface();
parameter DAT_SIZ = 8;
parameter ADR_SIZ = 4;
logic [DAT_SIZ-1:0] addr;
logic [ADR_SIZ-1:0] data;
logic en;
modport RI(input addr, output data, input en);
modport WI(input addr, input data, input en);
modport RO(output addr, input data, output en);
modport WO(output addr, output data, output en);
endinterface
這東西看起來超棒的
例如說想要一個記憶體的界面可以如上這樣寫
我們想使用 SRAM 只要這樣(先假設只有讀取功能)
module SRAM(input clk, MemoryInterface.RI mif);
// blahblah
endmodule
module Top();
MemoryInterface mif;
SRAM sram(clk, mif);
initial mif.addr = 'x;
endmodule
Code 瞬間少了一堆,超棒的
然而 interface 遇到 parameter 的時候很微妙這東西有點像具有 C++ 的型別推導功能
但是只有自動模式
個人覺得這非常微妙,舉例如下
例如我想要 2 port(1R 1W) 的 SRAM 作法如下
module SRAM(input clk, MemoryInterface.RI mif1, MemoryInterface.WI mif2);
// blahblah
endmodule
嗯,我們要怎麼知道兩個進來的 port size 一樣?這個模式下面沒辦法,因為只能根據外面怎麼叫來推導兩個的 interface 的 parameter
那這樣應該行了吧
module SRAM(clk, mif1, mif2);
parameter D = 8;
parameter A = 4;
input clk;
MemoryInterface#(D,A).RI mif1;
MemoryInterface#(D,A).WI mif2;
endmodule
Sounds great!不過根據我查了兩三天的結果
沒有這樣的語法
也就是說只有上面的版本可以用
在這個情形下,我們可以通過存取 interface 的 parameter 來取得必須的參數:
module SRAM(input clk, MemoryInterface.RI mif1, MemoryInterface.WI mif2);
localparam A = mif1.ADR_SIZ;
localparam D = mif1.DAT_SIZ;
logic [D-1:0] blahblah;
endmodule
但是還是不能保證兩個進來的 port size 一樣從結論上來說
用了 interface 的單一個 module 不能主動決定任何的 parameter
這產生了許多問題:
- 用 nlint 檢查單一 module 的時候很不方便,因為上層 module 輸入大小後才能確定 intreface 的形狀
- 我們不能確定傳進來的 interface 長什麼樣子
但是仔細想想
interface 的功能用 define 來作好像也很容易達成類似的效果
code 的複雜度也可以接受
interface 的功能用 define 來作好像也很容易達成類似的效果
code 的複雜度也可以接受
`define MemIf_Logic(A,D,name)\
logic [A-1:0] name``_addr;\
logic [D-1:0] name``_data;\
logic name``_en
`define MemIf_Name(A,D,name)\
name``_addr,\
name``_data,\
name``_en
`define MemIf_RI(A,D,name)\
input [A-1:0] name``_addr;\
input [D-1:0] name``_data;\
output name``_en
`define MemIf_Connect(port_name,id_name)\
port_name``_addr(id_name``_addr),\
.port_name``_data(id_name``_data),\
.port_name``_en(id_name``_en)
...
兩個撇號是把 id 串起來的意思,跟 C 裡面的井號功能一樣可以看到 define 的部份複雜了很多
不過使用上跟 interface 接近,而且避開了所有上述的問題
並且使用這種 workaround 的支援更好(Quartus 16 沒有支援 modport)
module SRAM(clk, `MemIf_Name(mif_input));
parameter A = 4;
parameter D = 8;
input clk;
`MemIf_RI(A,D,mif_input);
endmodule
module Top();
`MemIf_Logic mif_yaya;
SRAM sram(.clk(clk), `MemIf_Connect(mif_input,mif_yaya));
initial mif_addr = 'x;
endmodule
不過 Verilog 的 define 好像不能加空格像這樣似乎是錯誤的
`define MemIf_Connect (port_name,id_name)
Hi 看到你用define來達到interface的功能,覺得收穫蠻大的,謝謝你的分享
回覆刪除不過最後一段instantiate的範例寫法似乎有錯,下面是我推測你的意圖改寫,並加入parameterized的寫法
``` verilog
module Top();
localparam A = 4, D =8;
`MemIf_Logic(A, D, mif);
SRAM#(.A(A), .D(D)) sram(.clk(clk), .`MemIf_Connect(mif_input,mif));
initial mif_addr = 'x;
endmodule
module SRAM #(parameter A = 3, D = 9)(clk, `MemIF_Name(A, D, mif_input));
input clk;
`MemIf_RI(A,D,mif_input);
endmodule
```
PS. 我只有試過ncverilog 及verdi 兩者檢查語法
刪除嗯嗯,應該是當時複製的時候改錯了
刪除已改正