小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Verilog非阻塞賦值的仿真/綜合問題(二)

 cana_xzy 2010-06-12
From:http://blog./space.php?uid=121854&do=blog&id=1432

8.0
流水線建模

圖二示意了一個簡單的時序(sequential流水線寄存器。

                               

 

從例5到例8列舉了一個工程師可能選用的4種使用阻塞賦值為它建模的方案。

 

module pipeb1 (q3, d, clk);

output [7:0] q3;

input [7:0] d;                                      

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) begin

q1 = d;

q2 = q1;

q3 = q2;

end

endmodule

Example 5 - Bad blocking-assignment sequential coding style #1

                                                                      

 

(外注:綜合報告:WARNING: Signal <q1> is assigned but never used.

WARNING:Signal <q2> is assigned but never used.

在例5里面,接連的“阻塞賦值”命令將使得輸入D連續(xù)地覆蓋所有寄存器輸出(在下一個posedge clk到來時)。即在每一個clk邊沿,輸入值被無延遲地傳到q3的輸出。這很明顯并沒有建立一個流水線而只是為一個寄存器建模------實(shí)際綜合結(jié)果將是上面的圖3

 

module pipeb2 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

 

always @(posedge clk) begin  //注意次序的更改!

q3 = q2;               

q2 = q1;               

q1 = d;                

end

endmodule

Example 6 - Bad blocking-assignment sequential coding style #2 - but it works!

上面的pipeb2里面,阻塞賦值被仔細(xì)地安排了次序以使得行為仿真正確。這種建模同樣也可以得到正確的綜合結(jié)果。(外注:Found 3-bit shift register for signal <q3>.

    Summary: inferred   8 Shift register(s).  

 

在下面的例3里,“阻塞賦值”被安排在不同的always塊里面。這樣Verilog標(biāo)準(zhǔn)允許以任意的次序 來仿真執(zhí)行3always-------這也許會使得該流水線仿真結(jié)果產(chǎn)生錯誤,因?yàn)檫@產(chǎn)生了Verilog競爭條件。由不同的always塊執(zhí)行順序會產(chǎn)生不同的結(jié)果。盡管這樣,它的綜合結(jié)果將是正確的!   這就意味著綜合前仿真和綜合后仿真不匹配。Pipeb4或者其它的類似always塊同樣也許會產(chǎn)生仿真與綜合不匹配的結(jié)果------綜合結(jié)果是對的,但是仿真結(jié)果也許不正確。(外注:pipeb4只是又顛倒了一下次序,對實(shí)際仿真次序卻不產(chǎn)生決定作用.

 

module pipeb3 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) q1=d;

always @(posedge clk) q2=q1;

always @(posedge clk) q3=q2;

endmodule

Example 7 - Bad blocking-assignment sequential coding style #3

 

module pipeb4 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) q2=q1;

always @(posedge clk) q3=q2;

always @(posedge clk) q1=d;

endmodule

Example 8 - Bad blocking-assignment sequential coding style #4

 

假如每一個上面的例子都改用“非阻塞賦值”那么將會都能得到正確的仿真結(jié)果,并綜合出想要的流水線邏輯。

 

module pipen1 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) begin

q1 <= d;

q2 <= q1;

q3 <= q2;

end

endmodule

Example 9 - Good nonblocking-assignment sequential coding style #1

 

module pipen2 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) begin

q3 <= q2;

q2 <= q1;

q1 <= d;

end

endmodule

Example 10 - Good nonblocking-assignment sequential coding style #2

 

module pipen3 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) q1<=d;

always @(posedge clk) q2<=q1;

always @(posedge clk) q3<=q2;

endmodule

Example 11 - Good nonblocking-assignment sequential coding style #3

 

module pipen4 (q3, d, clk);

output [7:0] q3;

input [7:0] d;

input clk;

reg [7:0] q3, q2, q1;

always @(posedge clk) q2<=q1;

always @(posedge clk) q3<=q2;

always @(posedge clk) q1<=d;

endmodule

Example 12 - Good nonblocking-assignment sequential coding style #4

 

從上面的流水線編碼風(fēng)格例子可以看出:

 僅一個“阻塞賦值”的描述可以保證仿真正確。

 三個“阻塞賦值”的描述可以得到正確綜合結(jié)果。

 四個“非阻塞賦值”描述都可以保證仿真結(jié)果正確。

 四個“非阻塞賦值”描述都可以得到正確綜合結(jié)果。(原文這一條是“阻塞賦值”大概是有誤?)

雖然,如果限制在一個always塊里面,并小心地組織好一個always塊里面阻塞賦值的次序(外注:一個always塊里面的幾個“阻塞賦值”是按照陳述的次序串行仿真執(zhí)行的,綜合執(zhí)行次序也是?)同樣可能會正確地為流水線建模;但是另一方面,我們可以很容易地使用“非阻塞賦值”來為上面的流水線建模------它們既可以正確仿真也可以正確綜合。

 

9.0 阻塞賦值 & 簡單例子

 

有許多將VerilogVerilog綜合的書,它們舉了很多成功地利用“阻塞賦值”為一些簡單的時序電路建模的小例子。例13是一個在大多數(shù)Verilog書本里用來為一個觸發(fā)器(flip-flop)建模的例子(這是簡單而有缺陷的阻塞賦值建模,但是它確實(shí)可以工作):

 

module dffb (q, d, clk, rst);

output q;

input d, clk, rst;

reg q;

always @(posedge clk)

if (rst) q = 1'b0;

else q = d;

endmodule

Example 13 - Simple flawed blocking-assignment D-flipflop model - but it works!

 

如果工程師們想把所有的模塊(module)都集中到一個always里面描述,“阻塞賦值”可以用來正確地為所需要的邏輯建模、仿真和綜合。但是不幸的是這個原因?qū)е铝讼矚g在其它情況下也使用“阻塞賦值”的習(xí)慣,并且更復(fù)雜的時序always塊將會產(chǎn)生競爭條件------在前面已經(jīng)詳細(xì)闡述過。

 

module dffx (q, d, clk, rst);

output q;

input d, clk, rst;

reg q;

always @(posedge clk)

if (rst) q <= 1'b0;

else q <= d;

endmodule

Example 14 - Preferred D-flipflop coding style with nonblocking assignments

 

應(yīng)該努力養(yǎng)成使用“非阻塞賦值”為 所有的 時序邏輯建模的習(xí)慣------象上面的例14一樣------即使是為了對付任何一個簡單的模塊。

 

下面考慮一下一個稍微復(fù)雜的時序邏輯,一個線性反饋移位寄存器(Linear Feedback shift-Register)或稱之為LFSR。

 

10.0 為時序反饋建模 Sequential feedback modeling

 

一個LFSR是一種帶反饋環(huán)路(feedback loop)的時序邏輯。反饋環(huán)路(feedback loop)為工程師們帶來了一個難題使得他們試圖使用細(xì)心組織次序的“阻塞賦值”來為它正確建模,如下面的例子:

 

 

module lfsrb1 (q3, clk, pre_n);

output q3;

input clk, pre_n;

reg q3, q2, q1;

wire n1;

assign n1 = q1 ^ q3;

always @(posedge clk or negedge pre_n)

if (!pre_n) begin

q3 = 1'b1;

q2 = 1'b1;

q1 = 1'b1;

end

else begin

q3 = q2;

q2 = n1;

q1 = q3;

end

endmodule

Example 15 - Non-functional LFSR with blocking assignments(外注:綜合報告―――>

Register <q1> equivalent to <q3> has been removed

    Found 1-bit register for signal <q3>.

    Found 1-bit xor2 for signal <n1>.

Found 1-bit register for signal <q2>.

Summary:

inferred   2 D-type flip-flop(s).

沒有辦法通過調(diào)整描述次序的方法來正確建模除非引入一個臨時的變量(

外注:例如引入“wire n2――>

module xxxxx (q3, clk, pre_n);

output q3;

input clk, pre_n;

reg q3, q2, q1;

wire n1,n2;

assign n1 = q1 ^ q3;

assign n2 = q3;

always @(posedge clk or negedge pre_n)

if (!pre_n) begin

q3 = 1'b1;

q2 = 1'b1;

q1 = 1'b1;

end

else begin

q3 = q2;

q2 = n1;

q1 = n2;

end

endmodule

 

這樣可以得到正確的綜合結(jié)果:

    Found 1-bit register for signal <q3>.

    Found 1-bit xor2 for signal <n1>.

    Found 1-bit register for signal <q1>.

    Found 1-bit register for signal <q2>.

    Summary:

  inferred   3 D-type flip-flop(s).)。

可以通過把所有賦值弄到一個等式的方式(one-line equations)來避免使用臨時變量,例如下面的例16所示。但是現(xiàn)在編碼顯得更難于理解尤其當(dāng)涉及的表達(dá)式更大更長時,編寫代碼和調(diào)試都變得比較困難,因此不鼓勵使用這種風(fēng)格。

 

module lfsrb2 (q3, clk, pre_n);

output q3;

input clk, pre_n;

reg q3, q2, q1;

always @(posedge clk or negedge pre_n)

if (!pre_n) {q3,q2,q1} = 3'b111;

else {q3,q2,q1} = {q2,(q1^q3),q3};

endmodule

Example 16 - Functional but cryptic LFSR with blocking assignments

 

 

 如果把例15和例16的阻塞賦值(blocking assignment)都替換為非阻塞賦值(nonblocking assignment),如下面例1718所示,那么所有的仿真都將如我們對一個LFSR所期望的那樣。

module lfsrn1 (q3, clk, pre_n);

output q3;

input clk, pre_n;

reg q3, q2, q1;

wire n1;

assign n1 = q1 ^ q3;

always @(posedge clk or negedge pre_n)

if (!pre_n) begin

q3 <= 1'b1;

q2 <= 1'b1;

q1 <= 1'b1;

end

else begin

q3 <= q2;

q2 <= n1;

q1 <= q3;

end

endmodule

Example 17 - Functional LFSR with nonblocking assignments

 

module lfsrn2 (q3, clk, pre_n);

output q3;

input clk, pre_n;

reg q3, q2, q1;

always @(posedge clk or negedge pre_n)

if (!pre_n) {q3,q2,q1} <= 3'b111;

else {q3,q2,q1} <= {q2,(q1^q3),q3};

endmodule

Example 18 - Functional but cryptic LFSR with nonblocking assignments

      

                 根據(jù)8.0段例子pipeline10.0段例子LFSR,我們推薦對所有時序邏輯建模時使用非阻塞賦值(nonblocking assignment)。相似的分析也將顯示出對latch建模時使用非阻塞賦值(nonblocking assignment)是最安全的。

 

1: 當(dāng)為時序邏輯建模,使用“非阻塞賦值”。

2: 當(dāng)為鎖存器(latch)建模,使用“非阻塞賦值”。

 

11.0  組合邏輯―使用阻塞賦值(blocking assignment

 

Verilog可以有很多種方法為組合邏輯建模,但是當(dāng)使用always塊來為組合邏輯建模時,應(yīng)該使用阻塞賦值(blocking assignment)。

 

如果在某個always塊里面只有一個賦值(表達(dá)),那么使用阻塞或者非阻塞賦值都可以正確工作。但是如果您對養(yǎng)成好的編碼習(xí)慣有興趣的話,還是要“總是用阻塞賦值對組合邏輯建模”。

 

一些設(shè)計(jì)師建議非阻塞賦值不應(yīng)該只為編寫時序邏輯,它也可以用來編寫組合邏輯。當(dāng)然對于簡單的組合邏輯always塊這是可以的,但是對于在一個always塊里面含有多個賦值陳述,例如例19含有and-or的陳述,使用了不含延遲(delay)的非阻塞賦值會造成仿真不正確,或者要使仿真正確您需要另外的添加敏感事件列表(sensitivity list entries),和“多登入路徑”multiple passes)來貫穿always 塊以使得仿真正確。接下來的問題是從仿真需要多長時間來看,這是低效率的(外注:即降低仿真的performance)。

 

19y輸出建立在3個依次執(zhí)行的陳述上(外注:tmp1 <= a & b;   tmp2 <= c & d;   y <= tmp1 | tmp2;。由于非阻塞賦值的LHS變量值更新是在對RHS表達(dá)式估值之后,所以tmp1tmp2的值仍然是該always塊上一個登入口的值而不是在這一個仿真時間步(simulation time step)結(jié)束時被更新的值。因此y的值將受舊的tmp1tmp2影響,而不是這次掃描過的always塊內(nèi)被更新的值。

 

module ao4 (y, a, b, c, d);

output y;

input a, b, c, d;

reg y, tmp1, tmp2;

always @(a or b or c or d) begin

tmp1 <= a & b;

tmp2 <= c & d;

y <= tmp1 | tmp2;

end

endmodule

Example 19 - Bad combinational logic coding style using nonblocking assignments

 

20與例19是一樣的,不同之處在于tmp1tmp2被添加到事件列表中去了。如第7段(section 7.0)中所述,在“非阻塞賦值更新事件隊(duì)列”中當(dāng)非阻塞賦值更新LHS變量時,always塊將會“自觸發(fā)”并使用最新的tmp1tmp2來更新y輸出?,F(xiàn)在y輸出值正確了因?yàn)樵黾邮褂昧藘蓷l“登入路徑”(two passes)貫穿整個always塊。使用更多的“登入路徑”來貫穿always塊等于降低仿真器的性能,因此如果可以有合理的一些代碼變化可以取代這種用法的話,就盡量避免這種用法。

 

module ao5 (y, a, b, c, d);

output y;

input a, b, c, d;

reg y, tmp1, tmp2;

always @(a or b or c or d or tmp1 or tmp2) begin

tmp1 <= a & b;

tmp2 <= c & d;

y <= tmp1 | tmp2;

end

endmodule

Example 20 - Inefficient multi-pass combinational logic coding style with nonblocking assignments

 

發(fā)展一個好的習(xí)慣可以避免使用“多登入路徑”(multiple passes)貫穿always塊,即使用阻塞賦值為組合邏輯建模。

 

module ao2 (y, a, b, c, d);

output y;

input a, b, c, d;

reg y, tmp1, tmp2;

always @(a or b or c or d) begin

tmp1 = a & b;

tmp2 = c & d;

y = tmp1 | tmp2;

end

endmodule

Example 21 - Efficient combinational logic coding style using blocking assignments

 

21與例19一樣,不同之處只在于用阻塞賦值替代了非阻塞賦值。這保證了在一個“登入路徑”貫穿alwaysy輸出的正確(guarantee that the y-output assumes the correct value after only one pass through the always block?)。因此有下面的編碼方針:

 

 3 當(dāng)用always塊為組合邏輯建模,使用“阻塞賦值

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多