Project 5: A Simple Communications System

Introduction

In this project, you will design a 4-to-1 mux and a decoder with an enable signal as a “de-mux” to implement a simple serial data transmitter. Both mux and de-mux will be implemented in two Verilog files for future re-use. Another Verilog file will be used to wrap up the mux and de-mux to form a communication system. This hierarchical design methodology will help manage design complexity, promote design reuse, and allow parallel development.

Before you begin, you should:

  • Have Vivado installed.
  • Have your FPGA board set up.
  • Know how to write behavioral Verilog HDL code and write XDC files.

After you're done, you should:

  • Know how to instantiate circuit blocks described in other Verilog files.
  • Know how to implement a system using hierarchical design methodology.

Inventory

  • Digilent Nexys A7 or Basys 3 FPGA Board
  • Vivado Installation

Time Multiplexing Data Transmission

The word multiplexer has its origins in telecommunications, defining a system where one signal is used to transmit many different messages, either simultaneously or at different times. “Time-multiplexing” describes a system where different messages use the same physical signal, with different messages being sent at different times. A multiplexer can be used as a simple time multiplexer if the select inputs are used to define the time window and the data inputs are used as the data sources. A decoder with an enable can be used as a de-multiplexer.

In the following system diagram in Fig. 1, a 4-to-1 multiplexer selects one on four inputs to pass through to the output, and a de-multiplexer (decoder with enable signal) takes a single input and routes it to one of four outputs. Figure 1. Time-multiplexing communication system using multiplexer and de-multiplexer.

Figure 1. Time-multiplexing communication system using multiplexer and de-multiplexer.


Step 1: Implement a 4-to-1 Multiplexer

1. Create a project for your board, and create new a Verilog module named mux, with four data inputs (I0, I1, I2, I3), two select inputs (S1, S0), and a single output (Y).

module mux (
    I0, I1, I2, I3, S0, S1, Y
);
 
input I0, I1, I2, I3, S0, S1;
output reg Y;
 
// Your behavioral description of Y
// using if-else or case statements
 
endmodule

2. Code the functionality of the mux behaviorally, as we discussed in the previous project.

3. Create a test bench to simulate the multiplexer and make sure it is working properly.


Step 2: Implement a De-Multiplexer

A de-multiplexer can be built using a binary decoder with an enable signal. The functional definition of a binary decoder with an enable signal is shown in Fig. 2 below. Figure 2. Decoder with an enable signal as a de-multiplexer.

Figure 2. Decoder with an enable signal as a de-multiplexer.

1. In the same project, create a new Verilog module named demux, with 3 inputs (En, I0, I1), and four outputs (Y0, Y1, Y2, Y3).

module demux (
    En, I0, I1, Y0, Y1, Y2, Y3
);
 
input En, I0, I1;
output reg Y0, Y1, Y2, Y3;
 
// Your behavioral description of Y
// using if-else or case statements
 
endmodule

2. Code the functionality of the mux behaviorally, as we discussed in the previous project.

3. Create a test bench to simulate the de-multiplexer and make sure it is working properly.


Step 3: Create a Wrapper as the Top Level Module

In this step we are going to create the top level module, in which a mux and a de-mux will be instantiated and connected properly to form a simple time multiplexing communication system. The system diagram is shown in Fig. 3 below.

Figure 3. Block diagram of top level module wrapper.

Figure 3. Block diagram of top level module wrapper.

In the block diagram, the input/output ports of the module wrapper is in green; the input/output ports of module mux and demux is displayed in black italic; and the internal wire of wrapper module is in purple.

1. In the project, create a new Verilog module file named wrapper with 4 data inputs (I3, I2, I1, I0), 2 select inputs (S1, S0), and four outputs (Y3, Y2, Y1, Y0).

module wrapper (
    I0, I1, I2, I3, S0, S1, Y0, Y1, Y2, Y3
);
 
input I3, I2, I1, I0, S1, S0;
output Y0, Y1, Y2, Y3;
 
// Structural Description of wrapper
 
endmodule

2. Declare internal wire sdata after input and output declaration.

wire sdata;

3. Instantiate the mux (named input_mux) and connecting wires in wrapper to the I/O ports of the mux.

mux input_mux (
    .I3(I3),
    .I2(I2),
    .I1(I1),
    .I0(I0),
    .S1(S1),
    .S0(S0),
    .Y(sdata)
);

4. Instantiate the de-mux (named output_demux) and connecting wires in wrapper to the I/O ports of the de-mux.

demux output_demux (
    .En(sdata),
    .I1(S1),
    .I0(S0),
    .Y0(Y0),
    .Y1(Y1),
    .Y2(Y2),
    .Y3(Y3)
);

5. Put everything together. The top level Verilog module will be as follows:

module wrapper (
    I0, I1, I2, I3, S0, S1, Y0, Y1, Y2, Y3
);
 
input I3, I2, I1, I0, S1, S0;
output Y0, Y1, Y2, Y3;
 
// Structural Description of wrapper
wire sdata;
 
mux input_mux (
    .I3(I3),
    .I2(I2),
    .I1(I1),
    .I0(I0),
    .S1(S1),
    .S0(S0),
    .Y(sdata)
);
 
demux output_demux (
    .En(sdata),
    .I1(S1),
    .I0(S0),
    .Y0(Y0),
    .Y1(Y1),
    .Y2(Y2),
    .Y3(Y3)
);
 
endmodule

6. Create an XDC file as follows:

  • I3 to SW3; I2 to SW2, I1 to SW1, I0 to SW0
  • Y3 to LED3; Y2 to LED2, Y1 to LED1, Y0 to LED0
  • S1 to BTN1, S0 to BTN0

Test Your Knowledge!

Now that you've completed this project, try these modifications:

1. To finish a real communication you need to implement a module (“counter”) that can cycle through 00, 01, 10, 11 for S1 and S0 automatically, and another module (“latch”) to hold the data. (Counters and latches will be discussed in future projects.) So, here are two Verilog modules that you can use that help you do this:

Create a top module that connects all the components as displayed in Fig. 4 below. Figure 4. Block diagram of a transmission system.

Figure 4. Block diagram of a transmission system.

Create an XDC file to map.

  • I3 to SW3; I2 to SW2, I1 to SW1, I0 to SW0
  • Y3 to LED3; Y2 to LED2, Y1 to LED1, Y0 to LED0
  • clk to on-board system clock
  • tData to LED7