天天看點

【邏輯電路】for循環的等價展開電路

引言

本文讨論如何了解for循環在邏輯電路中的實作。通過各種寫法的rtl電路對比,來探讨for循環的等價電路,或者for電路的等價展開電路。

for循環示例

如下給出一個for循環使用的例子,我們來試圖了解for循環如何展現在邏輯電路中。

`timescale 1ns / 1ps
module generate_test(
    input   wire            clk     ,
    input   wire            rst     ,
    input   wire    [2:0]   in_sel  ,
    //
    input   wire    [7:0]   in_ch0  ,
    input   wire    [7:0]   in_ch1  ,
    input   wire    [7:0]   in_ch2  ,
    
    output  reg     [7:0]   in_ch_seq 
    );

    
    wire     [7:0]   in_ch[2:0];

    assign  in_ch[0]    =   in_ch0;
    assign  in_ch[1]    =   in_ch1;
    assign  in_ch[2]    =   in_ch2;

    //輸入資料串行化
    // reg     [7:0]   in_ch_seq;
    reg     [2:0]   i;
    always@(posedge clk) begin
        for(i = 0; i <= 2; i = i + 1) begin
            if(in_sel[i]) begin
                in_ch_seq       <=  in_ch[i];
            end
        end
    end



endmodule      

很顯然,這個邏輯的功能大概就是将并行的輸入串行化,這可不必關心。本文的重點是這個for循環怎麼了解?

先看它對應的RTL電路:

【邏輯電路】for循環的等價展開電路

很容易看出,in_sel的各bit用于選擇哪個in_sel輸出;

無優先級的if

那既然如此,是不是可以這麼實作for循環的替代呢?即

用如下邏輯:

always@(posedge clk) begin
        if(in_sel[0]) begin
            in_ch_seq       <=  in_ch[0];
        end
        if(in_sel[1]) begin
            in_ch_seq       <=  in_ch[1];
        end
        if(in_sel[2]) begin
            in_ch_seq       <=  in_ch[2];
        end
    end      

替換邏輯:

reg     [2:0]   i;
    always@(posedge clk) begin
        for(i = 0; i <= 2; i = i + 1) begin
            if(in_sel[i]) begin
                in_ch_seq       <=  in_ch[i];
            end
        end
    end      

我們看下替換後的邏輯電路:

【邏輯電路】for循環的等價展開電路

可見, 幾乎與for循環寫法沒有差別,可見,for循環的邏輯電路,可以等價于這種if展開。

問題大學到此結束,但仍需看下其他幾種寫法;

有優先級的if

always@(posedge clk) begin
        if(in_sel[0]) begin
            in_ch_seq       <=  in_ch[0];
        end
        else if(in_sel[1]) begin
            in_ch_seq       <=  in_ch[1];
        end
        else if(in_sel[2]) begin
            in_ch_seq       <=  in_ch[2];
        end
    end      

相信我們的設計,使用這種寫法也可以實作我們的功能,其rtl為:

【邏輯電路】for循環的等價展開電路

和上述for循環幾乎沒有差別,差別僅在于in_sel[0]以及in_ch[0]會被優先判斷。

case

使用case寫法替換for:

always@(posedge clk) begin
        case(1'b1)
            in_sel[0]: in_ch_seq   <=  in_ch[0];
            in_sel[1]: in_ch_seq   <=  in_ch[1];
            in_sel[2]: in_ch_seq   <=  in_ch[2];
            default:    in_ch_seq   <=  in_ch_seq;
        endcase
    end      

其rtl電路如下:

【邏輯電路】for循環的等價展開電路

我相信僅從功能的角度,這種方式最容易了解。

将for循環的邏輯電路想象成這種形式的電路最容易了解。

總結

從功能的角度來看,上述這幾種方式去替代我們的for寫法均可,但是有時候,使用for循環最為友善,例如我們的輸入特别多,我們使用if,那樣會讓我們的代碼行數非常多,顯得臃腫不堪,可效率低下,這時候for循環就可大顯身手。

還有一個問題就是為什麼我們的示例,不是僅為單純的for,還加入了if,有多方面的考慮:

一方面,是這樣看起來我們的for循環更像是一個多驅動的電路,可實際并非如此,可見我們的等價寫法;

另一方面,更多的趣味性(沒必要找更多有點了)。

最後,不免有人擡杠,說有漏洞之類,沒關系,你是對的。