Systemverilog for design 筆記(六)
第一章 有限狀態機建模(FSM,finite state machine)
1.1. 使用枚舉類型建立狀態機模型
l 三過程塊建模風格:三個過程塊分別實現:
a.狀態轉換(always_ff) b.產生下一狀態(always_comb) c.產生狀態輸出值(always_comb)
l 使用枚舉類型表示狀態編碼:通過定義enum類型決定狀態位數;可顯示指定label value
l 使用枚舉類型的反向case語句:對應ont-hot編碼模式,條件選項是狀態編碼的某一位
l 使用unique修飾case語句
l 對於未使用的狀態值(由狀態變量寬度遍歷產生):
n Verilog:使用X作為缺省賦值,case語句中default:state = n’bxxx; SV:用unique case
n 使用專用的綜合full_case附註
l 盡量使用enum list中的label,而不是具體value對枚舉變量賦值
l 對於enum變量的操作:1.直接將int賦值給enum變量是非法的,要在操作後(賦值前)進行強制轉換,將其轉換為枚舉類型。 2.可使用枚舉方法,見3.2.6
1.2. 在FSM模型中使用兩態數據類型
容易出現死鎖。解決方法:1.使用logic顯示聲明enum 2.使用always_comb
1.3. 總結
unique case + logic enum大法好
第二章 層次化設計
2.1. 模塊原型
SV允許用戶為被實例化的模塊指定一個原型。原型的定義使用關鍵詞extern
Extern之後是模塊及端口聲明。 該聲明只在其定義的範圍內可見。
若模塊有extern module聲明,則模塊定義時無需重復端口聲明,可用 .* 替代
Eg.extern module counter #(parameter N = 15)
(output logic
[N:0] cnt,
input wire [N:0] d,
input wire clock,
load,
resetN);
module counter (
.* ); //$unit中已使用原型定義,所以無需重復端口聲明
… //模塊內容
endmodule
2.2. 命名的結束語句
l 命名的模塊結尾 eg. endmodule : <module_name>
l 命名的代碼塊結尾 見6.7,另外還有package...endpackage,
interface...endinterface,
task...endtask,
function...endfunction, and begin...end
2.3. 嵌套(局部)模塊的聲明
Eg. module
ip_core (input clock);
sub1 u1 (...); // 嵌套模塊sub1實例化
module sub1
(...); // 嵌套模塊定義(註意是在ip_core模塊中嵌套定義,而非實例化)
sub2 u2 (); //在nested
module sub1的定義中實例化sub2
...
endmodule: sub1
module sub2; //嵌套模塊定義。Sub2沒有端口,但可看到其父模塊源碼中的標識符
sub3 u3 (...); //在nested module sub2的定義中實例化sub3
endmodule: sub2
module sub3 (...); //嵌套模塊定義
...
endmodule: sub3
endmodule: ip_core
Verilog中的模塊名全部是全局的
SV為解決全局模塊帶來的可能模塊間沖突及安全問題,提出了:
嵌套(局部)模塊:Nested (local) module 在模塊內聲明(local)模塊
允許一個模塊的定義嵌套在另一個模塊的定義中,該模塊在聲明的層次域外不可見
2.4. 簡化的模塊實例網表
Verilog中兩種連接模塊實例的代碼風格:
l 使用端口順序連接模塊實例 eg. dff d1 (out, /*not used*/, in, clock, reset);
l 使用端口名稱連接模塊實例
eg. dff d1 (.q(out), .qb(/*not used*/),//.<端口名>(<線網
.d(in),
.clk(clock), .rst(reset) );// 或變量名>)
SV中有三種端口連接方法:
l .name 端口連接
l .* 端口連接
l 接口(見第九章)
2.4.1. .name端口連接
當port_name = wire_name且寬度相同時,SV中可使用.name的方式連接模塊實例
相當於verilog中的.name(name)
Eg.
prom prom (
.dout(program_data),
.clk, //使用.name端口連接
.address(program_address)
);
2.4.2. .* 端口連接
用於表示模塊實例中所有名稱相同的端口和線網(或變量)是自動連接在一起的。
Eg.
prom prom (
.*, //使用.*端口連接
.dout(program_data),
.address(program_address)
);
2.5. 線網別名化(alias)
SV使用alias表示兩個不同名稱對同一個線網的引用。
Eg. wire clock,clk; alias clk = clock ;//clk和clock指的是同一個邏輯線網,不是賦值語句
Alias支持多重別名化:alias rst = reset = resetN = rstN ;//一個擁有4個別名的邏輯線網
Rule:
l 進行別名化的兩個線網類型及位數必須相同
l 只有線網類型可以別名化,變量不能別名化
(wire, uwire, wand, wor, tri, triand,trior, tri0, tri1, trireg.)
2.6. 在模塊端口間傳遞數值
Verilog對模塊端口的限制:
l 只有線網類型可以用在端口的輸入端
l 只有net , reg , integer ,或文本整數值可以用在模塊輸出端口
l 通過模塊端口傳遞real類型不合法,要先轉換成向量來傳遞
l 模塊端口間傳遞任何維數的非壓縮數組是不合法的
SV中解除了這些限制:
l 任何類型都可以在模塊的input/output端口,包括實數值
l 任何維數的壓縮或非壓縮數組都可以在端口間傳遞
l Struct和union也可以在模塊端口間傳遞
未解除一些限制:
u 變量只能從單個源接收數值
u 端口兩邊的非壓縮類型在結構上完全匹配(對於struct/union要求typedef相同)
(壓縮值作為向量在端口間傳遞)
2.7. 端口引用(ref)(不可綜合)
相對於verilog的input/ouput/inout,SV增加了ref端口。
Ref端口可以在端口間卻傳遞一個對變量的層次化引用,而不是傳遞該變量值。
對端口名稱的任何引用都會直接引用實際的原變量。
通過引用在端口間傳遞變量會生成共享變量,但在硬件行為卻不是如此。
2.8. 增強的端口聲明
SV相對於Verilog簡化了端口說明的步驟:
l SV制定了缺省的端口方向inout。
l 若port list中下一個port定義了類型,但沒有指定方向,那麽默認端口的方向與前一端口一致
l SV增加了兩種可以帶port ,interface和program的層次塊,它們的端口聲明同模塊
l 如果第一個端口沒有指定方向和類型,則其他端口也不能聲明方向和類型
2.9. 參數化類型
通過parameter type聲明參數化的類型
Eg.
module adder #(parameter type ADDERTYPE = shortint) //缺省情況下,參數類型是shortint
(input ADDERTYPE a, b, //可重定義類型
output ADDERTYPE sum, //可重定義類型
output logic carry);
ADDERTYPE temp; // 使用可重定義類型的局部變量
... // 加法器功能
endmodule
module big_chip( ... );
shortint a, b, r1;
int c, d, r2;
int unsigned e, f, r3;
wire carry1, carry2, carry3;
adder i1 (a, b, r1, carry1);//16位無符號加法器
adder #(.ADDERTYPE(int)) i2 (c, d, r2, carry2); //重新定義參數類型,32位有符號加法器
adder #(.ADDERTYPE(int unsigned)) i3 (e, f, r3, carry3); //32位有符號加法器
endmodule
Systemverilog for design 筆記(六)