第03课 · 组合逻辑

组合逻辑MUX译码器Verilator

📌 学习目标:掌握组合逻辑电路设计方法,实现多路选择器(MUX)、译码器(Decoder)、编码器(Encoder),并通过 Verilator 仿真验证。

一、组合逻辑概述

组合逻辑电路的输出仅取决于当前输入,与历史状态无关。这是与时序逻辑的核心区别。组合逻辑电路:

二、多路选择器(MUX)

多路选择器从多个输入中选择一个输出,是 CPU 数据通路中最关键的组件之一。

2.1 2选1 MUX

sel=0 时输出 d0,sel=1 时输出 d1。逻辑表达式:Y = (~sel & d0) | (sel & d1)

seld0d1Y
0000
0010
0101
0111
1000
1011
1100
1111

2.2 4选1 MUX

2位选择信号从4个输入中选1个输出。

2.3 8选1 MUX

3位选择信号从8个输入中选1个输出。

三、译码器(Decoder)

译码器将 n 位二进制输入转换为 2ⁿ 条输出线中的一条有效信号。

3.1 2-4 译码器

A1A0Y3Y2Y1Y0
000001
010010
100100
111000

3.2 3-8 译码器

常用于内存地址译码和指令译码。

四、优先编码器(Priority Encoder)

当多个输入同时有效时,优先编码器输出优先级最高的输入编码。

五、Verilog 实现

// combo_logic.v — 组合逻辑:MUX + 译码器 + 编码器 // 2选1 MUX module mux2to1 ( input d0, d1, sel, output y ); assign y = sel ? d1 : d0; endmodule // 4选1 MUX module mux4to1 ( input [3:0] d, input [1:0] sel, output y ); assign y = d[sel]; endmodule // 2-4 译码器(带使能) module decoder2to4 ( input [1:0] a, input en, output [3:0] y ); assign y = en ? (4'b0001 << a) : 4'b0000; endmodule // 4位优先编码器 module priority_encoder4 ( input [3:0] din, output [1:0] dout, output valid ); assign valid = |din; assign dout = din[3] ? 2'b11 : din[2] ? 2'b10 : din[1] ? 2'b01 : 2'b00; endmodule

5.1 测试台

// tb_combo_logic.v — 组合逻辑测试台 module tb_combo_logic; reg d0, d1, sel1; wire y_mux2; reg [3:0] d4; reg [1:0] sel4; wire y_mux4; reg [1:0] dec_a; reg dec_en; wire [3:0] dec_y; reg [3:0] pe_in; wire [1:0] pe_out; wire pe_valid; mux2to1 u_mux2 (.d0(d0), .d1(d1), .sel(sel1), .y(y_mux2)); mux4to1 u_mux4 (.d(d4), .sel(sel4), .y(y_mux4)); decoder2to4 u_dec (.a(dec_a), .en(dec_en), .y(dec_y)); priority_encoder4 u_pe (.din(pe_in), .dout(pe_out), .valid(pe_valid)); integer pass = 0, fail = 0; initial begin // 测试 2选1 MUX $display("--- 2选1 MUX 测试 ---"); for (integer i = 0; i < 8; i = i + 1) begin {d0, d1, sel1} = i[2:0]; #1; if (y_mux2 !== (sel1 ? d1 : d0)) begin $display("FAIL MUX2: d0=%b d1=%b sel=%b y=%b", d0, d1, sel1, y_mux2); fail = fail + 1; end else pass = pass + 1; end // 测试 4选1 MUX $display("--- 4选1 MUX 测试 ---"); d4 = 4'b1010; for (integer i = 0; i < 4; i = i + 1) begin sel4 = i[1:0]; #1; if (y_mux4 !== d4[sel4]) begin $display("FAIL MUX4: sel=%b y=%b exp=%b", sel4, y_mux4, d4[sel4]); fail = fail + 1; end else pass = pass + 1; end // 测试 2-4 译码器 $display("--- 2-4 译码器 测试 ---"); dec_en = 1; for (integer i = 0; i < 4; i = i + 1) begin dec_a = i[1:0]; #1; if (dec_y !== (4'b0001 << dec_a)) begin $display("FAIL DEC: a=%b y=%b", dec_a, dec_y); fail = fail + 1; end else pass = pass + 1; end dec_en = 0; dec_a = 2'b00; #1; if (dec_y !== 4'b0000) fail = fail + 1; else pass = pass + 1; // 测试优先编码器 $display("--- 优先编码器 测试 ---"); pe_in = 4'b1000; #1; if (pe_out !== 2'b11 || pe_valid !== 1) fail = fail+1; else pass = pass+1; pe_in = 4'b0110; #1; if (pe_out !== 2'b10 || pe_valid !== 1) fail = fail+1; else pass = pass+1; pe_in = 4'b0000; #1; if (pe_valid !== 0) fail = fail+1; else pass = pass+1; $display("========================================"); $display("组合逻辑测试: PASS=%0d FAIL=%0d", pass, fail); if (fail == 0) $display("✅ MUX+译码器+编码器全部验证通过!"); else $display("❌ 存在失败!"); $display("========================================"); $finish; end endmodule

六、Verilator 编译命令

verilator --cc combo_logic.v --exe tb_combo_logic.v \ --build --top-module tb_combo_logic ./obj_dir/Vtb_combo_logic

📊 预期输出

--- 2选1 MUX 测试 --- --- 4选1 MUX 测试 --- --- 2-4 译码器 测试 --- --- 优先编码器 测试 --- ======================================== 组合逻辑测试: PASS=16 FAIL=0 ✅ MUX+译码器+编码器全部验证通过! ========================================

七、组合逻辑在 CPU 中的应用

🤔 思考题:如何用多个 2选1 MUX 级联构成 8选1 MUX?需要几级?

💡 提示:3级树形结构,第一级4个2选1→第二级2个2选1→第三级1个2选1

🏆 成就解锁:组合逻辑设计师

✅ Verilator 仿真验证通过

✅ 多路选择器 MUX 验证正确

✅ 译码器 Decoder 验证正确

✅ 优先编码器验证正确

🎯 下一目标:算术运算电路 → 第04课:加法器