cisen / blog

Time waits for no one.
133 stars 20 forks source link

MUX 数据选择器 #1125

Open cisen opened 2 years ago

cisen commented 2 years ago

二选一数据选择器(2-1 MUX)

20190907155152454

mux2to1

用 2输入mux,实现与,或,非,异或

与逻辑: out = (a == 1’b0)? 1’b0: ((b == 1’b0)? 1’b0: 1’b1); 或 out = (a == 1’b1)? b: 1’b0; Y=SA+S’B=AB+A’0=AB

或逻辑: out = (a == 1’b1)? 1’b1: ((b == 1’b1)? 1’b1: 1’b0); 或 out = (a == 1’b0)? b: 1’b1; Y=SA+S’B=A’B+A=A+B

非逻辑: out = (a == 1’b1)? 1’b0: 1’b1;

异或 out = (a == 1’b1)? ((b == 1’b1)? 1’b0: 1’b1) : (b); Y=AB’+A’B

四选一

https://blog.csdn.net/qq_41270858/article/details/108461200 https://github.com/cisen/multisim-github/tree/main/MUX 20190907155152454

20200908085713408

mux4to1

Verilog描述

①采用case语句描述

module data_selector41(sel,in,out);
    input [1:0] sel;
    input [3:0] in;
    output out;
    reg out;
    //若括号里均为0,则out必为0,完全可以不执行always语句
    always @(sel or in)
        begin
            case({sel[1],sel[0]})
                2'b00: out <= in[0];
                2'b01: out <= in[1];
                2'b10: out <= in[2];
                2'b11: out <= in[3];
                default: out <= 1'bx;
            endcase
        end
endmodule

②采用assign语句描述

module data_selector41(a,b,c,d,s1,s0,y);
    input a,b,c,d,s1,s0;
    output y;

    wire [1:0] SEL;
    wire A,B,C,D;

    assign SEL = {s1,s0};
    assign A = (SEL == 2'b00);
    assign B = (SEL == 2'b01);
    assign C = (SEL == 2'b10);
    assign D = (SEL == 2'b11);
    assign y = (a & A)|(b & B)|(c & C)|(d & D);
endmodule

③采用条件语句描述

module data_selector41(a,b,c,d,s1,s0,y);
    input a,b,c,d,s1,s0;
    output y;

    reg [1:0] SEL;
    reg y;

    always @(a,b,c,d,s1,s0)
        begin
            SEL = {s1,s0};
            if(SEL == 2'b00) y = a;
            else if(SEL == 2'b01) y = b;
            else if(SEL == 2'b10) y = c;
            else y = d;
        end
endmodule

测试程序

module test_data_selector41;
    reg [3:0] IN;
    reg [1:0] S;
    wire Y;
    data_selector41 D41(.sel(S),
                        .in(IN),
                        .out(Y));
    always #10 IN[0] =~ IN[0];
    always #20 IN[1] =~ IN[1];
    always #40 IN[2] =~ IN[2];
    always #80 IN[3] =~ IN[3];

    initial 
        begin
            S = 1'b0; IN = 4'h0;
            #160 $stop;
        end
        always #10 S = S+1;
endmodule

仿真结果 20201023151355585

cisen commented 2 years ago

从底层结构开始学习FPGA----MUX多路选择器(Multiplexer) https://blog.csdn.net/wuzhikaidetb/article/details/124764526?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22124764526%22%2C%22source%22%3A%22wuzhikaidetb%22%7D&ctrtid=HqsZb

一、什么是MUX

多路选择器MUX是一个多输入、单输出的组合逻辑电路,一个n输入的多路选择器就是一个n路的数字开关,可以根据通道选择控制信号的不同,从n个输入中选取一个输出到公共的输出端。

4选1的多路开关电路模型如下所示:

d902eb56a85643e78906af003bb0ad58

其真值表如下: f619e87ed3c4407db2fe062601f2392e

二、FPGA内部的MUX

在FPGA底层,MUX也是作为一种基本的逻辑单元而存在。下图是FPGA的一个基本逻辑单元----SLICEL,可见其是由LUT、MUX、CARRY4和FF组成。 31dd9f6f852d4f49829ea5632f406747

通过使用不同LUT6和MUX的组合级联,就可以实现想要的位数的MUX了。

首先需要说明的是,若只实现MUX2、MUX3、和MUX4是不需要使用到FPGA的MUX资源的,只需要使用LUT6即可。关于LUT6:从底层开始学习FPGA(1)----LUT查找表

不妨先写个MUX4的Verilog代码,再用vivado来implementation一下,看看使用了些什么资源。Verilog代码如下:

module test(
    input       A1,
    input       A0,

    input       D3,
    input       D2,
    input       D1,
    input       D0,

    output reg  Y

);

always @(*)begin
    case({A1,A0})
        2'b00:  Y = D0;     
        2'b01:  Y = D1; 
        2'b10:  Y = D2; 
        2'b11:  Y = D3; 
        default:;
    endcase

end

endmodule

用vivado来分析一下,门级电路如下:

c459ffad6aad47b4915ac861c424f5a6

嗯,就是一个标准的MUX4,与上面提出的电路图一致。

再来看看会综合(synthesis)出什么东西:

f9042c1c51b74474bc9b73c9820ce0f8

可以看到,只用了一个LUT6。然后再看看在FPGA上的具体实现: 91ee30f0c991446691b4839eac0e4895

同样的,只用了一个LUT6。既然MUX4都只用一个LUT6就可以实现了,那么MUX3、MUX2就当然也只需要一个LUT6了。

MUX4的实现使用一个LUT6,其中LUT6的4个输入作为MUX4的4个输入,而另外2个输入则作为MUX4的地址线。那么MUX5~MUX8又是如何实现?(MUX5~MUX8均采用3根地址线,可以一起讨论)。

接下来的讨论以MUX8为例,既然一个LUT6可以实现MUX4,那么2个LUT6 + 1个MUX2就可以实现MUX8的功能了。MUX8的Verilog形式:

module test(
    input       A2,
    input       A1,
    input       A0,

    input       D7,
    input       D6,
    input       D5,
    input       D4,         
    input       D3,
    input       D2,
    input       D1,
    input       D0,

    output reg  Y
);

always @(*)begin
    case({A2,A1,A0})
        3'b000: Y = D0;     
        3'b001: Y = D1; 
        3'b010: Y = D2; 
        3'b011: Y = D3; 
        3'b100: Y = D4;     
        3'b101: Y = D5; 
        3'b110: Y = D6; 
        3'b111: Y = D7;     
        default:;
    endcase
end

endmodule

门级电路:

b51c87a0930d4ccdbebfe2b8ded74d25

vivado综合:

a45f8e6e378d48f0ac4b71e2e58decbf

综合的结果是:2个LUT6 + 1个MUXF7。MUXF7就是一个MUX2,但是注意它的输入只能是LUT6的输出。

映射到FPGA:

0880ce6c30dc479b84a9e275136c090a

那么从MUX8类推MUX16就很容易了:4个LUT6 + 2个MUX2 + 1个MUX2。MUX16的Verilog形式:

module test(
    input       A3,
    input       A2,
    input       A1,
    input       A0,

    input       D15,
    input       D14,
    input       D13,
    input       D12,            
    input       D11,
    input       D10,
    input       D9,
    input       D8, 
    input       D7,
    input       D6,
    input       D5,
    input       D4,         
    input       D3,
    input       D2,
    input       D1,
    input       D0,

    output reg  Y
);

always @(*)begin
    case({A3,A2,A1,A0})
        4'b0000:    Y = D0;     
        4'b0001:    Y = D1; 
        4'b0010:    Y = D2; 
        4'b0011:    Y = D3; 
        4'b0100:    Y = D4;     
        4'b0101:    Y = D5; 
        4'b0110:    Y = D6; 
        4'b0111:    Y = D7; 
        4'b1000:    Y = D8;     
        4'b1001:    Y = D9; 
        4'b1010:    Y = D10;    
        4'b1011:    Y = D11;    
        4'b1100:    Y = D12;        
        4'b1101:    Y = D13;    
        4'b1110:    Y = D14;    
        4'b1111:    Y = D15;            
        default:;
    endcase
end

endmodule

门级电路:

bec90535ff6040c9a9186f6250f76b59

vivado综合:

9b02c8d51a5c4322b1e37b65dca15a7b

与料想的一致,三层级结构: 4个LUT6 + 2个MUXF7 + 1个MUXF8。

映射到FPGA: 196b22dbe1c14035b9872bc48b9fb509

再来看看上面出现的SLICEL的资源图:

31dd9f6f852d4f49829ea5632f406747

到这基本上就明白FPGA的独立MUX了:每个SLICE中都有2个MUXF7,其输入只能为LUT6的输出,而输出只能接到MUXF8;每个SLICE中都有1个MUXF8,其输入只能为MUXF7的输出。

但是我们知道MUX2是可以用LUT6来实现的,也就是说 2个LUT6 + 1个MUXF7可以转换成2个LUT6 + 1个LUT6来实现MUX8;而4个LUT6 + 2个MUXF7+1个MUXF8可以转换成4个LUT6 + 1个LUT6来实现。那么既然LUT6可以实现MUX2的功能,FPGA里为何还要有固定的MUX这种结构?

首先可以肯定的是用LUT6来实现MUX2的效率没有固定MUX2的效率高,因为有两个输入没有利用就意味着有资源是浪费的。其次,每个SLICE中只有4个LUT6,如果只用LUT6来实现MUX16则需要5个LUT6,那么第5个LUT6则势必会布线到其他Slice,这样就容易造成不好布线和拥堵,且4个LUT6的输出分别到达第五个LUT6的时间会不同,到达时间不一致则容易产生毛刺。

而LUT6+MUX的构造则布线长度则是基本一致的,可以看下图: b0ea6c22c62143358381c49e7d32d38e

重点关注紫线,可以看到这个长度基本一致。如果要布线到另外Slice的LUT6的话,可以想象这条路径有多长和多难控制长度一致。

三、总结

3.1、每个SLICE中都有2个MUXF7 + 1个MUXF8。MUXF7 的输入只能为LUT6的输出,而输出只能接到MUXF8;MUXF8的输入只能为MUXF7的输出

3.2、MUX4可以由LUT6来实现,每个SLICE可以实现4个独立的MUX4

fe870c5e33f6432ca3d9cffcf01040b7

3.3、MUX8可以由2LUT6 + 1个MUXF7来实现,每个SLICE可以实现2个独立的MU8

7083c7b07f9d42de86ceefad454e4318

3.4、MUX16可以由4LUT6 + 2个MUXF7 + 1个MUXF8来实现,每个SLICE可以实现1个独立的MU16

38c25bcd05334fe6966fe4cd03d17f24

3.5、若大于16路的多路选择器则需要数个SLICE的资源进行级联来实现