本文源自微信公眾號 :數字晶元實驗室

1、連續賦值和過程賦值之間有什麼區別?

2、initial和always中的賦值有什麼區別?initial和always中的賦值都是過程賦值。

3、阻塞和非阻塞賦值之間有什麼區別?阻塞和非阻塞賦值都是過程賦值。

4、如何使用連續賦值建模雙向nets?

assign語句構成一個連續賦值。 RHS變化立即影響LHS。 然而,LHS的任何變化都不會影響RHS。

例如,在以下聲明,rhs的更改將更新到lhs,但反之不會。

System Verilog引入了一個關鍵字alias,能定義雙向nets。

例如,在以下代碼中,rhs的任何變化都會更新到lhs,反之亦然。

如果上述alias換成assign,則輸出如下:

lhs = 2 , rhs = 2lhs = c , rhs = z 然而,由於定義了alias,輸出如下:lhs = 2 , rhs = 2lhs = c, rhs = c在上面的示例中,對net任何一側的更改都會更新到另一側。

5、task和function之間有什麼區別?

Verilog中的task和function都可以實現常用功能,有助於代碼的清晰和可維護,避免在不同位置複製大量代碼。 本質上,task和function都提供了在模塊中不同位置重用相同代碼段的「子程序」機制。

但是,task和function在以下方面有所不同:

6、靜態task和動態task有何不同?

動態task在關鍵字task和名稱之間有automatic關鍵字。 動態task在每個task調用期間,自動分配變數內存空間,即每次調用都不會覆蓋這些值。沒有automatic關鍵字,變數是靜態分配的,這意味著這些變數在不同的task調用之間共享,因此可以被覆蓋。

以下示例說明了關鍵字automatic的效果。 這是一個不可綜合的代碼。

在上面的示例中,my_value是task中的局部變數。 每當調用此task時,輸入in_value在5個模擬時間單位之後賦值給局部變數。 在initial begin中,有一個fork-join,它啟動兩個並行進程,分別在模擬時間單位#1和#2之後開始。 第1個進程賦值2給my_value,第2個進程賦值3給my_value。 假設沒有automatic關鍵字,使用上面的代碼運行模擬,會輸出以下內容:

沒有automatic關鍵字的事件序列如下:

1. 從模擬時間0開始啟動fork-join兩個進程。

2.第一個進程在#1之後調用modify_value,並賦值局部變數my_value為2. 此時 t = 1。3.第二個進程在#2之後調用modify_value,並賦值局部變數my_value為3. 此時t = 2。請注意現在賦值給局部變數my_value的值被3覆蓋。4.再經過4個時間單位,即在t = 1 + 5 = 6時,第1個task調用$display。由於最新值現在是「3」, my_value顯示「3」,而不是 「2」。類似地,對於第二個過程,即t =2 + 5 = 7,第2個task調用$display。由於最新值仍為「3」,因此此處my_value顯示「3」。現在,在task和task名稱之間使用關鍵字automatic,模擬輸出一下內容:

按照上述相同的步驟,這次,由於存在關鍵字automatic,變數不會被其他進程覆蓋。

下表總結了動態task和靜態task之間的差異:

7、如何覆蓋automatic task中的變數?

默認情況下,module中的所有變數都是靜態的。 但是, task/function中的變數都可以定義為static或automatic。

以下示例組合了static或者automatic的task/function和其變數: 1、task/function和其變數都沒有定義為automatic 在Verilog-1995中,task/function和其變數都是隱式靜態的。 變數僅分配一次內存,多次調用將覆蓋其變數。 2、static task/function

System Verilog引入了關鍵字static。 當task/function被明確定義為static,它的變數只分配一次內存,並且多次調用將覆蓋其變數。 、

3、automatic task/function從Verilog-2001開始,當task/function定義為automatic,其變數也是隱式automatic的。 因此,在多次調用task/function時,變數每次都會分配內存並不會覆蓋。 4、static task/function和automatic變數SystemVerilog還允許在靜態task/function中使用automatic變數。 那些沒有automatic定義的變數會保持隱含的靜態。 這在變數需要在task/function調用之前初始化,並且自動分配內存的情況下很有用5、automatic task/function和static變數SystemVerilog還允許automatic task/function中使用靜態變數。沒有static聲明的那些變數將保留隱式automatic。 這在靜態變數需要為每次調用更新變數值的場景中很有用

8、如何沒有返回值地調用function?在Verilog 2001之前,任何function調用都必須返回一個值,調用function的代碼必須接收返回值。 例如,以下是語法錯誤:

上面例子中的一行是語法錯誤,因為調用了my_funct,卻沒有返回值。 只有task可以在沒有返回值的情況下調用。

SystemVerilog引入了void來支持沒有返回值的function調用。 這使得function調用類似於task調用。以下示例說明void的function調用:

上面的例子顯示了結果:

int_result = 7同時:1、function不能使用#,@等結構2、function不能使用非阻塞賦值。

3、function返回值默認為1比特位寬

9、如何在例化時修改模塊的parameter值?

如果Verilog模塊使用parameter,有兩種方法可以修改它值。1)按順序列表: 在此方法中,parameters的修改順序和模塊中聲明它們的順序一樣。 例如,parameter_list模塊包含兩個參數,即width和depth,已在模塊中分配默認值。 並且在example_parameter_list模塊中實例化,並且這些parameter在不同的實例化中被不同的值覆蓋。

使用上述方法的限制是:

parameter修改值必須被按順序修改覆蓋。 例如,在上面代碼中,U2實例化parameter_list,不能跳過width 和depth直接修改num_buses 我們有兩種方法克服這種限制:1、 在聲明模塊內的parameter時,將後面例化時需要改變的parameter聲明在不需要改變的parameter之前。 例如,在上面的代碼中,U0和U1實例化了parameter_list .num_buses不需要更改,所以最後聲明,分配給它的是默認值。2、 在模塊實例化時,為所有的parameter分配值,包括不需要修改的parameter。 在U2實例化中,雖然只有num_buses參數需要改變,但width and depth仍然需要分配模塊中定義的相同的默認值。2)按名稱指定: 這是Verilog-2001開始提供的一項新功能,可以通過顯式指定parameter來更好地修改模塊的parameter。 這樣,parameter值就鏈接到它的名字,而不是聲明時的位置順序。使用與上面相同的模塊parameter_list,下面的示例顯示了按名稱指定的相同的parameter修改覆蓋。

請注意,顯式地按parameter名稱指定修改方式,括弧中的值是修改的值。 在在U2實例化中,只需指定depth即可,無需為width指定任何修改值。

3)使用 defparam:在此方法中,模塊中的parameter根據其層次結構名稱訪問。 在下面的示例中,低層次模塊parameter_list在example_defparam模塊中實例化。 但是width和depth的值使用defparam修改。

以下總結了使用defparam方法的優點:

1、修改parameter值是不需要遵循parameter聲明順序2、可以修改特定parameter,而不是重新指定所有parameters3、通過對defparam進行分組,可以幫助進行代碼維護

10、如果阻止模塊例化時parameters不被改變

如果需要阻止模塊中的特定parameters被改變,應該使用localparam,而不是parameter。 localparam在Verilog-2001中引入。在以下示例中,localparam用於聲明num_bits,因此嘗試改變它會給出Error。

請注意,由於width和depth是使用parameter指定的,它們可以在實例化時被改變。

通常,localparam定義本地化標識符,其值來自常規parameters。

11、使用`define和parameter有什麼區別?

`define和parameter都可以在設計中用來指定常量。 例如:

12、什麼是派生parameters?

當一個或多個parameters用於定義另一個parameters時,則結果是派生parameters。 派生parameters可以是parameter或localparam。 在以下示例中,有兩個parameter,width和 depth,,用於定義第三個parameter,num_bits。在這種情況下,num_bits的值為32。

使用派生parameters可以增強RTL代碼的可重用性。

13、層次化設計當中連接Ports的方法有哪些?各自的優缺點是什麼?1)按順序連接

在此方法中,模塊實例化中的埠順序應與模塊聲明中的埠順序相同。 例如,在下面的代碼中,upper模塊實例化lower模塊,並且埠是隱式連接的,也就是說,按順序連接的。

2)按名稱連接

在此方法中,可以通過port名稱,在實例化模塊時顯式地完成port之間的連接。如下所示,按名稱連接連接進行連接port。

按名稱連接提高了port連接的可讀性, 和port聲明的順序不再相關,因為它們是顯示連接的。

請注意,兩種類型的模塊port連接不能混合,也就是說,下面示例的連接方式不正確:

3)按Interface連接

SystemVerilog引入了一個interface結構,將一束nets和variables封裝到一個組中。使用Interface,有助於創造可維護的代碼。 對Interface定義的更改會影響所有實例化interface的模塊。 下面是使用Interface結構的示例:

在上面的例子中,all_ins是實例化的Interface,指定in1到in3埠的ports連接。

喜歡請別放棄


推薦閱讀:
相关文章