2016-10-06 68 views
0

這是我第一次使用verilog hdl進行編程,並且無法弄清楚我的代碼出了什麼問題。我需要在行爲代碼中設計一個簡單的ALU。用於ALU的Verilog HDL行爲編碼調用模塊

到目前爲止,我已經創建了一個減法器和加法器模塊(我需要添加更多的模塊,但是我希望在添加其他模塊之前讓這些模塊在ALU模塊中工作)。

我有單獨的.V文件以下模塊在同一個項目(很肯定這是一種行爲?):

module adder3bit(sum, co, a, b); 
parameter n = 2; 
output reg [n:0] sum; 
output reg co; 
input [n:0] a; 
input [n:0] b; 

always @(a, b) 
{co, sum} = a + b; 

endmodule 


module subtract3bit(diff, bo, a, b); 
parameter n = 2; 
output reg [n:0] diff; 
output reg bo; 
input [n:0] a; 
input [n:0] b; 

always @(a, b) 
{bo, diff} = a - b; 

endmodule 

我測試過這些,看到他們的工作。

現在我想給他們打電話的主要ALU模塊:

module alu(out, overflow, a, b,sel); 
input [2:0] a, b; 
input sel; 
output [2:0] out; 
output overflow; 
always @(a,b,sel) 
begin 
if(sel=='b0) 
    adder3bit A1(out,overflow,a,b); 
if(sel=='b1) 
    subtract3bit S1(out, overflow, a, b); 
end 
endmodule 

我的語法可能是錯誤的,但它顯示的錯誤。我對verilog很不熟悉。我覺得我第一次感受到學習C.幫助將不勝感激。

我知道它正在調用模塊,但我認爲這與if語句有關。

謝謝我希望能學到新的東西!

回答

2

的主要問題是,你要調用的模塊。模塊不是你不能稱之爲的功能或任務。你可以並且應該對模塊做的事是在另一個模塊(在這種情況下是ALU模塊)中實例化它。模塊不能在程序塊內部實例化(e.x.總是在你的代碼中)。加法器和減法器在每次輸入變化時都會產生新的結果,因此您只需要正確驅動該模塊的輸入並讀取其輸出。

我建議你聲明模塊的端口更可讀的方式:

module adder3bit #(
    parameter N = 2 
) ( 
    output reg [N:0] sum, 
    output reg co, 
    input [N:0] a, 
    input [N:0] b 
); 
    always @(a, b) 
     {co, sum} = a + b; 

endmodule 

在ALU可以實例adder3bit這樣的:

module alu (
    input [2:0] a, 
    input [2:0] b, 
    input sel, 
    output [2:0] out, 
    output overflow 
) 
    localparam SIZE = 3; 
    wire [SIZE - 1 : 0] diff; 
    wire [SIZE - 1 : 0] sum; 
    wire co; 
    wire bo; 

    adder3bit #( 
     .N(SIZE) 
    ) adder (
     .a(a), 
     .b(b), 
     .sum(sum), 
     .co(co) 
    ); 

    subtract3bit #( 
     .N(SIZE) 
    ) subtractor (
     .a(a), 
     .b(b), 
     .diff(diff), 
     .bo(bo) 
    ); 

    always @(*) 
    begin 
     if(sel=='b0) 
      {out,overflow) = {sum, co}; 
     if(sel=='b1) 
      {out,overflow) = {diff, bo}; 
    end 
endmodule 

還有一件事,你的模塊參數,這些參數定義了它的輸入和輸出的大小,但是它的名字表明它被固定爲三個,這可能會讓人困惑。

+1

你用'n'&'N'來標識相同的參數是非法的;挑一個或另一個。我建議使用大寫字母來識別參數,因爲這是行業內常見的做法和幾種編程語言 – Greg

+0

當然你是對的,謝謝! –

+0

謝謝你的幫助。所以模塊需要提前初始化。這意味着每當always塊中的模塊輸出被讀取時,它會根據a和b讀取新的輸入?另外,是否允許使用單個輸出線而不是聲明兩條線,總和和差異? – Darklink9110

0

你不能在verilog的always塊中實例化一個模塊。相反,您可以將模塊adder3bit和substract3bit更改爲任務,您可以使用現在編寫的代碼。 的解決方案將是這樣

task adder3bit; 
parameter n = 2; 
input [n:0] a; 
input [n:0] b; 
output reg [n:0] sum; 
output reg co; 
begin 
always @(*) {co, sum} = a + b; 
endtask 


task subtract3bit; 
parameter n = 2; 
input [n:0] a; 
input [n:0] b; 
output reg [n:0] diff; 
output reg bo; 
begin 
always @(*) {bo, diff} = a - b; 
endtask 

module alu(out, overflow, a, b,sel); 
input [2:0] a, b; 
input sel; 
output [2:0] out; 
output overflow; 
always @(a,b,sel) 
begin 
if(sel=='b0) 
    adder3bit (a,b,out,overflow); 
if(sel=='b1) 
    subtract3bit (a,b,out,overflow); 
end 
endmodule 
+1

任務不能包含「always」塊並且不能聲明參數。 – Greg

+0

始終阻止不能聲明,但參數可以是... –

+0

我沒有深入查看語法樹,看到參數是block_item_declaration的子集,它本身是任務使用的tf_item_declaration的子集。但是,在重新審查LRM時,我發現_pure_ Verilog(IEEE 1364)不支持在模塊外定義的任務/功能。它在SystemVerilog(IEEE 1800)中是合法的。所有現代的Verilog仿真器都是SystemVerilog仿真器,但是如果編譯器標誌被設置爲嚴格的Verilog,那麼在模塊外部定義的任務應該是編譯錯誤。 – Greg