2016-04-28 36 views
0

我正在研究二進制解碼器,並試圖參數化地址大小。這是一個項目要求,這是在門級verilog。門級Verilog:有條件的,生成門輸入

有沒有辦法在基於ADDR_SIZE的第二個生成語句中生成i [k]語句?

module Decoder #(
    parameter ADDR_SIZE = 5 
)(
    out, 
    in 
); 
    input wire [ADDR_SIZE-1:0] in; 
    output wire [(2**ADDR_SIZE)-1:0] out; 
    wire [ADDR_SIZE-1:0] code, codeNot; 

    genvar j; 
    generate 
    for (j = 0; j < ADDR_SIZE; j = j + 1) 
    begin : bufs 
     buf (code[j], in[j]); 
     not(codeNot[j], in[j]); 
    end 
    endgenerate 

    genvar i; 
    generate 
    for (i = 0; i < (2**ADDR_SIZE); i = i + 1) 
    begin : selects 
     and (out[i], 
     i[0] ? codeNot[0] : code[0], 
     i[1] ? codeNot[1] : code[1], 
     i[2] ? codeNot[2] : code[2], 
     i[3] ? codeNot[3] : code[3], 
     i[4] ? codeNot[4] : code[4], 
    ); 
    end 
    endgenerate 
endmodule 

所以,如果ADDR_SIZE = 4,將改變的唯一的事情是:

and (out[i], 
     i[0] ? codeNot[0] : code[0], 
     i[1] ? codeNot[1] : code[1], 
     i[2] ? codeNot[2] : code[2], 
     i[3] ? codeNot[3] : code[3] 
    ); 

或者,如果ADDR_SIZE = 6

and (out[i], 
     i[0] ? codeNot[0] : code[0], 
     i[1] ? codeNot[1] : code[1], 
     i[2] ? codeNot[2] : code[2], 
     i[3] ? codeNot[3] : code[3], 
     i[4] ? codeNot[4] : code[4], 
     i[5] ? codeNot[5] : code[5] 
    ); 

自解碼器的,我接受2^ADDR_SIZE的二進制輸入(默認爲5)。根據輸入二進制值的不同,相應的輸出線將被驅動爲高電平,因此如果in = 5'b00001,out = 32'b ... 0000001(點全爲零,只有最低有效位爲高)。如果in = 5'b00011,out = 32'b ... 0000100。

該部分已完成,並在以下代碼中使用5位地址。我現在試圖做到這一點,如果我設置ADDR_SIZE = 4,我的輸入現在是4'b,我的輸出現在是16'b。這大多數工作,並且每個輸出行只是在或不在地方的AND。

畢竟這個生成的代碼被取出,我基本上是問我如何能做到以下幾點。同樣,它的重要性可以在Structural Verilog中完成。

parameter ADDR_SIZE = 5 

generate . . . 
and(out, a, b, c, d, e); 
endgenerate 

parameter ADDR_SIZE = 3 

generate . . . 
and(out, a, b, c); 
endgenerate 

parameter ADDR_SIZE = 6 

generate . . . 
and(out, a, b, c, d, e, f); 
endgenerate 
+0

歡迎堆棧溢出。對不起 - 我不明白你的問題。 –

+0

如果你爲ADDR_SIZE = 3和ADDR_SIZE = 4(即使只是幾個'i'值的摘錄)手寫的情況,你能告訴我們代碼應該是什麼樣子嗎?我猜可能需要一個嵌套的生成循環。 – hexafraction

+0

感謝您的反饋!現在已經編輯 – electricman

回答

0

如果您只想使用門級別,我的建議是使用遞歸調用自身的較小版本的模塊。例如:

module my_and #(parameter SIZE=4) (output out, input [SIZE-1:0] in); 
generate 
    if (SIZE<2) begin 
    // Intentionally cause a compile error if ever selected 

    // Verilog requires you to be a bit clever with your error messages 
    // Suggest using using non-existing modules instances 
    non_existing_module my_and_SIZE_is_less_than_2(); 

    // SystemVerlog allows option for more meaningful message 
    //$error("SIZE must be >= 2, was %0d @ %m", SIZE); 
    end 
    else begin 
    case(SIZE) 
     2 : and and2 (out, in[0], in[1]); 
     3 : and and3 (out, in[0], in[1], in[2]); 
     4 : and and4 (out, in[0], in[1], in[2], in[3]); 
     default : begin : recursive 
     wire half0, half1; 
     my_and #(SIZE/2) half_0 (half0, in[SIZE/2-1:0]); 
     my_and #(SIZE/2) half_1 (half1, in[SIZE-1-(SIZE%2):SIZE/2]); 
     if (SIZE%2) begin : odd 
      and and3 (out, half0, half1, in[SIZE-1]); 
     end 
     else begin : even 
      and and2 (out, half0, half1); 
     end 
     end 
    endcase 
    end 
endgenerate 
endmodule 

my_and未優化。根據您的目標最大尺寸和and的輸入,您可能需要考慮將遞歸方法有條件地分成三個或四個子片組。

然後創建一個本地載體的選擇:

genvar i,k; 
generate 
    for (i = 0; i < (2**ADDR_SIZE); i = i + 1) 
    begin : selects 
    wire [ADDR_SIZE-1:0] local_select; // local to scope 
    for(k = 0; k < ADDR_SIZE; k = k + 1) 
    begin 
     assign local_select[k] = i[k] ? code[k] : codeNot[k]; 
    end 
    my_and #(ADDR_SIZE) dec(out[i], local_select); 
    end 
endgenerate 

RTL顯然是簡單的:

module Decoder #(
    parameter ADDR_SIZE = 5 
)(
    output reg [(2**ADDR_SIZE)-1:0] out, 
    input [ADDR_SIZE-1:0] in 
); 
always @* begin 
    out = {(2**ADDR_SIZE){1'b0}}; 
    out[in] = 1'b1; 
end 
endmodule 
+0

Dang,我希望避免遞歸,以便在綜合過程中優化設計。謝謝! – electricman

+0

假設你有一個體面的合成器,你應該做你的解碼器RTL,而不是門,以獲得更多的優化合成。 – Greg