Combinational logic circuit design — multiplexer

Directory

1. Introduction to Multiplexer

2. Hardware design

3. Experimental tasks

4. Programming

4.1. Module design

4.2. Draw waveform diagram

4.3, write code

(1) Implementation method of the conditional operator (ternary operator) in assign:

(2) Use the if-else implementation method in the always statement block:

(3) The method of using the case statement in the always statement block:

4.4. Simulation verification

4.4.1. Writing TB files

4.4.2. Simulation verification

5. RTL schematic diagram


Combination logic circuit design — multiplexer

At the beginning of this chapter, we will carry out the design study of combinational logic circuits. The multiplexer is a logic circuit for the introduction of digital electronics. In this chapter, we will use the Verilog language to describe a circuit with a multiplexer function, leading everyone to master new syntax knowledge and basic module block diagrams, waveforms, code design methods, and finally verify the feasibility of the design through simulation.

1. Introduction to multiplexers

The multiplexer MUX (multiplexer) is a combinational logic circuit with multiple inputs and single output. An N-input multiplexer is an N-channel digital switch. Select an output to the common output. The multiplexer is also a basic resource inside the FPGA, mainly used for gating of internal signals. Simple multiplexers can also be cascaded to generate larger multiplexers.

2. Hardware design

On the development board, there are 5 key switches and 4 LED lights on board. The leftmost red button is the PL terminal reset button, the two buttons on the right of the PL terminal reset button are connected to the PL pin of ZYNQ, and the two rightmost buttons are connected to the PS pin of ZYNQ; the two leftmost LED lights are also connected to the ZTNQ The PL end of the power supply, the two LED lights on the far right are connected to the PS end. The actual picture is shown in the figure below:

The schematic diagram of the buttons on the backplane is shown in the figure below:

The schematic diagram of the LED on the base board is shown in the figure below:

It can be seen from the schematic diagram that the default state of the button is high level, and it will be low level after pressing, and the LED light will be lit when it is high level. We only use the peripherals on the PL side. Each button in the picture is connected with a 10K resistor, which acts as a current limiter to prevent the power supply from being directly grounded when the button is pressed and causing a short circuit.

3. Experimental tasks

The experimental task in this section is to use the ZYNQ development board to design a simple 2-to-1 multiplexer. The main function is to determine which of the input signals in1 and in2 is the output through the gate control signal sel. When the strobe control signal sel is 1, the output is the A terminal signal; when the strobe control signal sel is 0, the signal output is the B terminal signal.

4. Programming

4.1, Module Design

The function of this experiment is a two-choice multiplexer, so the module is named mux2_1. The input in the module is three 1-bit signals, among which in1 and in2 are two input signals, sel is an input control signal, and out is a single-bit output signal. The module diagram is shown in the figure below:

According to the experimental task, the truth table of the two-choice multiplexer can be listed, as shown in the following table:

It can be seen from the block diagram and the truth table that this experiment requires three input signals and one output signal. The input terminal can use two buttons on the PL terminal and a reset button, and the output terminal can be indicated by an LED light on the PL terminal.

4.2, draw waveform diagram

It can be seen from the truth table that when the sel signal is 1, the output signal out is equal to the input signal in1; when sel is 0, the output signal out is equal to in2.

Through the above analysis, we can draw the input and output waveforms of the multiplexer according to the truth table. Its waveform is shown in the figure below:

4.3, Writing Code

There are many forms of Verilog codes to realize the function of the two-to-one demultiplexer. Here, three different grammars are selected to realize the writing of the code.

(1) Implementation method of conditional operator (ternary operator) in assign:

Implementation method of conditional operator (ternary operator) in

//assign:
module mux2_1(
    input in1, //input signal in1
    input in2, //input signal in2
    input sel, //select control signal sel
    
    output out // output signal out
);

//************************************************** *****
//** main code
//************************************************** *****

//out: Combination logic output selection result
//The conditional operator (ternary operator) is used here, when the condition in the brackets is true
// Execute the result after "?"; if the condition in the brackets is not true, execute the result after ": "
assign out = (sel == 1'b1) ? in1 : in2;

endmodule

(2) Implementation method using if-else in the always statement block:

// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
//(2) Use if-else implementation method in the always statement block:
module mux2_1(
    input in1, //input signal in1
    input in2, //input signal in2
    input sel, //select control signal sel
                    
    output reg out //output signal out
);

//************************************************** *****
//** main code
//************************************************** *****

//out: Combination logic output selection result
always@(*) begin //"*" is a wildcard, when any input signal or level in this module changes
    if(sel == 1'b1) //The module below this statement will be executed.
        out <= in1;
    else
        out <= in2;
end

endmodule
// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

(3) Method of using case statement in always statement block:

//--------------------------------------------- --------
//(3) The method of using the case statement in the always statement block:
module mux2_1(
    input in1, //input signal in1
    input in2, //input signal in2
    input sel, //select control signal sel
            
    output reg out //output signal out
);

//************************************************** *****
//** main code
//************************************************** *****

//out: Combination logic output selection result
always@(*)begin
    case(sel)
        1'b0:
            out <= in2;
        1'b1:
            out <= in1;
        //If the situation of sel is not all listed, you must add default
        //Because there are only two cases of sel here, and they are all listed, so defalut can omit the judgment
        default: ;
    end case
end

endmodule
//------------------------------------------------ -----

4.4, simulation verification

4.4.1, Writing TB Files

TestBench is used to verify whether the design of the functional module meets expectations. It is mainly divided into the following three steps:

  • 1. Add stimulus to the input interface of the function module under test;
  • 2. Perform signal instantiation on the top-level interface of the function module under test;
  • 3. Determine whether the output of the tested functional module meets the design expectations.

The input ports of the two-to-one multiplexer module are in1, in2 and sel, and the output out is selected to output in1 or in2 according to the change of the control selection signal. So our simulation only needs to stimulate in1, in2 and sel to get the simulation of the output signal out.

The code of the two-to-one multiplexer TB module (tb_flow_led.v) is written as follows:

//Simulation verification
// write TB file
//TestBench is used to verify whether the design of the functional module meets expectations. It is mainly divided into the following three steps:
//1. Add stimulus to the input interface of the function module under test;
//2. Perform signal instantiation on the top-level interface of the function module under test;
//3. Determine whether the output of the tested functional module meets the design expectation.
//The input ports of the two-to-one multiplexer module are in1, in2 and sel,
//The output out is selected to output in1 or in2 according to the change of the control selection signal.
//So our simulation only needs to stimulate in1, in2 and sel to get the simulation of the output signal out.
//The code for the TB module (tb_flow_led.v) of the two-choice multiplexer is written as follows:

`timescale 1ns / 1ns

module tb_mux2_1();

reg in1;
reg in2;
reg sel;
wire out;

//initial statement cannot be synthesized, generally only expressed in testbench but not in RTL code.
initial begin //In the simulation, the contents of the begin...end block are executed sequentially
    in1 = 1'b0; //Initial state assignment
    in2 = 1'b0;
    sel = 1'b0;
    #100 //After 100ns delay
    in1 = 1'b0; //Input value at 100ns
    in2 = 1'b0;
    sel = 1'b1;
    #100 //After 200ns delay
    in1 = 1'b0; //Input value at 200ns
    in2 = 1'b1;
    sel = 1'b0;
    #100 //After 300ns delay
    in1 = 1'b0; //Input value at 300ns
    in2 = 1'b1;
    sel = 1'b1;
    #100 //After 400ns delay
    in1 = 1'b1; //Input value at 400ns
    in2 = 1'b0;
    sel = 1'b0;
    #100 // After a delay of 500ns
    in1 = 1'b1; //input value at 500ns
    in2 = 1'b0;
    sel = 1'b1;
    #100 //After 600ns delay
    in1 = 1'b1; //input value at 600ns
    in2 = 1'b1;
    sel = 1'b1;
end

mux2_1 u_mux2_1(
    .in1 (in1 ), //input signal in1
    .in2 (in2 ), //input signal in2
    .sel (sel ), //select control signal sel
                    
    .out (out ) // output signal out
);

endmodule

The 1ns / 1ns defined in the first line of code in the program means that the simulation unit and simulation precision are both 1ns.

In the testbench, the port list is empty, so the module in the third line is empty, and the variables in the initial and always statement blocks must be reg-type variables. The input variables need to be manually stimulated, so they must be reg-type variables . The output variables are generally wire variables in testbench.

The initial statement block is used in the 11th to 40th lines. The 13th to 15th lines first initialize each input signal. After the initialization is completed, the data of each input port needs to be simulated. Then assign a value to each input port every 100ns, and the generated data completes the excitation of the input port.

After completing the excitation of the signal, we can instantiate the test module, where mux2_1 is the name of the instantiated module, and u_mux2_1 is the name defined after our instantiation.

4.4.2, simulation verification

Next, open the Modelsim software to simulate the code. After running the simulation for 1us, the simulated waveform is shown in the figure below:

As can be seen from the above figure, in Figure 10.4.3 mux2_1 simulation waveform a, sel=1’b0, in2=1’b1, out=1’b1; in Figure 10.4.4 mux2_1 simulation waveform b, sel=1’b1, in1= 1’b0, out=1’b0. The simulation results correspond to the results of the truth table we listed. If you are interested, you can select several sets of waveforms to compare with the truth table.

5. RTL schematic

After completing the code design, you can view the RTL analysis schematic diagram through the Vivado software. Through the schematic diagram, you can quickly grasp the architecture diagram of the project design, which is convenient for subsequent code optimization. Click Schematic in the left navigation bar (located in Flow Navigator→RTL ANALYSIS→Open Elaborated Design→Schematic), open the RTL schematic design, as follows As shown in the figure:

. .

From the figure above, you can clearly see the corresponding relationship between the code and the circuit diagram. RTL_MUX is a selector, and the two input signals of in1 and in2 are selected according to the data of the control selection signal sel. It is worth mentioning that the RTL analysis schematic diagram in the Vivado software is only for the RTL level, not the corresponding relationship between the code and the internal resources of the FPGA device. If you want to check the corresponding relationship between the code and the internal resources of the FPGA, you can view the integrated principle Figure, you can first synthesize the code, and then find Flow Navigator→SYNTHESIS→Open Synthesized Design→Schematic, you can open it yourself to view.