FPGA Board For Beginner with free Experimental Manuals
Experimental Manuals FPGA for Beginners FPGA Products

FPGA evb – $59 – Cyclone 10

Fraser Innovation Inc

FII-PRA006/010 User Experimental Manual

Product Only $59

Product URL:

PRA006 – https://fraserinnovations.com/product/altera-fpga-study-board/

PRA010 – https://fraserinnovations.com/product/fpga-study-board-verilog-and-vhdl-for-beginner-cyclone-10-fpga-development-board-with-jtag-embeded-fii-pra010/

Official Shopping Website:  https://fpgamarketing.com/FPGA-Study-Board-Verilog-for-beginner-Cyclone-10-FII-PRA006-FII-PRA006.htm

We will send you official newest experimental manuals pdf file, hardware reference guide pdf file, project file zip file, Schematic Diagram pdf file when you order from above links:

FPGA Board For Beginner with free Experimental Manuals
FPGA Board For Beginner with free Experimental Manuals
Buy Cyclone-10 FPGA Development Board
Buy Cyclone-10 FPGA Development Board

The advantage of FPGA evb – Cyclone 10 development board:

  1. Beginner FPGA study board, cheaper but fully functional. cellphone sized. ( < 100 USD )
  2. power supply and download at the same time, no extra power supply and no extra data transfer line needed
  3. Small volume and light and can be put into your pocket. size: 10cm X 7 cm.
  4. Unique function: can be a study board as well a multifunctional JTAG downloader. 
  5. We use newest version Intel FPGA within two years and you can always keep in the front of FPGA industry.

 

Altera FPGA Study Board Hardware Resources:

  1. seven_seg_r
  2. VGA Video Interface × 1
  3. 1G Ethernet Interface × 1
  4. I2C EEPROM × 1
  5. DIP Switch × 8
  6. Controllable  LED light × 8
  7. Photoresistance × 1
  8. Thermistor × 1
  9. Adjustable Varistor × 1
  10. Buttons × 4
  11. GPIO Interface × 2
  12. Micro usb Interface(Power Supply and downlaod ) × 1
  13. SPI Communication Interface × 1
  14. AD/DA Conversion chip × 1
  15. JTAG Download Interface × 1
  16. FLASH 32Mbit  × 1
Buy FPGA Boards

Version Control

Version Date Descrption
V1.0 10/07/2019 Initial Release
V1.1 12/07/2019 Add figures for corresponding experimental phonomena of experiment board
V1.2 30/08/2019 Modify part of pin assignments and Ethernet description

Contents

FII-PRA006/010 User Experimental Manual 0

Project Files Content 5

Part One: Introduction to FII-PRA006/010 1

1、 Design Objective for the System 1

2、 System Resources 1

3、Human-computer Interaction Switch 1

4、Software Development System 1

5、Physical Picture 2

Part Two: FII-PRA006 The Use of Major Hardware Resources and FPGA Development Experiments 4

Experiment 1 LED shifting 5

1.1 Experiment Objective 5

1.2 Experiment Implement 5

1.3 Experiment 5

1.3.1 Introduction to LED 5

1.3.2 Hardware Design 5

1.3.3 Program Design 6

1.4 Experiment Verification 16

1.4.1 Some Preparation Before Verification 16

1.4.2 Method and Steps to Program the Board 19

Experiment 2 SignalTap 21

2.1 Experiment Objective 21

2.2 Experiment Implement 21

2.3 Experiment 21

2.3.1 Introduction to the Switches and SignalTap 21

2.3.2 Hardware Design 21

2.3.3 Program Design 22

2.4 Use and Verification of SignalTap Logic Analyzer 22

Experiment 3 Segment Display 26

3.1 Experiment Objective 26

3.2 Experiment Implement 26

3.3 Experiment 26

3.3.1 Introdyction to the Segment Display 26

3.3.2 Hardware Design 28

3.3.3 Program Design 28

3.4 Application and verification of Flash_memory 32

Experiment 4 Block/SCH Experiment 36

4.1 Experiment Objective 36

4.2 Experiment Implement 36

4.3 Experiment 36

4.4 Experiment Verification 39

Experiment 5 Button Debounce Experiment 40

5.1 Experiment Objective 40

5.2 Experiment Implement 40

5.3 Experiment 40

5.3.1 Introduction to Buttons and Debounce Principle 40

5.3.2 Hardware Design 41

5.3.3 Program Design 42

5.4 Experiment Verification 46

Experiment 6 Use of Multipliers and ModelSim Simulation 48

6.1 Experiment Objective 48

6.2 Experiment Implement 48

6.3 Experiment 48

6.3.1 Introduction of Program 48

6.4 Use of ModelSim and the Experiment Verification 51

Summary and Reflection 59

Experiment 7 Hexadecimal Number to BCD Code Conversion and Application 60

7.1 Experiment Objective 60

7.2 Experiment Implement 60

7.3 Experiment 60

7.2.1 Introduction to the Principle of Converting Hexadecimal Number to BCD Code 60

7.2.2 Introduction of the Program 62

7.4 Application of Hexadecimal Number to BCD Number Conversion 64

7.5 Experiment Verification 65

Experiment Summary and Reflection 67

Experiment 8 Use of ROM 68

8.1 Experiment Objective 68

8.2 Experiment Implement 68

8.3 Experiment 68

8.3.1 Introduction to Program 68

8.4 Experiment Verification 71

Experiment Summary and Reflection 72

Experiment 9 Use Dual_port RAM to Read and Write Frame Data 73

9.1 Experiment Objective 73

9.2 Experiment Implement 73

9.3 Experiment 73

9.3.1 Introduction of the Program 74

9.3 Experiment Verification 82

Experiment Summary and Reflection 83

Experiment 10 Asynchronous Serial Port Design and Experiment 84

10.1 Experiment Objective 84

10.2 Experiment Implement 84

10.3 Experiment 84

10.3.1 Inrtroduction of USB to Serial Conversion Chip (FT2232) 84

10.3.2 Hardware Design 85

10.3.3 Introduction to the Program 85

10.4 Experiment Verification 91

Experiment 11 IIC transmitting Experiment 93

11.1 Experiment Objective 93

11.2 Experiment Implement 93

11.3 Experiment 93

11.3.1 Introduction to EEPROM and IIC Protocol 93

11.3.2 Hardware Introduction 94

11.3.3 Introduction to the Program 94

11.4 Experiment Verification 103

Experiment 12 AD, DA Experiment 106

12.1 Experiment Objective 106

12.2 Experiment Implement 106

12.3 Experiment 106

12.3.1 Introduction to AD Conversion Chip PCF8591 106

12.3.2 Hardware Design 107

12.3.3 Introduction to the Program 108

12.4 Experiment Verification 110

Experiment 13 VGA Experiment 113

13.1 Experiment Objective 113

13.2 Experiment Implement 113

13.2 Experiment 113

13.2.1 VGA Principle 113

13.3.2 Hardware Design 115

13.3.3 Introduction to the Program 115

13.4 Experiment Verification 117

Experiment 14 Ethernet Experiment 119

14.1 Experiment Objective 119

14.2 Experiment Implement 119

14.3 Experiment 119

14.3.1 Experiment Principle 119

14.3.2 Hardware Design 121

14.3.3 Design of the Program 122

14.4 Experiment Verification 140

References 143

Project Files Content

Experiment 1: LED_shifting

Experiment 2: SW_LED

Experiment 3: BCD_counter

Experiment 4: block_counter

Experiment 5: block_debouncing

Experiment 6: mult_sim

Experiment 7: HEX_BCD, HEX_BCD_mult

Experiment 8: memory_rom

Experiment 9: dual_port_ram

Experiment 10: UART_FRAME

Experiment 11: eeprom_test

Experiment 12: adda_test

Experiment 13: vga

Experiment 14: Ethernet

Part One: Introduction to FII-PRA006/010

Design Objective for the System

The main purpose of designing this system is to achieve FPGA learning, development and experiment with Intel Quartus. The main device is Intel Cyclone10 10CL006YE144C8G or 10CL010YE144C8G, and is currently the latest generation of FPGA devices from Intel. The main learning and development projects can be completed as follows:

(1)Basic FPGA design practice

(2)Construction and practice using of SOPC (NIOSII) system.

(3)As a fully functional development board, PRA006/010 can also be used as a downloader to provide download services for Altera, Xillinx, and Risc-V.

System Resources

(1)Serial flash

Spi interface: serial flash (16M bytes)

(2)Serial EEPROM

(3)Gigabit Ethernet: 100/1000 Mbps

(4)USB to serial interface: USB-UART bridge

3、Human-computer Interaction Switch

(1)8 DIP switches

(2)5 buttons

4 buttons are defined as (up, down, left, right), the other one is the reset button

(3)8 LEDs

(4)6 seven-segment display

(5)I2C bus interface

(6)USB to UART interface

(7)JTAG programming interface

(8)2 12-pin GPIO connectors, in line with PMOD interface standards

(9)VGA interface

4、Software Development System

Quartus 18.0 and later versions for FPGA development, Nios-II SOPC

5、Physical Picture

(1)FII-PRA006 system block diagram

Figure 1 FII-PRA006 system block diagram

(2)FII-PRA006 physical picture

19

17

18

15

16

14

12

13

11

10

9

8

7

6

5

3

4

2

1

Figure 2 FII-PRA006 physical picture

(3)Corresponding to the physical picture of Figure 2, the main components of the development board are as follows:

1、10CL006YE144C8G or 10CL006YE144C8G

2、6-digit common anode seven-segment display

3、USB power supply and download interface

4、External expansion interface GPIO

5、8 DIP switches

6、8 LEDs

7、USB to serial port chip (FT2232)(Intefrated JTAG download function)

8、50 MHz oscillator

9、Thermistor (NTC-MF52)

10、Potentiometer

11、Photoresistor

12、4 buttons (up, down, right, down)

13、Reset button (Reset)

14、JTAG downloader function conversion interface

15、JTAG download interface (Used only when the board is used as a downloader)

16、Flash (N25Q128A, 128M bit/16M bytes)

17、Ethernet interface

18、Ethernet PHY chip (RTL8211E-VB)

19、VGA interface

20、Back of the board U8: AD/DA conversion chip (PCF8591)

21、Back of the board U13: EEPROM (AT24C02N)

Part Two: FII-PRA006 The Use of Major Hardware Resources and FPGA Development Experiments

This part mainly guides the user to learn the development of the FPGA program and the use of the onboard hardware through the experiment examples of the FPGA. At the same time, the experiment examples are developed from the elementary to the profound to introduction the development system software Quartus II. The experiments covered in this section are as follows.

Experiment 1: LED shifting design experiment

Experiment 2: SignalTap experiment

Experiment 3: Segment display experiment

Experiment 4: Block/SCH experiment

Experiment 5: button debouncing experiment

Experiment 6: use of multiplier and ModelSim simulation

Experiment 7: hex to BCD conversion and application

Experiment 8: usage of ROM

Experiment 9: use dual-ROM to read and write frame data

Experiment 10: asynchrounous serial port design and experiment

Experiment 11: IIC transmission experiment

Experiment 12: AD, DA experiment

Experiment 13: VGA experiment

Experiment 14: Ethernet experiment

Learning exercises in the order of the experimental design, and successfully completing these basic experiments, the level and capabilities of the primary FPGA engineers will be acheived.

Experiment 1 LED shifting

1.1 Experiment Objective

  1. Practice using the development software Quartus, the building of new projects, and the use of system resources IP Core;
  2. Proficiency practice in the writing of Verilog HDL programs to develop a fine code writing style;
  3. Master the design of the frequency divider to realize the design of LED shifting;
  4. Mange FPGA pin assignment according to the schematics, and verify it though programming the development board;
  5. Observe and summarize the experiment result

1.2 Experiment Implement

  1. All LEDs are lit up when pressing self-defined reset button;
  2. After resetting, LEDs light from low to high (from right to left) in turn;
  3. Each LED light is on for 1 second;
  4. After the last left (highest position) LED is lit, the next time it returns to the first right (lowest position) LED, to create a light shifting loop;

1.3 Experiment

1.3.1 Introduction to LED

LED (Light-Emitting Diode), is characterized by low operating current, high reliability and long life. Up to now, there are many types of LED lights, as shown in Figure 1.1. The FII-PRA006 uses the LED lights in the red circle.

Figure 1.1 Different kinds of LEDs

1.3.2 Hardware Design

The physical picture of the onboard 8-bit LED is shown in Figure 1.2. The schematics of LED is shown in Figure 1.3 (In the red rectangular). The LED module of this experiment board adopts 8 common anode LEDs, which are connected with Vcc 3.3V through 270 R resistors, and the cathodes are grounded through the N-channel FET (In the green rectangular). The FET gate is grounded through a 4.7K resistor, and the FPGA is connected to the FET gate through the SW_LED terminal (In the blue rectangular). Therefore, when the FPGA is set to 1, the output is high. The FET is turned on, then the LED is turned on, and the LED is on.

Figure 1.2 Physical picture of 8-bit LED

Figure 1.3 Schematics of LED

1.3.3 Program Design

1.3.3.1 System Block Diagram

See Figure 1.4 for the LED shifting system block diagram.

us division

Reset

Shift register

s division

ms division

50 MHz system clock

Figure 1.4 LED shifting system block diagram

1.3.3.2 Introduction to the program

Before writing a program, the development environment used and new project building are breifly introduced. Take the Quartus 18.1 version of the synthesizer as an example. The specific project establishment steps are shown in Figure 1.5 to 1.10.

  1. As shown in Figure 1.5, after opening Quartus, directly click New Project Wizard in the middle of the screen to create a new project, or click File to create a new project in the toolbar, or press Ctrl + N and follow the prompts to create a new project.
  2. As shown in Figure 1.6, select the correct project path. The project is named LED_shifting. It is recommended that the path is simple and easy to be found, which is convenient for later use and invoke.
  3. As shown in Figure 1.7, some files written in advance can be directly added, since it is a new project, click Next to perform the next step.
  4. As shown in Figure 1.8, select the correct FPGA chip model, the onboard chip model is 10CL006YE144C8G or 10CL010YE144C8G, select Cyclone 10 LP in the Family, select 144 in the Pin count, and select 8 in the Core speed grage. That helps narrow down the selection range and the target model can be found quickly.

Figure 1.5 Quartus II 18.1 interface

Figure 1.6 Path selection and naming of the project files

Figure 1.7 Add files

Figure 1.8 Device selection

  1. As shown in Figure 1.9, use the EDA tool that comes with Quartus.

Figure 1.9 Selection of EDA tool

  1. Click Next to proceed to the next interface and select Finish to complete the project building.
  2. Click File > New or use the shortcut key Ctrl+N to pop up the dialog box shown in Figure 1.10, to create a program file (note: Verilog HDL File), and write the code. Pay attention to the consistency of the program name and project name, and save it in the correct path (folder).

Figure 1.10 Start a new file (ii)

After the preparation is finished, starting to write the program, as described below.

The first step: the establishment of the main program framework (interface design)

module Led_shifting(

input rst,

input clk,

output reg [7:0] led

);

endmodule

The input signals of this experiment have 50MHz system clock clk, reset signal rst, and output signal led; 8 LEDs are defined by multi-bit width form of led [7:0], which reduces the code amount and facilitates code writing.

The second step: the invoke of IP Core and the establishment and use of PLL module

  1. See Figure 1.11, find ALTPLL in the IP catalog option bar on the right side of the main interface

Figure 1.11 IP Catalog

  1. As shown in Figure 1.12, double-click ALTPLL and enter the name of the PLL module in the pop-up dialog box. The name given here is PLL1. Note that the selection type is Verilog language type.

Figure 1.12 PLL naming

  1. As shown in Figure 1.13, after completing the previous step, the detailed setting interface is proceeded. Inclk0 is the input clock of the PLL, provided by the development board, which should be consistent with the system clock, set to 50MHz; PLL feedback path is set to normal mode. For advanced features involved, please use Intel reference file; PLL compensation output clock is c0; after the setting is completed, click Next.

Figure 1.13 PLL setting 1 (input clock)

  1. As shown in Figure 1.14, it is the setting of PLL asynchronous reset (areset) control and capture lock (locked) status. This experiment can be set to default mode shown in the figure.

Figure 1.14 PLL setting 2

  1. Click Next in the next 3 steps. Default settings are used.
  2. As shown in Figure 1.15, it is the setting of the PLL output clock. It can output 5 different clocks clk c0~c4. This experiment only uses one, set clk c0, other defaults are not applicable.. Set the output frequency to 100 MHz, the phase shift is set to 0, and the duty cycle is set to 50%.

Figure 1.15 PLL setting 3 (output clock)

  1. Keep the EDA setting to be default
  2. As shown in Figure 1.16, the output file type setting selects *.bsf (used in the subsequent design of graphic symbols) files and *.v files. Others are set by default and click Finish to complete the settings.

Figure 1.16 PLL setting 4 (output file type setting)

  1. As shown in Figure 1.17, select file in the Project Navigator type box of the project interface (the default is the project hierarchy)

Figure 1.17 PLL1.v file location

  1. As shown in Figure 1.18, click PLL1.v. The main window will display the contents of the PLL, find the module name and port list, copy it to the top level entity, and instantiate it.

Figure 1.18 PLL1.v

When the system is powered on, the pll_locked signal has a value of 0 before the PLL is locked (stable operation), pll_locked is pulled high after the PLL is locked, and the clock signal sys_clk is output normally. The phase-locked loop is instantiated as follows:

wire sys_clk;

wire pll_locked;

PLL1 PLL1_inst

(

.areset (1’b0),

.inclk0 (clk),

.c0 (sys_clk),

.locked (pll_locked)

)

  1. Sys_rst is used as the reset signal of the frequency division part, and ext_rst is used as the reset signal of the LED shifting. Under the drive of the clock sys_clk, it is synchronously reset by the primary register.
reg sys_rst;

reg rxt_rst;

always @ (posedge sys_clk)

begin

sys_rst <= !pll_locked;

ext_rst <= rst;

end

The third step: the design of the frequency divider

100 MHz clock output by PLL is used as the system clock. The experiment requires the shifting speed of LEDs to be 1 second, thus frequency division is applied. The design is firstly obtained 1us by microsecond frequency division, then 1ms is obtained by millisecond frquency division, and finally 1s clock is achieved through second frequency division.

  1. Microsecond frequency division
reg [6:0] us_cnt;

reg us_f;

always @ (posedge sys_clk)

begin

if (sys_rst) begin

us_cnt <= 0;

us_f <= 1’b0;

end

else begin

us_f <= 1’b0;

if (us_cnt == 99) begin

us_cnt <= 0;

us_f <= 1’b1;

end

else

us_cnt <= us_cnt + 1’b1;

end

end

The 100 MHz clock has a period of 10ns, and 1us requires 100 clock cycles, that is, 100 10ns. Therefore, a microsecond counter us_cnt [6:0] and a microsecond pulse signal us_f are defined. The counter is cleared at reset. On each rising edge of the clock, the counter is incremented by one. When the counter is equal to 99, the period of 1us elapses, and the microsecond pulse signal us_f is pulled high. Thus, every 1us, this module will generate a pulse signal.

  1. Millisecond frequency divider

Similarly, 1ms is equal to 1000 1us, so a millisecond counter ms_cnt [9:0] and a microsecond pulse signal ms_f are defined.

reg [9:0] ms_cnt;

reg ms_f;

always @ (posedge sys_clk)

begin

if (sys_rst) begin

ms_cnt <= 0;

ms_f <= 1’b0;

end

else begin

ms_f <= 1’b0;

if (us_f) begin

if (ms_cnt == 999) begin

ms_cnt <= 0;

ms_f <= 1’b1;

end

else

ms_cnt <= ms_cnt + 1’b1;

end

end

end

  1. Second frequency divider

Similarly, 1s is equal to 1000 1ms, so a second counter s_cnt [9:0] and one second pulse signal s_f are defined. When the three counters are simultaneously full, the time passes for 1 s and the second pulse signal is issued.

reg [9:0] s_cnt;

reg s_f;

always @ (posedge sys_clk) begin

if (sys_rst) begin

s_cnt <= 0;

s_f <= 1’b0;

end

else begin

s_f <= 1’b0;

if (ms_f) begin

if (s_cnt == 999) begin

s_cnt <=0;

s_f <= 1’b1;

end

else

s_cnt <= s_cnt + 1’b1;

end

end

end

The fourth step: the design of the shifting LED

When resetting, 8 LEDs are all on, so the output led is 8’hff. The LEDs need to light one by one, so the lowest LED is lit first. At this time, the led value is 8’b0000_0001. When the second pulse signal arrives, the next LED is illuminated, and the value of led is 8’b0000_0010.It can be seen that as long as the high level of “1” is shifted to the left, it can be realized by bit splicing, that is, led <= {led[6:0], led[7]}.

always @ (posedge sys_clk)

begin

if (ext_rst)

led <= 8’hff;

else begin

if (led == 8’hff)

led <= 8’b0000_0001;

else if (s_f)

led <= {led[6:0], led[7]};

end

end

1.4 Experiment Verification

1.4.1 Some Preparation Before Verification

Synthesis

Pin Assignment

Programmer

Compile

Figure 1.19 Introduction to some functions

As shown in Figure 1.19, after the program is written, analysis and synthesis is required to check for errors. Click the synthesis icon to complete, or use the shortcut key Ctrl+K, the pin assignment is to bind each signal to the FPGA pin, the compilation is to generate the programming file for the development board and check the error again. Click the programmer icon, and follow the instructions to program the development board. Click on the synthesis icon, Quartus will automatically generate a report after that, as shown in Figure 1.20. The details of the report are not described here.

Figure 1.20 Compilation report

Check and modify to no error before board verification. Do the pin assignment before actually programming the board. See Table 1.1 for the pin assignment.

Table 1.1 LED pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 Input clock
rst KEY3 10 Reset button
led[7] SW7_LED7 77 LED 7
led[6] SW6_LED6 76 LED 6
led[5] SW5_LED5 75 LED 5
led[4] SW4_LED4 74 LED 4
led[3] SW3_LED3 87 LED 3
led[2] SW2_LED2 86 LED 2
led[1] SW1_LED1 83 LED 1
led[0] SW0_LED0 80 LED 0

Click the pin assignment icon to open the pin assignment window, as shown in Figure 1.21. Double-click the location column corresponding to each pin, directly enter the pin number, or click the drop-down button to find the corresponding pin, but the latter is relatively slow. It should be noted that the I/O standard column in Figure 1.21, the content shown is the voltage standard of each I/O port, determined by the BANK voltage in the schematics and the design requirements. In this experiment, the I/O voltage should be selected as 3.3V. Double-click the I/O standard column and click the pull-down button, as shown in Figure 1.22, select the right voltage standard. The default voltage standard can be set in advance when selecting the chip model. Click Device and Pin Options -> Voltage -> Default I/O standard in Figure 1.8 to set it.

The pin assignment is complete, as shown in Figure 1.23. Then click on the compilation. After completion, program the development board.

Figure 1.21 Pin assignment window

C:\Users\Raytine\AppData\Local\Temp\1562232476(1).jpg

Figure 1.22 I/O voltage selection

Figure 1.23 Pin assignment finished

1.4.2 Method and Steps to Program the Board

Before programming the board, some settings should be made for the Quartus. For details, please refer to the “Intel FPGA Download Cable II User Guide” for reference. After the settings according to the instructions, click programmer icon to open the download window, as shown in Figure 1.24.

Figure 1.24 Program windows

After connecting the development board to the host computer, click on Hardware Setup and select development board, as shown in Figure 1.25.

Figure 1.25 Hardware setup

Click Start to program the board, as shown in Figure 1.26, Progress shows 100% (Successful), that is, the download is completed.

Figure 1.26 Programmed successfully

See Figure 1.27, the LEDs light one by one from low to high and the interval is one second.

Figure 1.27 Experiment phenomenon

Experiment 2 SignalTap

2.1 Experiment Objective

  1. Continue to practice using of the development board hardware;
  2. Practice the use of SignalTap Logic Analyzer in Quartus;
  3. Learn to analyze the captured signals.

2.2 Experiment Implement

Capture and analyze the switching signals on the development board through the use of SignalTap.

2.3 Experiment

2.3.1 Introduction to the Switches and SignalTap

  1. Introduction to the switches

The on-board switch is 8 DIP switches, as shown in Figure 2.1. The switch is used to switch the circuit by turning the switch handle using the binary coding principle of 0/1.

Figure 2.1 DIP switches physical picture

  1. Introduction to the SignalTap

SignalTap uses embedded logic analyzers to send signal data to SignalTap for real-time analysis of internal node signals and I/O pins when the system is operating normally.

2.3.2 Hardware Design

The schematics of the switch is shown in Figure 2.2 (In the red rectangular). One port of the 8 switches is connected to BANK_VADJ at the same time, which is in high level. The other port is respectively connected with an LED, and is connected to the control terminal SW_LED end of the LEDs. When the DIP switch is strobed, the high level turns on the FET, the LED is on, and a high level signal is input to the FPGA at the same time.

Figure 2.2 Schematics of the switches

2.3.3 Program Design

The first step: the establishment of the main program framework (interface design)

module SW_LED(

input clk,

input [7:0] sw,

output reg [7:0] led

);

endmodule

The experimental input signals have a system clock clk with frequency of 50 MHz, an high effective 8-bit switch sw, and an output 8-bit led.

2.4 Use and Verification of SignalTap Logic Analyzer

The first step: pin assignment

Pin assignments are shown in Table 2.1.

Table 2.1 Pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 Input clock
rst KEY3 10 Reset
SW[7] SW7_LED7 77 SW 7
SW[6] SW6_LED6 76 SW 6
SW[5] SW5_LED5 75 SW 5
SW[4] SW4_LED4 74 SW 4
SW[3] SW3_LED3 87 SW 3
SW[2] SW2_LED2 86 SW 2
SW[1] SW1_LED1 83 SW 1
SW[0] SW0_LED0 80 SW 0

The second step: SignalTap II setupa dn basic settings

Menu Tools > SignalTap II logic Analyzer

  1. In Figure 2.3, set the data under Signal Configuration
  2. Set the JTAG configuration and click on Setup to set the downloader.
  3. Set the device type by clicking Scan Chain
  4. Set up SOF Manager: set as *.SOF that is just compiled and generated before
  5. Clock and storage depth settings are shown in Figure 2.4.

Click the position shown in Figure 2.4 to add the clock. As shown in Figure 2.5, in the Clock Settings dialog box: Filter select SignalTap: pre-synthesis -> List, select the desired clock signal, select c0 in PLL1: PLL1_INST, move to the box on the right.

Other settings can be set as shown in Figure 2.2. (for advanced use of SignalTap II, please read the Intel reference files)

Double click to add nodes

Figure 2.3 SignalTap setting

Click here to add the clock

Figure 2.4 Clock signal and the sample depth

Figure 2.5 Clock signal selection dialogue

The third step: add observation signals

Figure 2.6 Adding interface for the observation signals

As shown in Figure 2.3, double-click the blank space to add the observation signal. Adding interface is shown in Figure 2.6. Select the signal to observe on the left side, add it to the right side, click Insert. Save it and recompile.

The fourth step: setting of observation signals

For the signal to be observed, whether it is a rising edge trigger, a falling edge trigger, or not care, etc., needs to be manually adjusted, as shown in Figure 2.7.

Figure 2.7 Trigger signal setting

The fifth step: observe the result

As shown in Figure 2.8, click Run Analysis to observe the output of SignalTap.

Figure 2.8 Experiment result

After the switch sw[4] is turned on, its signal is high, and the corresponding LED will be lit.

Modify the Trigger condition, test the output results under different Trigger conditions, analyze and summarize the experiment results.

 

Experiment 3 Segment Display

3.1 Experiment Objective

  1. Review previous experiments, proficient practice in PLL configuration, frequency division design, and project verification;
  2. Learn to use the BCD code counter;
  3. Digital display decoding design;
  4. Learn to program the project into the serial FLASH of the development board;

3.2 Experiment Implement

  1. The segment display has two lower (right most) digits to display seconds, the middle two digits to display minutes, and the highest (left most) two digits to display hours.
  2. The decimal point remains off and will not be considered for the time being.

3.3 Experiment

3.3.1 Introdyction to the Segment Display

One type of segment display is a semiconductor light-emitting device. The segment display can be divided into a seven-segment display and an eight-segment display. The difference is that the eight-segment display has one more unit for displaying the decimal point, the basic unit is a light-emitting diode. The on-board segment display is a six-in-one eight-segment display as shown in Figure 3.1, and its structure is shown in Figure 3.2.

Figure 3.1 Physical picture of the segment display

Figure 3.2 Single segment display structure

Common anode segment displays are used here. That is, the anodes of the LEDs are connected. See Figure 3.3. Therefore, the FPGA is required to control the cathode of the LED to be low level, illuminate the diode, and display the corresponding information. The six-digit common anode eight-segment display refers to the signal that controls which one is lit, which is called the bit selection signal. The content displayed by each digital segment is called the segment selection signal. The corresponding truth table is shown in Table 3.1.

Figure 3.3 Schematics of common anode LEDs

表3-1 共阳极八段数码管段选信号真值表

Segment Selection Signal DP G F E D C B A
· 0 1 1 1 1 1 1 1
0 1 1 0 0 0 0 0 0
1 1 1 1 1 1 0 0 1
2 1 0 1 0 0 1 0 0
3 1 0 1 1 0 0 0 0
4 1 0 0 1 1 0 0 1
5 1 0 0 1 0 0 1 0
6 1 0 0 0 0 0 1 0
7 1 1 1 1 1 0 0 0
8 1 0 0 0 0 0 0 0
9 1 0 0 1 0 0 0 0
A 1 0 0 0 1 0 0 0
B 1 0 0 0 0 0 1 1
C 1 1 0 0 0 1 1 0
D 1 0 1 0 0 0 0 1
E 1 0 0 0 0 1 1 0
F 1 0 0 0 1 1 1 0

There are two ways to display the segment display, static display and dynamic display.

Static display: Each display segment is connected with an 8-bit data line to control and maintain the displayed glyph until the next segment selection signal arrives. The advantage is that the driver is simple, and the disadvantage is that it takes up too much I/O resources.

Dynamic display: Parallel the segment selection lines of all segment display, and the digit selection line controls which digit is valid and lights up. Through the afterglow effect of the LED and the persistence effect of the human eye, the segment display appears to be continuously lit at a certain frequency. The advantage is to save I / O resources, the disadvantage is that the driver is more complicated, the brightness is not static display high.

In this experiment, the digital tube was driven by dynamic scanning.

3.3.2 Hardware Design

The schematics of the segment display is shown in Figure 3.4. The anode is connected to VCC through the P-channel field effect transistor. Therefore, when the bit selection signal SEG_3V3_D[0:5] is low level 0, the FET is turned on, the anode of the segment display is high level; the cathode (segment selection signal) SEG_PA, SEG_PB, SEG_PC, SEG_PD, SEG_PE, SEG_PF, SEG_PG, SEG_DPZ are directly connected to the FPGA and directly controlled by the FPGA. Therefore, when the bit selection signal is 0, and the segment selection signal is also 0, the segment display is lit.

Figure 3.4 Schematics of segment display

3.3.3 Program Design

3.3.3.1 System Block Diagram

The segment display system block diagram is shown in Figure 3.5.

Segment Display decode

Segment selection signal

System control

Frequency division

Bit selection signal

Segment Display

Reset

50 MHz system clock

Figure 3.5 Segment display system block diagram

The top-level module RTL view is shown in Figure 3.6.

Figure 3.6 RTL view

3.3.3.2 Introduction to Program

The first step: the establishment of the main program framework (interface design)

module BCD_counter (

input clk,

input rst,

output [7:0] seven_seg,

output [5:0] scan

);

endmodule

The input signal has a clock and a reset signal, and the output signal are a segment selection signal seven_seg and a new signal scan.

The second step: system control module

//Instantiate PLL

PLL PLL_inst

(

.areset (1’b0),

.inclk0 (clk),

.c0 (sys_clk),

.locked (locked)

);

//Reset signal

always @ (posedge sys_clk)

begin

sys_rst <= !locked;

ext_rst <= rst;

end

In the first sub-module (system control module), the input clock is the system 50 MHz clock, and a 100MHz is output through the phase-locked loop as the working clock of the other sub-modules. The phase-locked loop lock signal is inverted as the system reset signal. The button is reset to be used as an external hardware reset signal.

The third step: the frequency division module

Referring to previous experiments, a millisecond pulse signal and a second pulse signal are output as input signals of the segment display driving module.

The fourth step: segment display driver module

  1. Counting section

The counting part is similar to the frequency dividing module. It is timed by the second pulse signal for 60 seconds, 60 minutes, 24 hours, and when the time reaches 23 hours, 59 minutes and 59 seconds, the counters are all cleared, which is equivalent to one day.

  1. Segment display dynamic scanning part
reg [3:0] count_sel;

reg [2:0] scan_state;

always @ (posedge clk)

begin

if (rst) begin

scan <= 6’b111_111;

count_sel <= 4’d0;

scan_state <= 0;

end

else case (scan_state)

0 :

begin

scan <= 6’b111_110;

count_sel <= counta;

if (ms_f)

scan_state <= 1;

end

 

1 :

begin

scan <= 6’b111_101;

count_sel <= countb;

if (ms_f)

scan_state <= 2;

end

 

2 :

begin

scan <= 6’b111_011;

count_sel <= countc;

if (ms_f)

scan_state <= 3;

end

 

3 :

begin

scan <= 6’b110_111;

count_sel <= countd;

if (ms_f)

scan_state <= 4;

end

 

4 :

begin

scan <= 6’b101_111;

count_sel <= counte;

if (ms_f)

scan_state <= 5;

end

5 :

begin

scan <= 6’b011_111;

count_sel <= countf;

if (ms_f)

scan_state <= 0;

end

default : scan_state <= 0;

endcase

end

The dynamic scanning of the segment display is realized by the state machine. A total of six segment display require six states. The state machine scan_state[2:0] is defined, and the corresponding content count_sel is displayed in different states. At reset, all six segment display are extinguished and jump to the 0 state. The segment display is dynamically scanned in 1 millisecond time driven by a millisecond pulse:

In the 0 state, the 0 segment display is lit, and the ones digit of the second is displayed;

In the 1 state, the first segment display is lit, and the tens digit of the second is displayed;

In the 2 state, the second segment display is lit, and the ones digit of the minute is displayed;

In the 3 state, the third segment display is lit, and the tens digit of the minute is displayed;

In the 4 state, the fourth segment display is lit, and the ones digit of the hour is displayed;

In the 5 state, the fifth segment display is lit, and the tens digit of the hour is displayed

The fifth step: segment display segment code section

always @ (*)

begin

case (count_sel)

0 : seven_seg_r <= 7’b100_0000;

1 : seven_seg_r <= 7’b111_1001;

2 : seven_seg_r <= 7’b010_0100;

3 : seven_seg_r <= 7’b011_0000;

4 : seven_seg_r <= 7’b001_1001;

5 : seven_seg_r <= 7’b001_0010;

6 : seven_seg_r <= 7’b000_0010;

7 : seven_seg_r <= 7’b111_1000;

8 : seven_seg_r <= 7’b000_0000;

9 : seven_seg_r <= 7’b001_0000;

default : seven_seg_r <= 7’b100_0000;

endcase

end

Referring to Table 3.1, the characters to be displayed are associated with the segment code, the decimal point is set high to extinguish, and then the final segment selection signal output is composed in a spliced form.

3.4 Application and verification of Flash_memory

The first step: pin assignment

Pin assignments are shown in Table 3.2.

Table 3.2 Segment display pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 Input Clock
rst KEY3 10 Reset
scan[5] SEG_3V3_D5 124 Bit selection 5
scan[4] SEG_3V3_D4 127 Bit selection 4
scan[3] SEG_3V3_D3 129 Bit selection 3
scan[2] SEG_3V3_D2 141 Bit selection 2
scan[1] SEG_3V3_D1 142 Bit selection 1
scan[0] SEG_3V3_D0 136 Bit selection 0
seven_seg[7] SEG_PA 128 Segment selection 7
seven_seg[6] SEG_PB 135 Segment selection 6
seven_seg[5] SEG_PC 138 Segment selection 5
seven_seg[4] SEG_PD 126 Segment selection 4
seven_seg[3] SEG_PE 125 Segment selection 3
seven_seg[2] SEG_PF 133 Segment selection 2
seven_seg[1] SEG_PG 137 Segment selection 1
seven_seg[0] SEG_DP 132 Segment selection 0

The second step: compilation

The third step: solidify the program to Flash

Onboard Flash (N25Q128A) is a serial Flash chip that can store 128Mbit of content, which is more than enough in the engineering learning process. The schematics of the Flash is shown in Figure 3.7.

Figure 3.7 Schematics of flash

The function of Flash is to save the program on the development board. After the power is off, the program will not disappear. The next time the development board is powered on, it can be used directly. It is more practical in the actual learning life. Driven by the SPI_CLK clock, the FPGA Flash is programmed through the SPI_ASDO line. After repowered on, the FPGA re-reads the program to the FPGA through SPI_XDATA for testing.

The specific configuration process of Flash is as follows:

  1. Menu File -> Convert programming files, as shown in Figure 3.8;
  2. Option settings
  3. Select JTAG Indirect configuration File(*.Jic)
  4. Configuration Device:EPCQ 128A (Compatible with development board N25Q128A)
  5. Mode:Active serial

Figure 3.8 *.jic file setting

  1. Click the Advanced button and set it as shown in Figure 3.9.

Figure 3.9 Advanced setting

  1. Add a conversion file, as shown in Figure 3.10.

Figure 3.10 Add conversion file

  1. Add a device, as shown in Figure 3.11.

Figure 3.11 Add a device

  1. Click Generate to generate the BCD_counter.jic file
  2. Consistent with previous program verification operations, select the correct file (*.jic) to program the development board

The fourth step: power up verification

As shown in Figure 3.12, after repowered on, the FPGA automatically reads the program in Flash into the FPGA and runs it.

Figure 3.12 Experiment phenomenon

Experiment 4 Block/SCH Experiment

4.1 Experiment Objective

  1. Review building new FPGA projects in Quartus, device selection, PLL setup, PLL frequency setting, Verilog’s tree hierarchy design, and the use of SignalTap II
  2. Master the design method of graphics from top to bottom
  3. Combined with the BCD_counter project to achieve the display of the digital clock
  4. Observe the experimental results

4.2 Experiment Implement

Use schematics design to build the project

4.3 Experiment

This experiment is mainly to master another design method. The other design contents are basically the same as the experiment 3. Similar steps will not be introduced in detail. The modular design method is introduced below.

  1. New project: File -> New Project Wizard…

Project name: block_counter

Select device (10cl010YE144c8G)

  1. Create new file; File -> New, select Block Diagram/Schematic File. See Figure 4.1.

Figure 4.1 New file

  1. See Figure 4.2, the middle part is the graphic design area, which can be used for Block/SCH design.
  2. Save the file as block_counter.bdf
  3. Double-click the blank space in the graphic design area to add a symbol

Figure 4.2 Graph design interface

  1. Graph editing

Double-click on the graphic design area to select the appropriate library and device in the libraries

Click here to modify the pin name

Figure 4.3 Input symbol

  1. Add input, output, and modify their names
  2. Add a custom symbol
  3. bdf Create a new block/sch file and save it as PLL_sys.bdf
  4. Add PLL IP, refer to experiment 1
  5. Select the generated file to include the PLL1.bsf file
  6. Double-click in the blank area of the PLL_sys.bdf file to select the PLL1 symbol just generated and add it to the file, as shown in Figure 4.4.

Figure 4.4 Invoke the symbols generated in the IP catalog in the graphical editing interface

  1. Continue to add other symbols, input, output, dff, GND, etc. and connect them, as shown in Figure 4.5.

Figure 4.5 Connect the device

  1. Recreate the newly created file symbol for graphic editing to use in subsequent design
  2. File > Create/Update > Create Symbol file for Current File. See Figure 4.6.
  3. Generate PLL_sys.bsf

Figure 4.6 Creating a symbol file for the current file (symbol file *.bsf)

  1. Create a frequency division module
  2. Create a new verilog file div_us for the frequency divider (Refer project files for the code)
  3. The PLL output clock is used as its own input clock, and the 100 MHz clock is divided into 1 MHz clocks.
  4. Repeat (7) to create div_us.bsf
  5. Create a new 1000 frequency division verilog file: div_1000f.v
  6. Create div_1000f.bsf symbol
  7. Create the output pulse us, ms, second module, as shown in Figure 4.7. Refer the specific implementation to the reference code and the frequency division design of the experiment 1 and 3
  8. Create a new block/sch file block_div and add the designed graphic symbol file to block_div.bdf
  9. Repeat (7) to create the block_div.bsf symbol

Figure 4.7 us, ms, second pulse of block/sch design

  1. Create a new verilog file bcd_counter.v, design the hour and minute counter, and create the bsf symbol. Refer to the previous experiments, and implement part of the frequency division using block_div in (9).
  2. Combine each *.bsf and complete the design of the digital clock (block_counter.bdf), as shown in Figure 4.8.

Figure 4.8 Digital clock for BDF design

4.4 Experiment Verification

Pin assignment, compilation, and program verification are consistent with Experiment 3. For reference, see Experiment 3, which is skipped here.

Experiment 5 Button Debounce Experiment

5.1 Experiment Objective

  1. Review the design process of the shifting LED
  2. Learn button debounce principle and adaptive programming
  3. Study the connection and use of the FII-PRA006/010 button hardware circuit
  4. Comprehensive application button debounce and other conforming programming

5.2 Experiment Implement

  1. Control the movement of the lit LED by pressing the button
  2. Each time the button is pressed, the lit LED moves one bit.
  3. When the left shift button is pressed, the lit LED moves to the left, presses the right button, and the lit LED moves to the right.

5.3 Experiment

5.3.1 Introduction to Buttons and Debounce Principle

  1. Introduction to buttons

The on-board buttons are common push buttons, which are valid when pressed, and automatically pops up when released. A total of five, respectively, PB0 (UP), PB1 (LEFT), PB2 (RIGHT), PB3(DOWN) and a hardware reset button (RESET). As shown in Figure 5.1.

Figure 5.1 Button physical picture

  1. Principle of button debounce

As long as mechanical buttons are used, instability should be considered. Usually, the switches used for the buttons are mechanical elastic switches. When the mechanical contacts are opened and closed, due to the elastic action of the mechanical contacts, a push button switch does not immediately turn on when closed, nor is it off when disconnected. Instead, there is some bouncing when connecting and disconnecting. See Figure 5.2.

The length of the button’s stable closing time is determined by the operator. It usually takes more than 100ms. If pressing it quickly, it will reach 40-50ms. It is difficult to make it even shorter. The bouncing time is determined by the mechanical characteristics of the button. It is usually between a few milliseconds and tens of milliseconds. To ensure that the program responds to the button’s every on and off, it must be debounced. When the change of the button state is detected, it should not be immediately responding to the action, but waiting for the closure or the disconnection to be stabilized before processing. Button debounce can be divided into hardware debounce and software debounce.

https://electrosome.com/wp-content/uploads/2012/12/Switch-Bouncing-in-Pull-Down-Connection.jpg

Figure 5.2 Button bounce principle

In most of cases, software or programs are used to achieve debounce. The simplest debounce principle is to wait for a delay time of about 10ms after detecting the change of the button state, and then perform the button state detection again after the bounce disappears. If the state is the same as the previous state just detected, the button can be confirmed. The action has been stabilized. This type of detection is widely used in traditional software design. However, as the number of button usage increases, or the buttons of different qualities will react differently. If the delay is too short, the bounce cannot be filtered out. When the delay is too long, it affects the sensitivity of the button.

5.3.2 Hardware Design

The schematics is shown in Figure 5.3. One side of the button (P1, P2) is connected to VCC, and the other side (P3, P4) is connected to the FPGA. At the same time, it is connected to GND through a 1 kohm resistor. In the normal state, the button is floating, thus the potential of the button P3 is 0, so the input value of the button to the FPGA is 0; when the button is pressed, the buttons are turned on both sides, and the potential of the button P3 is VCC3.3V, so the input value of the button to the FPGA is 1. The onboard switch is active high.

Figure 5.3 Schematics of buttons

5.3.3 Program Design

5.3.3.1 System Block Diagram

Figure 5.4 shows the block diagram of the button controlled shifting LED system.

50 MHz system clock

Shifting LED

LED

System control

Button Debounce

Frequency Division

Reset

Figure 5.4 System block diagram

The top-level module RTL view is shown in Figure 5.5.

Figure 5.5 RTL view

See Figure 5.6 for the top level design.

Figure 5.6 Top level design

5.3.3.2 Introduction to the Program

 

Refer to the previous experiments for the frequency division module and the LED display module. Here, a new part of the button debounce module is introduced.

This chapter introduces an adaptive button debounce method: starts timing when a change in the state of the button is detected. If the state changes within 10ms, the button bouncing exists. It returns to the initial state, clears the delay counter, and re-detects the button state until the delay counter counts to 10ms. The same debounce method is used for pressing and releasing the button. The flow chart is shown in Figure 5.7. Case 0 and 1 debounce the button press state. Case 2 and 3 debounce the button release state. After finishing the whole debounce procedure, the program outputs a synchronized clock pulse.

Start

End

Figure 5.7 Button debounce flow chart

module pb_ve (

input sys_clk,

input sys_rst,

input ms_f,

input keyin,

output keyout

);

reg keyin_r;

reg keyout_r;

reg [1:0] ve_key_st;

reg [3:0] ve_key_count;

always @ (posedge sys_clk)

begin

keyin_r <= keyin;

end

always @ (posedge sys_clk)

begin

if (sys_rst) begin

keyout_r <= 1’b0;

ve_key_count <= 0;

ve_key_st <= 0;

end

else case (ve_key_st)

0 :

begin

keyout_r <= 1’b0;

ve_key_count <= 0;

if (keyin_r)

ve_key_st <= 1;

end

1 :

begin

if (!keyin_r)

ve_key_st <= 0;

else begin

if (ve_key_count == 10)

ve_key_st <= 2;

else if (ms_f)

ve_key_count <= ve_key_count + 1’b1;

end

end

2 :

begin

ve_key_count <= 0;

if (!keyin_r)

ve_key_st <= 3;

end

3 :

begin

if (keyin_r)

ve_key_st <= 2;

else begin

if (ve_key_count == 10) begin

ve_key_st <= 0;

keyout_r <= 1’b1;

end

else if (ms_f)

ve_key_count <= ve_key_count + 1’b1;

end

end

default : ;

endcase

end

assign keyout = keyout_r;

 

endmodule

5.4 Experiment Verification

The first step: pin assignment

See Table 5.1 for the pin assignment

Table 5.1 Button debounce pin mapping

Signal Name Network Label FPGA Pin Port Description
left KEY1 3 Left shift signal
right KEY2 7 Right shift signal
rst KEY3 10 Reset
led[7] SW7_LED7 77 LED 7
led[6] SW6_LED6 76 LED 6
led[5] SW5_LED5 75 LED 5
led[4] SW4_LED4 74 LED 4
led[3] SW3_LED3 87 LED 3
led[2] SW2_LED2 86 LED 2
led[1] SW1_LED1 83 LED 1
led[0] SW0_LED0 80 LED 0

The second step: program the development board

After the pin assignment is completed, the compilation is performed. The experimental phenomenon is shown in Figure 5.8 to Figure 5.10 below.

After the development board is programmed, the LEDs are completely off, press the reset button, the LED are fully illuminated, as shown in Figure 5.8.

Figure 5.8 Button debounce experiment phenomenon (Reset state)

When the right shift button is pressed, the highest LED lights up. See Figure 5.9.

Figure 5. 9 Button debounce experiment phenomenon (One right shift)

Press the right shift button again and the LED will move one bit to the right. See Figure 5.10.

Figure 5. 10 Button debounce experiment phenomenon (Another right shift)

Experiment 6 Use of Multipliers and ModelSim Simulation

6.1 Experiment Objective

  1. Learn to use multiplier
  2. Use ModelSim simulation to design output

6.2 Experiment Implement

  1. 8×8 multiplier, the first input value is an 8-bit switch, and the second input value is the output of an 8-bit counter.
  2. Observe the output in ModelSim
  3. Oberseve the calculation results with a four-digit segment display

6.3 Experiment

Since the simulation tools and the new IP core are used here, there is no introduction or design part of hardware.

6.3.1 Introduction of Program

ModelSim is an HDL language simulation software. Programs can be simulated to achieve inspection and error correction. ModelSim experiment, different from the previous experiment, when building the project, the simulation tool to be used needs to be added in the EDA tool selection window. See Figure 6.1.

Figure 6.1 EDA tool setting

Only one counter, one PLL and one multiplier are used in the program. Only the multiplier is introduced here.

The first step: the establishment of the main program framework

module mult_sim (

input inclk,

input rst,

input [7:0] sw,

output [15:0] mult_res,

output reg [7:0] count

);

The value of the switch is used as the first input of the multiplier, the value of the counter is the second input, and the result of the calculation is output.

The second step: the multiplier IP core setting steps are as follows:

  1. After adding the LPM_MULT IP (IP Catalog > Library > Basic Functions > Arithmatic > LPM_MULT) and saving the path, the setting window of the multiplier is popped up, as shown in Figure 6.2, and the two input data is set to eight bits as required.

Figure 6.2 mult setting 1

  1. Select the multiplication type to be Unsigned. See Figure 6.3.

Figure 6.3 mult setting 2

  1. Select the pipeline to speed up the operation, as shown in Figure 6.4.
  2. Select others to be default.

Figure 6.4 mult setting 3

8×8 multiplier instantiation:

reg sys_clk;

mult_8x8 mult_8x8_inst (

.clock (sys_clk),

.dataa (sw),

.datab (count),

.result (mult_res)

);

6.4 Use of ModelSim and the Experiment Verification

Here, ModelSim simulation is used to verify the experiment.

Method 1: Simulation based on waveform input

  1. Click the menu bar Tools > Options, as shown in Figure 6.5, click OK.

Figure 6.5 Select ModelSim-Altera path

  1. Tools > Run Simulation Tool > RTL Simulation to start simulation. See Figure 6.6.

Figure 6.6 ModelSim window

  1. Set ModelSim
  2. Simulate > Start Simulation
  3. In the popup window, add libraries under Libraries tag. See Figure 6.7.

Figure 6.7 Add simulation libraries

  1. Under Design tag, choose simulation project mult_sim and click OK. See Figure 6.8.

Figure 6.8 Choose the project to simulate

  1. In the Objects window, choose all the signals and drag them to Wave window. See Figure 6.9.

Figure 6.9 Add observation signals

  1. Set the signals in Wave, right click any signal and a selection window will occur. See Figure 6.10.

Figure 6.10 Set the signals

  1. Logical signals select Force and select Clock for clock signals
  2. Set rst siganl. See Figure 6.11.

Figure 6.11 Set rst signal

  1. Set Inclk signal. See Figure 6.12.

Figure 6.12 Set inclk signal

  1. Set sw signal. See Figure 6.13.

Figure 6.13 Set sw signal

  1. Run simulation. In the tool bar, set the simulation time to be 100 ns. Click the Run icon to run the simulation. See Figure 6.14.

Figure 6.14 Set the simulation time

  1. Observe the simulation result. See Figure 6. 15.

Figure 6.15 Simulation result

  1. Result analysis
  2. Counter count does not have a valid result, instead, unknow result XXXXXX is gotten.
  3. sys_rst does not reset signals. It changes from X to 0
  4. Add pll_locked signal to the wave, and re-simulate
  5. In Figure 6.16, before PLL starts to lock, the sys_clk already has a rising edge, so PLL_locked signal is just converted from low to high. There is no reliable reset is formed.

Figure 6.16 Re-simulation result

  1. Solution
  2. Define sys_rst to be 1’b1
  3. Use external rst signal to provide reset

Here method a is adopted. The revised code is as follows:

module pll_sys_rst(

input inclk,

output sys_clk,

output reg sys_rst = 1’b1

);

  1. Recompile the simulation

Figure 6.17 Recompile the simulation

Since waveform editing efficiency is relatively low, the use of simulation testbench file is encouraged.

Method 2: Write a testbench file for simulation

  1. Name a new Verilog HDL file tb_mult.v.
  2. The code is as follows:
`timescale 1ns/1ps

module tb_mult;

reg rst;

reg clk;

reg [7:0] sw;

wire [7:0] count;

wire [15:0] mult_res;

// S1 is the instance of simulation module

mult_sim S1(

.rst (rst),

.inclk (clk),

.sw (sw),

.count (count),

.mult_res (mult_res)

);

// Define the clock required for the simulation and display the results in text form

always begin

#10 clk = ~clk;

$monitor (“%d * %d = %d”, count, sw, mult_res);

end

//Set the simulation condition

initial begin

rst = 0;

clk = 1;

 

#10 sw = 20;

#10 sw = 50;

#10 sw = 100;

#10 sw = 101;

#10 sw = 102;

#10 sw = 103;

#10 sw = 104;

#50 sw = 105;

//Stop the signal

#1000 $stop;

end

endmodule

When writing the testbench file, first mark the time unit of the simulation at the beginning, this experiment is 1 ns, then instantiate the project that needs to be simulated into the testbench file, define the clock cycle and the simulation conditions, and stop the simulation after a certain time. This simulation stops after 1000 clock cycles.

After the compilation, the testbench file is added to the ModelSim for simulation, the specific steps are as follows:

  1. Set the testbench file: Assignments > Settings. See Figure 6.18.

Figure 6.18 Simulation setting 1

  1. In Compile test bench, click Test Benches to add tb simulation file. See Figure 6.19.

Figure 6.19 Simulation setting 2

  1. Click New, input the Test bench name. Make the name be consistent with tb file. See Figure 6. 20.

Figure 6.20 Simulation setting 3

  1. Click the red ellipse to add the test bench file. Find tb_mult.v file written before.
  2. Click Add to add the file. Click OK (three times) to finish the setting. See Figure 6.21.

Figure 6.21 Simulation setting 4

Repeat previous step, to start ModelSim to simulate. See Figure 6.22.

Figure 6.22 Waveform output

After a certain delay, outputs will display in Transcript. See Figure 6.23

Because the result of the operation will be one clock cycle later than the input, the multiplier and the result will differ by one line, which does not seem to match, but does not affect the analysis of the experimental results.

Figure 6.23 Text displays operation result

Summary and Reflection

Try to use the switch as the input to the multiplier. The upper four digits are one number, the lower fourth digits are a number, and the two numbers are multiplied to output the result.

Experiment 7 Hexadecimal Number to BCD Code Conversion and Application

Experiment Objective

  1. Learn to convert binary numbers to BCD code (bin_to_bcd)
  2. Learn to convert hexadecimal numbers to BCD code (hex_to_bcd)

7.2 Experiment Implement

Combined with experiment 6, display the results of the operation to the segment display.

7.3 Experiment

7.2.1 Introduction to the Principle of Converting Hexadecimal Number to BCD Code

Since the hexadecimal display is not intuitive, decimal display is more widely used in real life.

Human eyes recognition is relatively slow, so the display from hexadecimal to decimal does not need to be too fast. Generally, there are two methods

  1. Countdown method:

Under the control of the synchronous clock, the hexadecimal number is decremented by 1 until it is reduced to 0. At the same time, the appropriate BCD code decimal counter is designed to increment. When the hexadecimal number is reduced to 0, the BCD counter Just gets with the same value to display.

  1. Bitwise operations (specifically, shift bits and plus 3 here). The implementation is as follows:
  2. Set the maximum decimal value of the expression. Suppose a 16-digit binary value (4-digit hexadecimal) needs to be converted to decimal. The maximum value can be expressed as 65535. Firstly five four-digit binary units are defined: ten thousand, thousand, hundred, ten, and one to accommodate calculation results
  3. Shift the hexadecimal number by one to the left, and put the removed part into the defined variable, and judge whether the units of ten thousand, thousand, hundred, ten, and one are greater than or equal to 5, and if so, add the corresponding bit to 3 until the 16-bit shift is completed, and the corresponding result is obtained.

Note: Do not add 3 when moving to the last digit, put the operation result directly

  1. The principle of hexadecimal number to BCD number conversion

Suppose ABCD is a 4-digit binary number (possibly ones, 10 or 100 bits, etc.), adjusts it to BCD code. Since the entire calculation is implemented in successive shifts, ABCDE is obtained after shifting one bit (E is from low displacement and its value is either 0 or 1). At this time, it should be judged whether the value is greater than or equal to 10. If so, the value is increased by 6 to adjust it to within 10, and the carry is shifted to the upper 4-bit BCD code. Here, the pre-movement adjustment is used to first determine whether ABCD is greater than or equal to 5 (half of 10), and if it is greater than 5, add 3 (half of 6) and then shift

For example, ABCD = 0110 (decimal 6)

  1. After shifting it becomes 1100 (12), greater than 1001 (decimal 9)
  2. By plus 0110 (decimal 6), ABCD = 0010, carry position is 1, the result is expressed as decimal 12
  3. Use pre-shift adjustment, ABCD = 0110 (6), greater than 5, plus 3
  4. ABCD = 1001 (9), shift left by one
  5. ABCD = 0010, the shifted bit is the lowest bit of the high four-bit BCD.
  6. Since the shifted bit is 1, ABCD = 0010(2), the result is also 12 in decimal.
  7. The two results are the same
  8. Firstly, make a judgement, and then add 3 and shift. If there are multiple BCD codes at the same time, then multiple BCD numbers all must first determine whether need to add 2 and then shift.
  9. The first way is relatively easy. Here, the second method is mainly introduced.

Example 1: Binary to BCD. See Figure 7.1.

IMG_256

Figure 7.1 Example 1, bin_to_bcd

Example 2: Hexadecimal to BCD. See Figure 7.2.

IMG_256

Figure 7.2 hex_to_bcd

7.2.2 Introduction of the Program

The first step: the establishment of the main program framework

module HEX_BCD (

 

input [15:0] hex,

output reg [3:0] ones,

output reg [3:0] tens,

output reg [3:0] hundreds,

output reg [3:0] thousands,

output reg [3:0] ten_thousands

);

 

Enter a 16-bit binary number hex, which can represent a maximum of 65535 decimal, so output ones, tens, hundreds, thousands, and ten_thousands.

The second step: the implementation of bit operation

reg [15:0] hex_reg;

integer i;

always @ (*)

begin

hex_reg = hex;

ones = 0;

tens = 0;

hundreds = 0;

thousands = 0;

ten_thousands = 0;

 

for (i = 15; i >= 0; i = i-1) begin

if(ten_thousands >= 5)

ten_thousands = ten_thousands + 3;

if(thousands >= 5)

thousands = thousands + 3;

if(hundreds >= 5)

hundreds = hundreds + 3;

if(tens >= 5)

tens = tens + 3;

if(ones >= 5)

ones = ones + 3;

ten_thousands = ten_thousands << 1;

ten_thousands[0] = thousands[3];

thousands = thousands << 1;

thousands[0] = hundreds[3];

hundreds = hundreds << 1;

hundreds[0] = tens[3];

tens = tens << 1;

tens[0]= ones[3];

ones = ones << 1;

ones[0] = hex_reg[15];

hex_reg = {hex_reg[14:0], 1’b0};

end

end

Referring to Figure 7.2, the former part of the program is the judgment calculation part, and if it is greater than or equal to 5, then adds 3. The latter part is the shift part.

The third step: verification

Referring to Experiment 6, simulation was performed using ModelSim, and the simulation conditions are set as follows:

initial begin

hex = 0 ;

repeat (20) begin

#10;

hex = {$random}%20000;

#10;

end

end

At the beginning, the 16-bit binary number is equal to 0. The delay is 10 ns. The 16-bit binary number takes a random number less than 20,000. A delay of 10 ns is applied and the process is repeated 20 times.

After the ModelSim is set and the testbench file is added, perform the simulation. The result is shown in Figure 7.3.

Figure 7.3 Simulation for binary to decimal

Remark and reflection:

  1. The assignment symbols for the examples above are “=” instead of “<=”. Why?
  2. Since the whole program is designed to be combinational logic, when invoking the modules, the other modules should be synchronized the timing.

7.4 Application of Hexadecimal Number to BCD Number Conversion

  1. Continue to complete the multiplier of Experiment 6 and display the result on segment display in decimal. Every 1 second, the calculation results on the segment display changes once. The experiment needs to use frequency division, segment display, multiplier and hexadecimal number to BCD number conversion.
  2. Compilation. Observe the Timing Analyzer in Compilation Report.
  3. Fmax Summary 83.71 MHz. See Figure 7.4.

Figure 7.4 Fmax Summary

  1. Setup Memory

Figure 7.5 Setup time summary

  1. Timing Closure Recommendation. See Figure 7.6.

图7-6 Timing Analysis

  1. From the above three indicators, the above programming does not meet the timing requirements. It can also be seen that the maximum delay path is the delay of the output of the multiplier to HEX_BCD.

There are 3 solutions:

  1. Reduce the clock frequency
  2. Increase the timing of HEX_BCD and increase the pipeline
  3. Insert pipeline isolation at the periphery (can reduce some delay)

The way to increase the pipeline, will be introduced in the follow-up experiment, because the function of HEX_BCD is mainly used to display the human-machine interface, the speed requirement is low, and the frequency reduction method is adopted here.

  1. Modify PLL to increase an output of 20 MHz frequency (BCD_clk)
  2. Recompile and observe timing results
  3. Lock the pins, compile, and program FII-PRA040 development board for testing

7.5 Experiment Verification

The first step: pin assignment

See Table 7.1 for the pin assignment

Table 7.1 Hexadecimal to BCD number conversion pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 Input clock
rst KEY3 10 Reset
scan[5] SEG_3V3_D5 124 Bit selection 5
scan[4] SEG_3V3_D4 127 Bit selection 4
scan[3] SEG_3V3_D3 129 Bit selection 3
scan[2] SEG_3V3_D2 141 Bit selection 2
scan[1] SEG_3V3_D1 142 Bit selection 1
scan[0] SEG_3V3_D0 136 Bit selection 0
seven_seg[7] SEG_PA 128 Segment selection a
seven_seg[6] SEG_PB 135 Segment selection b
seven_seg[5] SEG_PC 138 Segment selection c
seven_seg[4] SEG_PD 126 Segment selection d
seven_seg[3] SEG_PE 125 Segment selection e
seven_seg[2] SEG_PF 133 Segment selection f
seven_seg[1] SEG_PG 137 Segment selection g
seven_seg[0] SEG_DP 132 Segment selection dp
SW[7] SW7_LED7 77 Switch 7
SW[6] SW6_LED6 76 Switch 6
SW[5] SW5_LED5 75 Switch 5
SW[4] SW4_LED4 74 Switch 4
SW[3] SW3_LED3 87 Switch 3
SW[2] SW2_LED2 86 Switch 2
SW[1] SW1_LED1 83 Switch 1
SW[0] SW0_LED0 80 Switch 0

The second step: development board verification

After the pin assignment is completed, the compilation is performed. Program the development board for verification after passing. The experimental result is shown in Figure 7.7. The value of the DIP switch input is 00001010, decimal 10, the counter is constantly accumulating, so the display result is always accumulatively changed by 10.

Figure 7.7 Experiment phenomenon

Experiment Summary and Reflection

  1. How to implement BCD using more than 16 bits binary numbers
  2. What is a synchronous clock and how to handle an asynchronous clock
  3. Learn to design circuits that meet timing requirements based on actual needs.

Experiment 8 Use of ROM

8.1 Experiment Objective

  1. Study the internal memory block of FPGA
  2. Study the format of *.mif and how to edit *.mif file to configure the contents of ROM
  3. Learn to use RAM, read and write RAM

8.2 Experiment Implement

  1. Design 16 outputs ROM, address ranging 0-255
  2. Interface 8-bit switch input as ROM’s address
  3. Segment display illustrates the contents of ROM and require conversion of hexadecimal to BCD output.

8.3 Experiment

8.3.1 Introduction to Program

This experiment was carried out on the basis of Experiment 7, and the contents of Experiment 7 were cited, so only the IP core ROM portion is introduced here.

  1. In Installed IP, choose Library > Basic Function > On Chip Memory > ROM: 1-PORT, file type to be Verilog HDL. Choose 16 bits and 256 words for output. See Figure 8.1.

Figure 8.1 RAM IP core invoking

  1. According to the default setting, an initial ROM file in the location where red oval circles needs to be added. See Figure 8.2. In the figure, a *.mif file has already been added.
  2. Create a top level entity rom.mif
  3. Generate rom.mif file. Go to File > New > Memory Files > Memory Initialization File. See Figure 8.3.
  4. In Figure 8.4, modify the Number of words and Word size.
  5. In Figure 8.5, in the address area, right click to input the data or change the display format, such as hexadecimal, octal, binary, unsigned, signed, etc

Figure 8.2 ROM setting

Figure 8.3 New *.mif file

Figure 8.4 *.mif file setting 1

Figure 8.5 *.mif file setting 2

  1. After completing the ROM and IP’s setting, fill the data for rom.mif. For convenience of verification, store the same data as the address from the lower byte to higher byte in ascending form. Right click to select Custom Fill Cells. See Figure 8.6. The starting address is 0, ending at 255 (previous address setting depth is 256). The initial value is 0 and the step is 1.

Figure 8.6 Fill date for rom.mif

  1. After the setup, the system will fill in the data automatically. See Figure 8.7.

Figure 8.7 Part of data after auto filling

  1. Refer to the design of conversion from hexadecimal to BCD in Experiment 7, the data rom_q in the ROM is synchronized by the primary register and displayed on the segment display.

ROM instantiation:

reg [15:0] rom_q_r;

always @ (posedge BCD_clk)

rom_q_r<=rom_q;

HEX_BCD HEX_BCD_inst(

.hex (rom_q_r),

.ones (ones),

.tens (tens),

.hundreds (hundreds),

.thousands (thousands),

.ten_thousands (ten_thousands)

);

onep_rom onep_rom_dut(

.address (sw),

.clock (sys_clk),

.q (rom_q)

);

8.4 Experiment Verification

Pin assignments are consistent with Experiment 7. After the compilation is completed, the board is verified. As shown in Figure 8.8. When the DIP switch is 10010100, the decimal expression is 148, which means the contents of the 148th byte of the ROM is read, and the segment display will illustrate 148, which is consistent with the data deposited before.

Figure 8.8 Experiment phenomenon

Experiment Summary and Reflection

  1. How to use the initial file of ROM to realize the decode, such as decoding and scanning the segment display.
  2. Write a *.mif file to generate sine, cosine wave, and other function generators.
  3. Comprehend application, combine the characteristic of ROM and PWM to form SPWM modulation waveform.

Experiment 9 Use Dual_port RAM to Read and Write Frame Data

9.1 Experiment Objective

  1. Learn to configure and use dual-port RAM
  2. Learn to use synchronous clock to control the synchronization of frame structure
  3. Learn to use asynchronous clock to control the synchronization of frame structure

Experiment Implement

  1. Observing the synchronization structure of synchronous clock frames using SignalTap II
  2. Extended the use of dual-port RAM
  3. Design the use of three-stage state machine
  4. Design a 16-bit data frame
  5. Data is generated by an 8-bit counter: Data={~counta,counta}
  6. The ID of the data frame inputted by the switch (7 bits express maximum of 128 different data frames)
  7. 16-bit checksum provides data verification
  8. 16-bit checksum accumulates, discarding the carry bit
  9. After the checksum is complemented, append to the frame data
  10. Provide configurable data length data_len by parameter
  11. Packet: When the data and checksum package are written to the dual-port RAM, the userID, the frame length and the valid flag are written to the specific location of the dual-port RAM. The structure of the memory is shown in Table 9.1.
Wr_addr Data/Flag Rd_addr
8’hff {valid,ID,data_len} 8’hff
N/A
8’hnn+2 N/A 8’hnn+2
8’hnn+1 ~checksum+1 8’hnn+1
8’hnn datann 8’hnn
….
8’h01 Data1 8’h01
8’h00 Data0 8’h00

表1 memory结构

  1. Read and write in an agreed order

Valid is the handshake signal. This flag provides the possibility of read and write synchronization, so the accuracy of this signal must be ensured in the program design.

9.3 Experiment

9.3.1 Introduction of the Program

The first step: the establishment of the main program framework

module frame_ram

#(parameter data_len=250)

(

input inclk,

input rst,

input [6:0] sw,

output reg [6:0] oID,

output reg rd_done,

output reg rd_err

);

The second step: the definition of the state machine

parameter [2:0] mema_idle=0,

mema_init=1,

mema_pipe0=2,

mema_read0=3,

mema_read1=4,

mema_wr_data=5,

mema_wr_chsum=6,

mema_wr_done=7;

parameter [2:0] memb_idle=0,

memb_init=1,

memb_pipe0=2,

memb_read0=3,

memb_read1=4,

memb_rd_data=5,

memb_rd_chsum=6,

memb_rd_done=7;

The third step: other definitions

Clock variable definition

wire sys_clk;

wire BCD_clk;

wire sys_rst;

reg ext_clk;

Dual-port RAM interface definition

reg [7:0] addr_a;

reg [15:0] data_a;

reg wren_a;

wire [15:0] q_a;

reg [7:0] addr_b;

reg wren_b;

wire [15:0] q_b;

Write state machine part variable definition

reg [6:0] user_id;

reg [7:0] wr_len;

reg [15:0] wr_chsum;

wire wr_done;

reg [7:0] counta;

wire [7:0] countb;

assign countb=~counta;

reg [15:0] rd_chsum;

reg [7:0] rd_len;

reg [15:0] rd_data;

reg ext_rst;

reg [2:0] sta;

reg [2:0] sta_nxt,;

Read state machine part variable definition

reg [15:0] rd_chsum;

reg [7:0] rd_len;

reg [15:0] rd_data;

reg [2:0] stb;

reg [2:0] stb_nxt;

The fourth step: generate dual-port RAM, PLL

dp_ram dp_ram_inst

(

.address_a (addr_a),

.address_b (addr_b),

.clock (sys_clk),

.data_a (data_a),

.data_b (16’b0),

.wren_a (wren_a),

.wren_b (wren_b),

.q_a (q_a),

.q_b (q_b)

);

pll_sys_rst pll_sys_rst_inst

(

.inclk (inclk),

.sys_clk (sys_clk),

.BCD_clk (BCD_clk),

.sys_rst (sys_rst)

);

The RAM is 16 bits wide and 256 depth. The PLL inputs a 50 MHz clock, outputs 100 MHz as the operating clock of other modules, and 20 MHz is used to drive the segment display.

The fifth step: data generation counter

always @ (posedge sys_clk)

if(sys_rst) begin

counta <= 0;

user_id <= 0;

end

else begin

counta <=counta + 1;

user_id <= sw;

end

The sixth step: write state machine

assign wr_done = (wr_len == (data_len – 1’b1));

//Think why using wr_len==data_len-1, instaed of wr_len==data_len

//First stage

always @ (posedge sys_clk)

begin

if (sys_rst) begin

sta = mema_idle;

end

else

sta = sta_nxt;

end

//Second stage

always @ (*)

begin

case (sta)

mema_idle : sta_nxt = mema_init;

mema_init : sta_nxt = mema_pipe0;

mema_pipe0 : sta_nxt = mema_read0;

mema_read0 :

begin

if (!q_a[15])

sta_nxt = mema_read1;

else

sta_nxt = sta;

end

mema_read1 :

begin

if (!q_a[15])

sta_nxt = mema_wr_data;

else

sta_nxt = sta;

end

mema_wr_data :

begin

if (wr_done)

sta_nxt = mema_wr_chsum;

else

sta_nxt = sta;

end

mema_wr_chsum : sta_nxt = mema_wr_done;

mema_wr_done : sta_nxt = mema_init;

default : sta_nxt = mema_idle;

endcase

end

//Third stage

always @ (posedge sys_clk)

begin

case (sta)

mema_idle :

begin

addr_a <= 8’hff;

wren_a <= 1’b0;

data_a <= 16’b0;

wr_len <= 8’b0;

wr_chsum <= 0;

end

mema_init, mema_pipe0, mema_read0, mema_read1 :

begin

addr_a <= 8’hff;

wren_a <= 1’b0;

data_a <= 16’b0;

wr_len <= 8’b0;

wr_chsum <= 0;

end

mema_wr_data :

begin

addr_a <= addr_a + 1’b1;

wren_a <= 1’b1;

data_a <= {countb, counta};

wr_len <= wr_len + 1’b1;

wr_chsum <= wr_chsum + {countb, counta};

end

mema_wr_chsum :

begin

addr_a <= addr_a + 1’b1;

wr_len <= wr_len + 1’b1;

wren_a <= 1’b1;

data_a <= (~wr_chsum) + 1’b1;

end

mema_wr_done :

begin

addr_a <= 8’hff;

wren_a <= 1’b1;

data_a <= {1’b1, user_id, wr_len};

end

default : ;

endcase

end

Write order:

  1. Read the flag of the 8’hff address (control word). If valid=1’b0, the program proceeds to the next step, otherwise waits
  2. Address plus 1, 8’hff+1 is exactly zero, write data from 0 address and calculate the checksum
  3. Determine whether the predetermined data length is reached. If so, proceeds to next step, otherwise continue writing data, and the checksum is calculated.
  4. checksum complements and write to memory
  5. Write the control word in the address 8’hff, packet it

The seventh step: read state machine

//First stage

always @ (posedge sys_clk)

begin

if (ext_rst) begin

stb = memb_idle;

end

else

stb = stb_nxt;

end

//Second stage

always @ (*)

begin

case (stb)

memb_idle : stb_nxt = memb_init;

memb_init : stb_nxt = memb_pipe0;

memb_pipe0 : stb_nxt = memb_read0;

memb_read0 :

begin

if (q_b[15])

stb_nxt = memb_read1;

else

stb_nxt = memb_init;

end

memb_read1 :

begin

if (q_b[15])

stb_nxt = memb_rd_data;

else

stb_nxt = memb_init;

end

memb_rd_data :

begin

if(rd_done)

stb_nxt = memb_rd_chsum;

else

stb_nxt = stb;

end

memb_rd_chsum : stb_nxt = memb_rd_done;

 

memb_rd_done : stb_nxt = memb_init;

default : stb_nxt = memb_idle;

endcase

end

// Third stage, the actual operation needs to be driven by the edge of the clock.

always @ (posedge sys_clk)

begin

case (stb)

memb_idle :

begin

addr_b <= 8’hff;

rd_data <= 0;

rd_chsum <= 0;

wren_b <= 1’b0;

rd_len <= 8’b0;

oID <= 7’b0;

rd_err <= 1’b0;

end

memb_init :

begin

addr_b <= 8’hff;

rd_data <= 0;

rd_chsum <= 0;

wren_b <= 1’b0;

rd_len <= 8’b0;

oID <= 7’b0;

rd_err <= 1’b0;

end

memb_pipe0 :

begin

addr_b <= 8’b0;

end

memb_read0 :

begin

if (q_b[15])

addr_b <= addr_b + 1’b1;

else

addr_b <= 8’hff;

rd_data <= 0;

rd_chsum <= 0;

wren_b <= 1’b0;

rd_len <= 8’b0;

oID <= 7’b0;

end

memb_read1 :

begin

if(q_b[15])

addr_b <= addr_b + 1’b1;

else

addr_b <= 8’hff;

rd_data <= 0;

rd_chsum <= 0;

wren_b <= 1’b0;

rd_len <= q_b[7:0];

oID <= q_b[14:8];

end

memb_rd_data :

begin

addr_b <= addr_b + 1’b1;

rd_data <= q_b;

rd_chsum <= rd_chsum + rd_data;

wren_b <= 1’b0;

rd_len <= rd_len – 1’b1;

end

memb_rd_chsum :

begin

addr_b <= 8’hff;

wren_b <= 1’b0;

if (|rd_chsum)

rd_err <= 1’b1;

end

memb_rd_done :

begin

addr_b <= 8’hff;

wren_b <= 1’b1;

end

default : ;

endcase

end

Read order

  1. Idle is the state after reset
  2. Init: Initialization, set the address to 8’hff
  3. Rd_pipe0: Add a latency (since the read address and data are both latched). Address +1, forming a pipeline structure
  4. Read0: Set the address to 8’hff, read the control word and judge whether the valid bit is valid.
  5. If valid=1’b1, address +1, proceeds to the next step
  6. If valid=1’b0, it means the packet is not ready yet, the address is set to be 8’hff and returns to the init state.
  7. Read1: read the contro word again
  8. If valid=1’b1, address+1, ID and data length are assigned to the corresponding variables and proceeds to the next step
  9. If valid=1’b0, it means the packet is not ready yet, the address is set to 8’hff, and returns to the init state.
  10. Rd_data:
  11. Read data and pass to data variables
  12. Calculate checksum, data_len – 1
  13. Determine whether the data_len is 0
  14. 0: all data has been read, proceeds to the next step
  15. Not 0: continue the operation in current state
  16. rd_chsum: Read the value of checksum and calculate the last checksum. Correct the data and set the flag of rd_err
  17. rd_done: The last step clears the valid flag in memory and opens the write enable for the next packet

Experiment Verification

The first step: pin assignment

See Table 9.2 for the pin assignment.

Table 9.2 Frame data read and write experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
Inclk C10_50MCLK 91 Input clock
rst KEY2 10 Reset signal
sw[6] SW6_LED6 76 7-digit DIP switch

(address input)

sw[5] SW5_LED5 75
sw[4] SW4_LED4 74
sw[3] SW3_LED3 87
sw[2] SW2_LED2 86
sw[1] SW1_LED1 83
sw[0] SW0_LED0 80

The second step: observe the read and write results of the dual-port RAM with SignalTap

  1. In order to facilitate the observation of the read and write state machine synergy results, the data length is changed to 4 here and recompile.Users can test themselves using long data.
module frame_ram

#(parameter data_len=4)

(

input inclk,

input rst,

input [6:0] sw,

output reg [6:0] oID,

output reg rd_done,

output reg rd_err

);

  1. Observe the simulation result
  2. Observe the handshake mechanism through dual-port RAM
  3. Determine whether the reading is started after the packet is written
  4. Determine whether the write packet is blocked before reading the entire packet is completed
  5. Observe the external interface signal and status
  6. rd_done, rd_err

Set rd_err = 1, or the rising edge is the trigger signal to observe whether the error signal is captured.

  1. Observe whether wren_a, wren_b signal and the state machine jump are strictly matched to meet the design requirements.
  2. SignalTap result. See Figure 9.1.

Figure 9.1 SignalTap II simulation

Experiment Summary and Reflection

  1. Review the design requirements of how to analyze an actual demand, to gradually establish a model of digital control and state machine and finally design it.
  2. Modify the third stage of the state machine into the if…else model and implement.
  3. Focus on thinking If the read and write clocks are different. After it becomes an asynchronous mechanism, how to control the handshake protocol.
  4. According to the above example, consider how dual-port RAM can be used in data acquisition, asynchronous communication, embedded CPU interface, and DSP chip interface.
  5. How to build ITCM with dual-port RAM and DTCM preparing for future CPU design.

Experiment 10 Asynchronous Serial Port Design and Experiment

10.1 Experiment Objective

Because asynchronous serial ports are very common in industrial control, communication, and software debugging, they are also vital in FPGA development.

  1. Study the basic principles of asynchronous serial port communication, handshake mechanism and data frame strcuture
  2. Master asynchronous sampling techniques
  3. Review the frame structure of the data packet
  4. Learn to use FIFO
  5. Joint debugging with common debugging software of PC (SSCOM, Tera Term, etc.)

10.2 Experiment Implement

  1. Design and transmit full-duplex asynchronous communication interface Tx, Rx
  2. Baud rate of 11520 bps, 8-bit data, 1 start bit, 1 or 2 stop bits
  3. Receive buffer (Rx FIFO), transmit buffer (Tx FIFO)
  4. Forming a data packet
  5. Packet parsing

10.3 Experiment

10.3.1 Inrtroduction of USB to Serial Conversion Chip (FT2232)

USB is an interface technology used in the PC field to regulate the connection and communication between computers and external devices. The USB interface supports plug-and-play and hot-swap capabilities for devices and connects up to 127 peripherals such as mice, modems and keyboards. However, there are still a large number of peripheral devices and software using the RS232 serial port standard. In order to fully utilize the advantages of USB, a USB-RS232 converter is designed to transmit RS232 data through the USB bus. Here is a design scheme of USB-RS232 conversion module based on FT2-232H.

The onboard serial port conversion chip is FT2232, which can realize USB to two serial UART, FIFO, Bit-Bang I/O interface, and can also be configured as MPSSE, I2C, JTAG and SPI bus. The FT2232H has two independent UART/FIFO controllers for controlling asynchronous data, 245 FIFO data, opto-isolated (high-speed serial) or controlling Bit-Bang mode when installing program commands; USB protocol engine controlling and managing the interface between UTMI PHY and FIFO. It is also responsible for power management and USB protocol specifications; the dual port FIFO TX buffer (4KB) stores data from the host PC and uses data from the multipurpose UART, FIFO controller; dual port FIFO RX buffer (4KB) Stores data from the multipurpose UART/FOFO controller and then sends the data to the host; the reset generator module provides a reliable power reset for the internal circuitry of the device when powered up. The RESETn input pin allows the external device to reset the FT2232H. If RESETn is not used, it should be connected to VCCIO (+3.3 V); the independent baud rate generator provides a ×16 or ×10 clock signal to the UART. The optimum baud rate tuning is provided by a 14-bit scale factor and 4 register bits to determine the baud rate of the UART programmable settings.

10.3.2 Hardware Design

Figure 10.1 Schematics of the serial port

The schematics of USB serial port conversion is shown in Figure 10.1. J2 is a USB interface. When downloading the program, the two lines of USB_N and USB_P are input to the FT2232, and are internally processed and input into the FPGA by JTAG_TXD_O. In the serial port experiment, the transmission path from the PC end to the FPGA end is consistent with the download procedure. The FPGA to PC receive path is the FPGA transmits the data from JTAG_RXD_I to the FT2232, and is internally processed and then sent to the PC through the USB interface to implement serial receive and transmit functions.

10.3.3 Introduction to the Program

The first step: the main program architecture

module uart_top

(

input inclk,

input rst,

input [1:0] baud_sel,

input tx_wren,

input tx_ctrl,

input [7:0] tx_data,

input tx_done,

output txbuf_rdy,

 

input rx_rden,

output [7:0] rx_byte,

output rx_byte_rdy,

output sys_rst,

output sys_clk,

input rx_in,

output tx_out

);

There are a lot of handshake signals here, with the tx prefix for the transmit part of the signal, and the rx prefix is for the receive part of the signal.

The second step: create a new baud rate generator file

  1. Input clock 7.3728MHz (64 times 115200). The actual value is 7.377049 MHz, which is because the coefficient of the PLL is an integer division, while the error caused by that is not large, and can be adjusted by the stop bit in asynchronous communication. See Figure 10.2.

Fine solution

  1. Implemented with a two-stage PLL for a finer frequency
  2. The stop bit is set to be 2 bits, which can effectively eliminate the error.

This experiment will not deal with the precision. The default input frequency is 7.3728 MHz.

Figure 10.2 PLL setting

  1. Supported baud rates are 115200,57600,38400,19200
  2. The default baud rate is 115200
  3. Source file of designing baud rate
//Transmit baud rate, clock frequency division selection

wire [8:0] frq_div_tx;

assign frq_div_tx = (baud_sel == 2’b00) ? 9’d63:

(baud_sel == 2’b01) ? 9’d127:

(baud_sel == 2’b10) ? 9’d255:9’d511;

reg [8:0] count_tx=9’d0;

always @ (posedge inclk)

if (rst) begin

count_tx <= 9’d0;

baud_tx <= 1’b0;

end

else begin

if (count_tx == frq_div_tx) begin

count_tx <= 9’d0;

baud_tx <= 1’b1;

end

else begin

count_tx <= count_tx + 1’b1;

baud_tx <= 1’b0;

end

end

Four different gear positions are set to select the baud rate, corresponding to the second step, (1). The baud rate of the receiving part is consistent to that of the transmitting part.

The third step: design the transmit buffer file tx_buf

  1. 8-bit FIFO, depth is 256, read/write clock separation, write full flag, read empty flag
  2. Interface and handshake
  3. rst reset signal
  4. wr_clk write clock
  5. tx_clk transmit clock
  6. 8-bit write data tx_data
  7. wr_en write enable
  8. ctrl writes whether the input is a data or a control word
  9. rdy buffer ready, can accept the next data frame

Transmit buffer instantiation file

tx_buf

#(.TX_BIT_LEN(8),.STOP_BIT(2))

tx_buf_inst

(

.sys_rst (sys_rst),

.uart_rst (uart_rst),

.wr_clk (sys_clk),

.tx_clk (uart_clk),

.tx_baud (tx_baud),

.tx_wren (tx_wren),

.tx_ctrl (tx_ctrl),

.tx_datain (tx_data),

.tx_done (tx_done),

.txbuf_rdy (txbuf_rdy),

.tx_out (tx_out)

);

  1. Serial transmission, interface and handshake file design
  2. Interface design
  3. tx_rdy, send vacancy, can accept new 8-bit data
  4. tx_en, send data enable, pass to the sending module 8-bit data enable signal
  5. tx_data, 8-bit data to be sent
  6. tx_clk, send clock
  7. tx_baud, send baud rate
  8. Instantiation
tx_transmit

#(.DATA_LEN(TX_BIT_LEN),

.STOP_BIT(STOP_BIT)

)

tx_transmit_inst

(

.tx_rst (uart_rst),

.tx_clk (tx_clk),

.tx_baud (tx_baud),

.tx_en (tx_en),

.tx_data (tx_data),

.tx_rdy (trans_rdy),

.tx_out (tx_out)

);

  1. Write a testbench file to simulate the transmit module. (tb_uart)
  2. ModelSim simulation waveforms for transmit module. See Figure 10.3.

Figure 10.3 Serial port transmit ModelSim waveform

  1. Extended design (extended content is only reserved for users to think and practice)
  2. Design the transmitter to support 5, 6, 7, 8-bit PHY (Port physical layer)
  3. Support parity check
  4. The settings of the above steps involve FIFO, PLL, etc. (Refer to uart_top project file)

The fourth step: UART receiving module design

  1. Desigbn of rx_phy.v
  2. Design strategies and steps
  3. Use 8 times sampling: so rx_baud is different from tx_baud, here sampling is rx_band = 8*tx_band
  4. Adopting judgments to the receiving data

Determine whether the data counter is greater than 4 after the sampling value is counted.

  1. Steps to receive data:
  2. Synchronization: refers to how to find the start bit from the received binary data e.g. 0101 (sync_dtc)
  3. Receive start bit (start)
  4. Cyclically receive 8-bit data
  5. Receive stop bit (determine whether it is one stop bit or two stop bits)
  6. Determine if the stop bit is correct
  7. Correct, jump to step B
  8. Incorrect, jump to step A, resynchronize
  9. Do not judge, jump directly to B, this design adopts the scheme of no judgment
  10. Design of rx_buf
  11. Design strategies and steps
  12. Add 256 depth, 8-bit fifo
  13. Read and write clock separation
  14. Asynchronous clear (internal synchronization)
  15. Data appears before the rdreq in the read port
  16. Steps:
  17. Initialization: fifo, rx_phy
  18. Wait: FIFO full signal (wrfull) is 0
  19. Write: Triggered by rx_phy_byte, rx_phy_rdy of rx_phy:
  20. End of writing
  21. Back to step b and continue to wait
  22. rx_buf.v source program (Reference to project files)
  23. Receive module simulation

Contents and steps

  1. tx, rx loopback test (assign rx_in = tx_out)
  2. Continue to use the testbench file in the tx section
  3. Write the testbench of rx
  4. ModelSim simulation. See Figure 10.4.

Figure 10.4 rx_phy waveform

  1. Reflection and development
  2. Modify the program to complete the 5, 6, 7, 8-bit design
  3. Completing the design of the resynchronization when the start and stop have errors of the receiving end rx_phy
  4. Complete the analysis and packaging of the receiving data frame of rx_buf
  5. Using multi-sampling to design 180° alignment data sampling method, compare FPGA resources, timing and data recovery effects

10.4 Experiment Verification

  1. Hardware interface, FII-PRA006/010 development board has intergrated USB to serial port conversion

USB to UART Conversion

TXD

USB

J2

RXD

  1. See Table 10.1 for the FPGA and UART pin assignment.

Table 10.1 FPGA and UART pin mapping

UART Name RXD TXD
Network Label JTAG_TXD_O JTAG_RXD_I
FPGA Pin 144 143
  1. Write a hardware test file
  2. Test plan: connect development board J2 to host USB interface
  3. Using test software such as Tera Term, SSCOM3, etc., you can also write a serial communication program (C#, C++, JAVA, Python…)
  4. PC sends data in a certain format
  5. The test end uses a counter to generate data in a certain format.
  6. Write the test program hw_tb_uart and instantiate uart_top in it.
  7. 将此程序设为顶层,例化之前的程序,即可下板验证。Set hw_tb_uart to the top level, instantiate the previous program, and then verify it
  8. Pin assignments:

The pin assignment is shown in Tabel 10.2.

Table 10.2 Serial port experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
Inclk C10_50MCLK 91 Input clock
rst KEY2 10 Reset
rx_in TAG_RXD_I 144 Serial data received
tx_out TAG_TXD_O 143 Serial data transmitted
  1. Observe the experiment result
  2. Observe the data received by the PC. See in Figure 10.5.
  3. Observe the data received by the FPGA with SignalTap II

Figure 10.5 Data transmitted by FPGA displayed on the host computer

  1. The receiving part has been skipped here. It is encouraged to try it personaly.

Experiment 11 IIC transmitting Experiment

11.1 Experiment Objective

  1. Learning the basic principles of asynchronous IIC bus, and the IIC communication protocol
  2. Master the method of reading and writing EEPROM
  3. Joint debugging using logic analyzer

11.2 Experiment Implement

  1. Correctly write a number to any address in the EEPROM (this experiment writes to the register of 8’h03 address) through the FPGA (here changes the written 8-bit data value by (SW7~SW0)). After writing in successfully, read the data as well. The read data is displayed directly on the segment display.
  2. Program the FPGA and press the LEFT push button to execute the data write into EEPROM operation. Press the RIGHT push button to read the data that was just written.
  3. Determine whether it is correct or not by reading the displayed number on the segment display. If the segment display has the same value as written value, the experiment is successful.
  4. Analyze the correctness of the internal data with SignalTap II and verify it with the illustration of the segment display.

11.3 Experiment

11.3.1 Introduction to EEPROM and IIC Protocol

  1. Introduction of EEPROM

EEPROM (Electrically Erasable Programmable Read Only Memory) refers to a charged erasable programmable read only register. It is a memory chip that does not lose data after turning off power.

On the experiment board, there is an IIC interface EEPROM chip 24LC02 with a capacity of 256 bytes. Users can store some hardware configuration data or user information due to the characteristics that the data is not lost after power-off.

  1. The overall timing protocol of IIC is as follows
  2. Bus idle state: SDA, SCL are high
  3. Start of IIC protocol: SCL stays high, SDA jumps from high level to low level, generating a start signal
  4. IIC read and write data stage: including serial input and output of data and response signal issued by data receiver
  5. IIC transmission end bit: SCL is in high level, SDA jumps from low level to high level, and generates an end flag. See Figure 11.1.
  6. SDA must remain unchanged when SCL is high. It changes only when SCL is low

Figure 11.1 Timing protocol of IIC

11.3.2 Hardware Introduction

Each IIC device has a device address. When some device addresses are shipped from the factory, they are fixed by the manufacturer (the specific data can be found in the manufacturer’s data sheet). Some of their higher bits are determined, and the lower bits can be configured by the user according to the requirement. The higher four-bit address of the EEPROM chip 24LC02 used by the develop board has been fixed to 1010 by the component manufacturer. The lower three bits are linked in the develop board as shown below, so the device address is 1010000. See Figure 11.2.

Figure 11.2 EEPROM schematics of IIC device

EEPROM reads and writes data from the FPGA through the I2C_SCL clock line and the I2C_SDA data line.

11.3.3 Introduction to the Program

This experiment has two main modules, IIC reading and writing module and LED display module; The first module is mainly introduced here.

The first step: establishment of the main program framework

module iic_com(

input clk,

input rst,

input [7:0] data,

input sw1,sw2,

inout scl,

inout sda,

output reg iic_done,

output [7:0] dis_data

);

The input 8-bit data is needed to be written into the EEPROM, provided by an 8-bit DIP switch.

The second step : Create clock I2C_CLK

reg [2:0] cnt;

reg [8:0] cnt_delay;

reg scl_r;

reg scl_link ;

always @ (posedge clk or posedge rst)

begin

if (rst)

cnt_delay <= 9’d0;

else if (cnt_delay == 9’d499)

cnt_delay <= 9’d0;

else

cnt_delay <= cnt_delay + 1’b1;

end

always @ (posedge clk or posedge rst)

begin

if (rst)

cnt <= 3’d5;

else begin

case (cnt_delay)

9’d124: cnt <= 3’d1; //cnt=1:scl

9’d249: cnt <= 3’d2; //cnt=2:scl

9’d374: cnt <= 3’d3; //cnt=3:scl

9’d499: cnt <= 3’d0; //cnt=0:scl

default: cnt<=3’d5;

endcase

end

end

`define SCL_POS (cnt==3’d0) //cnt=0:scl

`define SCL_HIG (cnt==3’d1) //cnt=1:scl

`define SCL_NEG (cnt==3’d2) //cnt=2:scl

`define SCL_LOW (cnt==3’d3) //cnt=3:scl

always @ (posedge clk or posedge rst)

begin

if (rst)

scl_r <= 1’b0;

else if (cnt == 3’d0)

scl_r <= 1’b1;

else if (cnt == 3’d2)

scl_r <= 1’b0;

end

assign scl = scl_link ? scl_r: 1’bz ;

First, use the system 50 MHz clock to get a 100 kHz clock with a period of 10us by frequency division as the transmission clock of the IIC protocol. Then, the rising edge, the high state, the falling edge and the low state of the clock are defined by the counter, prepared for the subsequent data reading and writing and the beginning of the IIC protocol. The last line of code means to define a data valid signal. Only when the signal is high, that is, when the data is valid, the IIC clock is valid again, otherwise it is in high impedance. This is also set according to the IIC transport protocol.

The third step: specific implementation of I2C transmission

`define DEVICE_READ 8’b1010_0001

`define DEVICE_WRITE 8’b1010_0000

`define BYTE_ADDR 8’b0000_0011

parameter IDLE = 4’d0;

parameter START1 = 4’d1;

parameter ADD1 = 4’d2;

parameter ACK1 = 4’d3;

parameter ADD2 = 4’d4;

parameter ACK2 = 4’d5;

parameter START2 = 4’d6;

parameter ADD3 = 4’d7;

parameter ACK3 = 4’d8;

parameter DATA = 4’d9;

parameter ACK4 = 4’d10;

parameter STOP1 = 4’d11;

parameter STOP2 = 4’d12;

reg [7:0] db_r;

reg [7:0] read_data;

reg [3:0] cstate;

reg sda_r;

reg sda_link;

reg [3:0] num;

always @ (posedge clk or posedge rst)

begin

if (rst) begin

cstate <= IDLE;

sda_r <= 1’b1;

scl_link <= 1’b1;

sda_link <= 1’b1;

num <= 4’d0;

read_data <= 8’b0000_0000;

cnt_5ms <= 20’h00000;

iic_done <= 1’b0;

end

else case (cstate)

IDLE :

begin

sda_link <= 1’b1;

scl_link <= 1’b1;

iic_done <= 1’b0 ;

if (sw1_r || sw2_r) begin

db_r <= `DEVICE_WRITE;

cstate <= START1;

end

else cstate <= IDLE;

end

START1 :

begin

if (`SCL_HIG) begin

sda_link <= 1’b1;

sda_r <= 1’b0;

num <= 4’d0;

cstate <= ADD1;

end

else cstate <= START1;

end

ADD1 :

begin

if (`SCL_LOW) begin

if (num == 4’d8) begin

num <= 4’d0;

sda_r <= 1’b1;

sda_link <= 1’b0;

cstate <= ACK1;

end

else begin

cstate <= ADD1;

num <= num + 1’b1;

case (num)

4’d0 : sda_r <= db_r[7];

4’d1 : sda_r <= db_r[6];

4’d2 : sda_r <= db_r[5];

4’d3 : sda_r <= db_r[4];

4’d4 : sda_r <= db_r[3];

4’d5 : sda_r <= db_r[2];

4’d6 : sda_r <= db_r[1];

4’d7 : sda_r <= db_r[0];

default : ;

endcase

end

end

else cstate <= ADD1;

end

ACK1 :

begin

if (`SCL_NEG) begin

cstate <= ADD2;

db_r <= `BYTE_ADDR;

end

else cstate <= ACK1;

end

ADD2 :

begin

if (`SCL_LOW) begin

if (num == 4’d8) begin

num <= 4’d0;

sda_r <= 1’b1;

sda_link <= 1’b0;

cstate <= ACK2;

end

else begin

sda_link <= 1’b1;

num <= num+1’b1;

case (num)

4’d0 : sda_r <= db_r[7];

4’d1 : sda_r <= db_r[6];

4’d2 : sda_r <= db_r[5];

4’d3 : sda_r <= db_r[4];

4’d4 : sda_r <= db_r[3];

4’d5 : sda_r <= db_r[2];

4’d6 : sda_r <= db_r[1];

4’d7 : sda_r <= db_r[0];

default : ;

endcase

cstate <= ADD2;

end

end

else cstate <= ADD2;

end

ACK2 :

begin

if (`SCL_NEG) begin

if (sw1_r) begin

cstate <= DATA;

db_r <= data_tep;

end

else if (sw2_r) begin

db_r <= `DEVICE_READ;

cstate <= START2;

end

end

else cstate <= ACK2;

end

START2 :

begin

if (`SCL_LOW) begin

sda_link <= 1’b1;

sda_r <= 1’b1;

cstate <= START2;

end

else if (`SCL_HIG) begin

sda_r <= 1’b0;

cstate <= ADD3;

end

else cstate <= START2;

end

ADD3 :

begin

if (`SCL_LOW) begin

if (num == 4’d8) begin

num <= 4’d0;

sda_r <= 1’b1;

sda_link <= 1’b0;

cstate <= ACK3;

end

else begin

num <= num + 1’b1;

case (num)

4’d0 : sda_r <= db_r[7];

4’d1 : sda_r <= db_r[6];

4’d2 : sda_r <= db_r[5];

4’d3 : sda_r <= db_r[4];

4’d4 : sda_r <= db_r[3];

4’d5 : sda_r <= db_r[2];

4’d6 : sda_r <= db_r[1];

4’d7 : sda_r <= db_r[0];

default: ;

endcase

end

end

else cstate <= ADD3;

end

ACK3 :

begin

if (`SCL_NEG) begin

cstate <= DATA;

sda_link <= 1’b0;

end

else cstate <= ACK3;

end

DATA :

begin

if (sw2_r) begin

if (num <= 4’d7) begin

cstate <= DATA;

if(`SCL_HIG) begin

num <= num + 1’b1;

case (num)

4’d0 : read_data[7] <= sda;

4’d1 : read_data[6] <= sda;

4’d2 : read_data[5] <= sda;

4’d3 : read_data[4] <= sda;

4’d4 : read_data[3] <= sda;

4’d5 : read_data[2] <= sda;

4’d6 : read_data[1] <= sda;

4’d7 : read_data[0] <= sda;

default: ;

endcase

end

end

else if((`SCL_LOW) && (num == 4’d8)) begin

num <= 4’d0;

cstate <= ACK4;

end

else cstate <= DATA;

end

else if (sw1_r) begin

sda_link <= 1’b1;

if (num <= 4’d7) begin

cstate <= DATA;

if (`SCL_LOW) begin

sda_link <= 1’b1;

num <= num + 1’b1;

case (num)

4’d0 : sda_r <= db_r[7];

4’d1 : sda_r <= db_r[6];

4’d2 : sda_r <= db_r[5];

4’d3 : sda_r <= db_r[4];

4’d4 : sda_r <= db_r[3];

4’d5 : sda_r <= db_r[2];

4’d6 : sda_r <= db_r[1];

4’d7 : sda_r <= db_r[0];

default: ;

endcase

end

end

else if ((`SCL_LOW) && (num==4’d8)) begin

num <= 4’d0;

sda_r <= 1’b1;

sda_link <= 1’b0;

cstate <= ACK4;

end

else cstate <= DATA;

end

end

ACK4 :

begin

if (`SCL_NEG)

cstate <= STOP1;

else

cstate <= ACK4;

end

STOP1 :

begin

if (`SCL_LOW) begin

sda_link <= 1’b1;

sda_r <= 1’b0;

cstate <= STOP1;

end

else if (`SCL_HIG) begin

sda_r <= 1’b1;

cstate <= STOP2;

end

else cstate <= STOP1;

end

STOP2 :

begin

if (`SCL_NEG) begin

sda_link <= 1’b0;

scl_link <= 1’b0;

end

else if (cnt_5ms==20’h3fffc) begin

cnt_5ms <= 20’h00000;

iic_done <= 1;

cstate <= IDLE;

end

else begin

cstate <= STOP2;

cnt_5ms <= cnt_5ms + 1’b1;

end

end

default: cstate <= IDLE;

endcase

end

The entire process is implemented using a state machine. When reset, it is idle state, while data line sda_r is pulled high, clock and data are both valid, i.e. scl_link, sda_link are high; counter num is cleared and read_data is 0. 5ms delay counter is cleared, IIC transmission end signal Iic_done is low thus invalid.

  1. IDLE state: When receiving the read enable or write enable signal sw1_r || sw2_r, assign the write control word to the intermediate variable db_r <= `DEVICE_WRITE, and jump to the start state START1;
  2. START1 state: pull the data line low when the clock signal is high, generating the start signal of IIC transmission, and jump to the device address state ADD1;
  3. Device address status ADD1: After the write control word (device address plus one ‘0’ bit) is transmitted according to MSB (high order priority), the sda_link is pulled low causing data bus in a high impedance state, and jump to the first response state ACK1, waiting for the response signal from the slave (EEPROM).
  4. The first response status ACK1: If the data line is pulled low, it proves that the slave receives the data normally, otherwise the data is not written into EEPROM, and then the rewriting or stopping is decided by the user. There is no temporary judgment and processing here, jump directly to the write register address state ADD2, and assign the address BYTE_ADDR written to the intermediate variable (this experiment writes the data into the third register, i.e. BYTE_ADDR = 0000_0011 )
  5. Register address status ADD2: Same as (3), it transfers register address to slave and jump to second response status ACK2
  6. The second response state ACK2: At this time, it is urgent to judge. If it is the write state sw1, it jumps to the data transfer state DATA, and at the same time assigns the written data to the intermediate variable. If it is the read state sw2, it jumps to the second start state START2 and assign the read control word to the intermediate variable.
  7. The second start state START2: it produces a start signal identical to (2) and jumps to the read register address state ADD3
  8. Read register address status ADD3: it jumps to the third response status ACK3S after the transfer of the register address that needs to be read out
  9. The third response state ACK3: it jumps directly to the data transfer state DATA. In the read state, the data to be read is directly read out immediately following the register address.
  10. ACK4 Data transfer status DATA: it needs to be judged here. If it is the read status, the data will be directly output. If it is the write status, the data to be written will be transferred to the data line SDA. Both states need to jump to the fourth response state. ACK4
  11. The fourth response status ACK4: it direct jumps to stop transmission STOP1
  12. Stop transmission STOP1: it pulls up data line when the clock line is high, generating a stop signal, and jumps to the transfer completion status STOP2
  13. Transfer completion status STOP2: it releases all clock lines and data lines, and after a 5ms delay, returns to the IDLE state to wait for the next transfer instruction. This is because EEPROM stipulates that the interval between two consecutives read and write operations must not be less than 5ms.

11.4 Experiment Verification

The first step: pin assignements

See Table 11.1 for the pin assignment.

Table 11.1 IIC protocol transmission experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 System clock 50 MHz
rst KEY3 11 Reset, low by default
sm_db[0] SEG_PA 132 Segment selection signal
sm_db [1] SEG_PB 137
sm_db [2] SEG_PC 133
sm_db [3] SEG_PD 125
sm_db [4] SEG_PE 126
sm_db [5] SEG_PF 138
sm_db [6] SEG_PG 135
sm_db [7] SEG_DP 125
sm_cs1_n SEG_3V3_D1 142 Segment 1
sm_cs2_n SEG_3V3_D0 136 Segment 0
data[0] SW0 80 Switch 0
data[1] SW1 83 Switch 1
data[2] SW2 86 Switch 2
data[3] SW3 87 Switch 3
data[4] SW4 74 Switch 4
data[5] SW5 75 Switch 5
data[6] SW6 76 Switch 6
data[7] SW7 77 Switch 7
sw1 KEY0 3 Write EEPROM button
sw2 KEY1 7 Read EEPROM button
scl I2C_SCL R20 EEPROM clock line
sda I2C_SDA R21 EEPROM data line

The second step: board verification

After the pin assignment is completed, the compilation is performed, and the board is verified after passing.

After the board is programmed, press the LEFT key to write the 8-bit value represented by SW7~SW0 to EEPROM. Then press the RIGHT key to read the value from the write position. Observe the consistency between the value displayed on the segment display on the experiment board and the value written in the 8’h03 register of the EEPROM address (SW7~SW0) (this experiment writes 8’h34). The read value is displayed on the segment display. The experimental phenomenon is shown in Figure 11.3.

Figure 11.3 EEPROM experiment phenomenon

Experiment 12 AD, DA Experiment

12.1 Experiment Objective

Since in the real world, all naturally occurring signals are analog signals, and all that are read and processed in actual engineering are digital signals. There is a process of mutual conversion between natural and industrial signals (digital-to-analog conversion: DAC, analog-to-digital conversion: ADC). The purpose of this experiment is as follows:

  1. Learn about the theory of AD conversion
  2. Review the knowledge of the IIC protocol learned in the previous experiment and write the data into PCF8591 on the development board.
  3. Read the value of AD acquisition from PCF8591, and convert the value obtained into actual value, display it with segment display

12.2 Experiment Implement

  1. The ADC port of the chip is used for analog-to-digital conversion. The chip is correctly configured. Three variable (potentiometer, photoresistor, thermistor) voltages on the development board are collected, and the collected voltage value is displayed through the segment display.
  2. Board downloading verification, compared with resistance characteristics, verify the correctness of the results

12.3 Experiment

Introduction to AD Conversion Chip PCF8591

 

The PCF8591 is a monolithically integrated, individually powered, low power consuming, 8-bit CMOS data acquisition device. The PCF8591 has four analog inputs, one analog output, and one serial IIC bus interface. The three address pins A0, A1 and A2 of the PCF8591 can be used for hardware address programming. The address, control signals and data signals of the input and output on the PCF8591 device are transmitted serially via the two-wire bidirectional IIC bus. Please refer to the previous experiment 11 for the contents of the IIC bus protocol. After the device address information and the read/write control word are sent, the control word information is sent.

Analog Input Selection

A/D Channel Number

Automatic Gain Flag

Analog Output Enable

Figure 12.1 PCF8951 control word

The specific control word information is shown in Figure 12.1. Digit 1 – digit 0 is used for four channel settings, digit 2 is for automatic gain selection, ‘1’ is valid. Digit 5 – digit 4 determines analog input selection. Digit 6 is analog output enable. Digit 7 and digit 3 are reserved to be ‘0’. The second byte sent to PCF8951 is stored in the control register to control the device functionality. The upper nibble of the control register is used to allow the analog output to be programmed as a single-ended or differential input. The lower nibble selects an analog input channel defined by the high nibble. If the auto increment flag is set to 1, the channel number will be automatically incremented after each A/D conversion.

In this experiment, the input channel is selected as the AD acquisition input channel by using the DIP switch (SW1, SW0). The specific channel information is shown in Table 12.1. The control information is configured as 8’h40, which is the analog output, and defaults to “00” channels, which means that the photoresistor voltage value is displayed by default.

Table 12.1 Channel information

SW1,SW0 Channel Selection Acquisition Object
00 0 Voltage of photoresistor
01 1 Voltage of thermistor
10 2 Voltage of potentiometer

Hardware Design

Figure 12.2 Schematics of the AD/DA converter

The schematics of AD/DA conversion using PCF8591 is shown in Figure 12.2. The IIC bus goes through two pull-up resistors and pulls high when not working. A0, A1, A2 are grounded, so the device address is 7’b1010000, the analog input channel AIN0 is connected to the photoresistor, AIN1 is connected to the thermistor, and AIN3 is connected to the potentiometer. When the channel is selected, FPGA will read the value in PCF8591 through the data bus ADDA_I2C_SLC for processing.

12.3.3 Introduction to the Program

This experiment also uses the IIC bus to control the PCF8951 chip, so the program is basically the same as Experiment 11. Only parts difference from Experiment 11 are indicated here.

reg [7:0] read_data_temp [15:0];

reg [11:0] dis_data_temp;

always @ (posedge clk)

dis_data_temp <= read_data_temp[0] + read_data_temp[1] + read_data_temp[2]

+ read_data_temp[3] + read_data_temp[4] + read_data_temp[5]

+ read_data_temp[6] + read_data_temp[7] + read_data_temp[8]

+ read_data_temp[9] + read_data_temp[10] + read_data_temp[11]

+ read_data_temp[12] + read_data_temp[13] + read_data_temp[14]

+ read_data_temp[15];

always @ (posedge clk )

dis_data <= dis_data_temp >> 4;

integer i;

always @ (posedge clk or posedge rst)

begin

if (rst) begin

for (i=0;i<16;i=i+1)

read_data_temp[i] <= 8’h00;

end

else if (iic_done) begin

for (i=0;i<15;i=i+1)

read_data_temp[i+1] <= read_data_temp[i];

read_data_temp[0] <= read_data ;

end

else begin

for (i=0;i<16;i=i+1)

read_data_temp[i] <= read_data_temp[i];

end

end

The role of this part is that when the chip continuously collects the voltage value across the resistor, due to a series of unstable factors, the voltage value will be unstable, so the output value will have a large error, so 16 sets of data is collected each time, then gets averaged, and the result is output as the voltage value across the resistor at this time. Then, by the change of the voltage value, it is possible to judge the regular pattern. Such as photoresistor, the greater the light intensity, the smaller the voltage value, the smaller the resistance value, satisfying the photoresistor characteristics; the higher the thermistor temperature, the smaller the voltage value, the smaller the resistance, satisfying the photoresistor characteristics; the potentiometer rotates clockwise, and the voltage increases, the resistance increases; counterclockwise rotating decreases the voltage, and the resistance decreases.

The maximum output of the AD chip is an 8-bit digital quantity, but in fact it is not the required voltage value. It quantifies the voltage value of the range into 256 portions (8-bit binary number can represent 256 decimal numbers), so further calculations and conversions needs to be applied when displaying on the segment display.

parameter V_REF = 12’d3300;

reg [19:0] num_t;

reg [19:0] num1;

wire [3:0] data0;

wire [3:0] data1;

wire [3:0] data2;

wire [3:0] data3;

wire [3:0] data4;

wire [3:0] data5;

assign data5 = num1 / 17’d100000;

assign data4 = num1 / 14’d10000 % 4’d10;

assign data3 = num1 / 10’d1000 % 4’d10 ;

assign data2 = num1 / 7’d100 % 4’d10 ;

assign data1 = num1 / 4’d10 % 4’d10 ;

assign data0 = num1 % 4’d10;

 

always @ (posedge clk)

num_t <= V_REF * dis_data;

always @(posedge clk or posedge rst)

begin

if(rst) begin

num1 <= 20’d0;

end

else

num1 <= num_t >> 4’d8;

end

VCC is 3.3V, so the maximum resistance voltage is 3.3V. The 8-bit data dis_data is multiplied by 3300 and assigned to numt by 1000 times, which is convenient for display and observation. The numt is further reduced by 256 times (left shifting 8 bits) to num1, corresponding to 256 quantitized portions of PCF8951. num1 at this time is 1000 times the voltage value of two ends of the resistor. Display each digit on the segment display, in the order of high to low (data5 to data0) and add the decimal point (data3) to digit of thousands. At this time, the value displayed by the segment display is the voltage across the resistor value and correct to 3 decimal places.

12.4 Experiment Verification

The first step: pin assignments

See Table 12.2 for the pin assignmnet

Table 12.2 AD conversion experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 System Clock 50 MHz
rst KEY3 10 Reset
sm_db[0] SEG_PA 132 Segment selection signal
sm_db [1] SEG_PB 137
sm_db [2] SEG_PC 133
sm_db [3] SEG_PD 125
sm_db [4] SEG_PE 126
sm_db [5] SEG_PF 138
sm_db [6] SEG_PG 135
sm_db [7] SEG_DP 128
data[0] SW0 80 Switch input
data[1] SW1 83
data[2] SW2 86
data[3] SW3 87
data[4] SW4 74
data[5] SW5 75
data[6] SW6 76
data[7] SW7 77
scl ADDA_I2C_SCL 53 PCF8591 clock line
sda ADDA_I2C_SDA 52 PCF8591 data line
sel[0] SEG_3V3_D0 136 Bit selection signal
sel[1] SEG_3V3_D1 142
sel[2] SEG_3V3_D2 141
sel[3] SEG_3V3_D3 129
sel[4] SEG_3V3_D4 127
sel[5] SEG_3V3_D5 124

The second step: board verification

After the pin assignment is completed, the compilation is performed, and board is verified after passing.

Under the default state, that is, the channel selection is “00”, the segment display shows the current ambient brightness state, the voltage value across the photoresistor is 1.469 V, as shown in Figure 12.3.

Figure 12.3 Photoresistor test phenomenon

When the channel selection is “01”, the segment display shows the current ambient temperature, the voltage across the thermistor is 2.926 V, as shown in Figure 12.4.

Figure 12.4 Thermistor experiment phenomenon

When the channel is selected as “10”, the segment display shows the current resistance value, and the voltage across the potentiometer is 1.624 V, as shown in Figure 12.5.

Figure 12.5 Potentiometer experiment phenomenon

Experiment 13 VGA Experiment

13.1 Experiment Objective

  1. Master the principle of VGA implementation
  2. Design a simple customized VGA image display

13.2 Experiment Implement

在屏幕上实现彩条状图形。A color bar graphic is implemented on the screen.

13.2 Experiment

13.2.1 VGA Principle

VGA (Video Graphics Array) is a computer display standard that IBM introduced in 1987 using analog signals. VGA is a low standard that is supported by most manufacturers. PCs must support the VGA standard before loading their own unique drivers.

The VGA scanning mode on the display is divided into progressive scanning and interlaced scanning: progressive scanning is scanning from the top left corner of the screen, scanning from left to right point by point, each time a line is finished, the electron beam returns to the starting position of the next line on the left of the screen. During the process the CRT blanks the electron beam, and at the end of each line, synchronizes with the line sync signal; when all the lines are scanned, a frame is formed. The field sync signal is used for field synchronization and make the scan back to the top left of the screen, while performing field blanking, start the next frame. Interlaced scanning refers to scanning every other line in the scanning of electron beams. After scanning one screen and then returning to scan the remaining lines, the interlaced display flashes quickly, which may cause eye fatigue. (This experiment uses progressive scanning). See Figure 13.1, 13.2

Figure 13.1 Column synchronization timing

Figure 13.2 Row synchronization timing

The definition of the row timing and column timing in the VGA requires a sync pulse (a segment), a display trailing edge (b segment), and a display timing segment (c segment) and a display leading edge (d segment). VGA industry standard display mode requirements: row synchronization, column synchronization is both negative, that is, the synchronization pulse is required to be a negative pulse. According to the VGA row timing, each row has a negative row sync pulse (a segment), which is the end mark of the data line and the start mark of the next row. After the sync pulse is the display trailing edge (b segment), during the display timing segment (c segment), the monitor is bright, and the RGB data drives each pixel on the row to display one row. At the end of a row is the display leading edge (d segment). No image is projected onto the screen outside the display timing period, but a blanking signal is inserted. The sync pulse, display trailing edge, and display leading edge are all within the line blanking interval. When the blanking is valid, the RGB signal is invalid and the screen does not display data.

The column timing of VGA is basically the same as the row timing analysis.

VGA also has many display standards. In this experiment, the standard of 640×480@60 Hz is used. The standard overview is shown in Figure 13.3.

Clock

Rows

Columns

Display mode

Figure 13.3 VGA display standard

Take the display standard 640*480*60 Hz of this experiment as an example. (640 is the number of columns, 480 is the number of rows, 60 Hz is the frequency to refresh a screen). Row timing: The number of rows corresponding to the screen is 525 (a + b + c + d = e segments), of which 480 (c segment) is the display row; each row has a row synchronization signal (a segment), which is 2 row periods Low level. Column timing: Each display line consists of 800 columns (a + b + c + d = e segments), where 640 (c segment) is the valid display areas, and each row has a row sync signal (a segment) of 96 column periods Low level.

13.3.2 Hardware Design

Figure 13.4 Schematics

The schematic of the VGA display is shown in Figure 13.4. The FPGA directly controls 12 data lines and two control lines, VGA_R3-R0 represents a red component, VGA_G3-G0 represents a green component, VGA_B3-B0 represents a blue component, and a line sync signal VGA_HS and a field sync signal VGA_VS.

13.3.3 Introduction to the Program

The first step: the main program framework is established

module vga_test(

input clk,

input rst,

output vga_hs,

output vga_vs,

output [11:0] vga_data

);

The inputs have a 50 MHz clock and a reset signal. Outputs are a line sync signal vga_has, a field sync signal vga_vs, and a 12-bit data line vga_data[11:0].

The second step: Clock frequency division Module

According to the display mode used in the experiment, the clock is output using a phase-locked loop.

The third step: control module

The main task of the control module is to display the pixels into the active area. Firstly some quantities are defined according to the display criteria.

parameter H_SYNC = 10’d96;

parameter H_BACK = 10’d48;

parameter H_DISP = 10’d640;

parameter H_FRONT = 10’d16;

parameter H_TOTAL = 10’d800;

parameter V_SYNC = 10’d2;

parameter V_BACK = 10’d33;

parameter V_DISP = 10’d480;

parameter V_FRONT = 10’d10;

parameter V_TOTAL = 10’d525;

The five segments with the H prefix corresponding to the column timing in Figure 13.3, the value is the number of pixels per segment, with the V prefix corresponding to the five segments of the row timing in Figure 13.3, the value is the number of rows per segment.

reg [9:0] cnt_h;

reg [9:0] cnt_v;

wire vga_en;

wire data_req;

assign vga_hs = (cnt_h <= H_SYNC – 1’b1) ? 1’b0 : 1’b1;

assign vga_vs = (cnt_v <= V_SYNC – 1’b1) ? 1’b0 : 1’b1;

assign vga_rgb = vga_en ? pixel_data : 16’d0;

assign vga_en = (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))

&&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))

? 1’b1 : 1’b0;

assign data_req = (((cnt_h >= H_SYNC+H_BACK-1’b1) && (cnt_h < H_SYNC

+H_BACK+H_DISP-1’b1))

&& ((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))

? 1’b1 : 1’b0;

assign pixel_xpos = data_req ? (cnt_h – (H_SYNC + H_BACK – 1’b1)) : 10’d0;

assign pixel_ypos = data_req ? (cnt_v – (V_SYNC + V_BACK – 1’b1)) : 10’d0;

This part of the content is fixed by the counter, vga_en fixes the effective area of the image. pixel_xpos and pixel_ypos give each pixel in the effective area a certain coordinate from the upper left corner to facilitate subsequent filling of the corresponding color information. Color output is only available in the active area.

The fourth step: display module

The main task of the display module is dividing the display area, and filling in the color of each block as required.

parameter H_DISP = 10’d640;

parameter V_DISP = 10’d480;

localparam WHITE = 16’b11111_111111_11111;

localparam BLACK = 16’b00000_000000_00000;

localparam RED = 16’b11111_000000_00000;

localparam GREEN = 16’b00000_111111_00000;

localparam BLUE = 16’b00000_000000_11111;

 

always @(posedge vga_clk or negedge sys_rst_n)

begin

if (!sys_rst_n)

pixel_data <= 16’d0;

else begin

if ((pixel_xpos >= 0) && (pixel_xpos <= (H_DISP/5)*1))

pixel_data <= WHITE;

else if ((pixel_xpos >= (H_DISP/5)*1) && (pixel_xpos < (H_DISP/5)*2))

pixel_data <= BLACK;

else if ((pixel_xpos >= (H_DISP/5)*2) && (pixel_xpos < (H_DISP/5)*3))

pixel_data <= RED;

else if ((pixel_xpos >= (H_DISP/5)*3) && (pixel_xpos < (H_DISP/5)*4))

pixel_data <= GREEN;

else

pixel_data <= BLUE;

end

end

First, five colors, white, black, red, green, and blue, are defined. Then, according to the pixel coordinates, the display area is divided into five vertical bars, and five colors are respectively filled in.

13.4 Experiment Verification

The first step: pin assignments

See Table 13.1 for the pin assignments

Table 13.1 VGA experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
clk C10_50MCLK 91 System clock 50 MHz
rst KEY3 10 Reset
vga_data[11] VGA_R3 105 Image red component
vga_data[10] VGA_R2 103
vga_data[9] VGA_R1 101
vga_data[8] VGA_R0 100
vga_data[7] VGA_G3 113 Image green component
vga_data[6] VGA_G2 112
vga_data[5] VGA_G1 111
vga_data[4] VGA_G0 106
vga_data[3] VGA_B3 120 Image blue component
vga_data[2] VGA_B3 119
vga_data[1] VGA_B2 115
vga_data[0] VGA_B1 114
vga_hs VGA_HS 98 Horizontal synchronous signal
vga_vs VGA_VS 99 Vertical synchronous signal

The second step: board verification

After the pin assignment is completed, the compilation is performed, and the development board is programmed. The experimental phenomenon is shown in Figure 13. 5. The screen is divided into five vertical bars, which are white, black, red, green and blue.

Figure 13.5 VGA experiment phenomenon

Experiment 14 Ethernet Experiment

14.1 Experiment Objective

  1. Understand what Ethernet is and how it works
  2. Familiar with the relationship between different interface types (MII, GMII, RGMII) and their advantages and disadvantages (the development board uses RGMII)
  3. Combine the development board to complete the transmission and reception of data and verify it

14.2 Experiment Implement

  1. Perform a loopback test to check if the hardware is working properly.
  2. Performing data verification
  3. Perform data transmission verification

14.3 Experiment

14.3.1 Experiment Principle

Ethernet is a baseband LAN technology. Ethernet communication is a communication method that uses coaxial cable as a network medium and uses carrier multi-access and collision detection mechanisms. The data transmission rate reaches 1 Gbit/s, which can satisfy the need for data transfer of non-persistent networks. As an interconnected interface, the Ethernet interface is very widely used. There are many types of Gigabit Ethernet MII interfaces, and GMII and RGMII are commonly used.

MII interface has a total of 16 lines. See Fig 14. 1.

PHY SIDE

MAC SIDE

Figure 14.1 MII interface

 

RXD (Receive Data) [3:0]: data reception signal, a total of 4 signal lines;

TX_ER (Transmit Error): Send data error prompt signal, synchronized to TX_CLK, active high, indicating that the data transmitted during TX_ER validity period is invalid. For 10Mbps rate, TX_ER does not work;

RX_ER (Receive Error): Receive data error prompt signal, synchronized to RX_CLK, active high, indicating that the data transmitted during the valid period of RX_ER is invalid. For 10Mbps, RX_ER does not work;

TX_EN (Transmit Enable): Transmit enable signal, only the data transmitted during the valid period of TX_EN is valid;

RX_DV (Receive Data Valid): Receive data valid signal, the action type is TX_EN of the transmission channel;

TX_CLK: Transmit reference clock, the clock frequency is 25MHz at 100Mbps, and the clock frequency is 2.5MHz at 10Mbps. Note that the direction of TX_CLK clock is from the PHY side to the MAC side, so this clock is provided by the PHY;

RX_CLK: Receive data reference clock, the clock frequency is 25MHz at 100Mbps, and the clock frequency is 2.5MHz at 10Mbps. RX_CLK is also provided by the PHY side;

CRS: Carrier Sense, carrier detect signal, does not need to synchronize with the reference clock. If there is data transmission, CRS is valid. In addition, CRS is effective only if PHY is in half-duplex mode;

COL: Collision detection signal, does not need to be synchronized to the reference clock, is valid only if PHY is in half-duplex mode.

GMII interface is shown in Figure 14.2.

PHY SIDE

MAC SIDE

Figure 14.2 GMII interface

Compared with the MII interface, the data width of the GMII is changed from 4 bits to 8 bits. The control signals in the GMII interface such as TX_ER, TX_EN, RX_ER, RX_DV, CRS, and COL function the same as those in the MII interface. The frequencies of transmitting reference clock GTX_CLK and the receiving reference clock RX_CLK are both 125 MHz (1000 Mbps / 8 = 125 MHz).

There is one point that needs special explanation here, that is, the transmitting reference clock GTX_CLK is different from the TX_CLK in the MII interface. The TX_CLK in the MII interface is provided by the PHY chip to the MAC chip, and the GTX_CLK in the GMII interface is provided to the PHY chip by the MAC chip. The directions are different.

In practical applications, most GMII interfaces are compatible with MII interfaces. Therefore, the general GMII interface has two transmitting reference clocks: TX_CLK and GTX_CLK (the directions of the two are different, as mentioned above). When used as the MII mode, TX_CLK and 4 of the 8 data lines are used.

See Figure 14.3 for RGMII interface.

PHY SIDE

MAC SIDE

Figure 14.3 RGMII interface

RGMII, or reduced GMII, is a simplified version of GMII, which reduces the number of interface signal lines from 24 to 14 (COL/CRS port status indication signals, not shown here), the clock frequency is still 125MHz, and the TX/RX data width is changed from 8 to 4 bits. To keep the transmission rate of 1000 Mbps unchanged, the RGMII interface samples data on both the rising and falling edges of the clock. TXD[3:0]/RXD[3:0] in the GMII interface is transmitted on the rising edge of the reference clock, and TXD[7:4]/RXD[7:4] in the GMII interface is transmitted on the falling edge of the reference clock. RGMI is also compatible with both 100Mbps and 10Mbps rates, with reference clock rates of 25MHz and 2.5MHz, respectively.

The TX_EN signal line transmits TX_EN and TX_ER information, TX_EN is transmitted on the rising edge of TX_CLK, and TX_ER is transmitted on the falling edge. Similarly, RX_DV and RX_ER are transmitted on the RX_DV signal line, and RX_DV is transmitted on the rising edge of RX_CLK, and RX_ER is transmitted on the falling edge.

14.3.2 Hardware Design

Figure 14.4 Schematics of RTL8211E-VB

The RTL8211E-VB chip is used to form a Gigabit Ethernet module on the experiment board. The schematics is shown in Figure 14. 4. The PHY chip is connected to the FPGA by receiving and transmitting two sets of signals. The receiving group signal prefix is RG0_RX, and the transmitting group signal prefix is RG0TX, which is composed of a control signal CTL, a clock signal CK and four data signals 3-0. RG0_LED0 and RG0_LED1 are respectively connected to the network port yellow signal light and green signal light. At the same time, the FPGA can configure the PHY chip through the clock line NPHY_MDC and the data line NPHY_MDIO.

14.3.3 Design of the Program

  1. Loopback test design(test1)

The first step: introduction of the program

The loopback test is straightforward. Simply output the input data.

module test1 (

input rst,

input rxc,

input rxdv,

input [3:0] rxd,

output txc,

output txen,

output [3:0] txd,

);

 

assign txd = rxd;

assign txen = rxdv;

assign txc = rxc;

endmodule

(Note: Each program in this experiment contains a smi_ctrl module. In the config folder, it is a setting module for the PHY chip, to solve the problem that some computers cannot connect to the network port normally, and will not explain in detail)

The second step: pin assignment

See Table 14.1 for the pin assignment

Table 14.1 Ethernet experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
rxc RG0_RXCK 24 Input clock
rxdv RG0_RXCTL 34 Input control signal
rxd[3] RG0_RX3 28 Receive data (4-bit bilateral edge)
rxd[2] RG0_RX2 31
rxd[1] RG0_RX1 32
rxd[0] RG0_RX0 33
txc RG0_TXCK 43 Output clock
txen RG0_TXCTL 42 Output control signal
txd[3] RG0_TX3 46 Transmit data (4-bit bilateral edge)
txd[2] RG0_TX2 49
txd[1] RG0_TX1 50
txd[0] RG0_TX0 51
e_mdc NPHY_MDC 38 Configuration clock
e_mdio NPHY_MDIO 39 Configuration data

Before verification (the default PC NIC is a Gigabit NIC, otherwise it needed to be replaced). The host PC IP address needs to be confirmed first. In the DOS command window, type ipconfig -all command to check it. As an example, as shown in Figure 14.5.

Figure 14.5 PC end IP information

To facilitate subsequent experiments, provides PC a fixed IP address. Take this as an example, IP configuration is 192.169.0.100 (could be revised, but needs to be consistent to the IP address of target sending module, for Internet Protocol reason, IP address 169.XXX.X.X is not suggested ). Find Internet Protocol Version 4(TCP/IPv4) in Network and Sharing center. See Figure 14.6.

Figure 14.6 Configure PC end IP address

Since there is no ARP protocol content (binding IP address and MAC address of the development board) in this test, it needs to be bound manually through the DOS command window. In this test, the development board IP is set to 192.168.0.2 and the MAC address is set to 00-0A-35-01-FE-C0, (can be replaced by yourself) as shown in Fig 14. 7, the method is as follows: (Note: Run the DOS command window as an administrator)

Run the command: ARP -s 192.168.0.2 00-0A-35-01-FE-C0

View binding results: ARP -a

Figure 14.7 Address binding method 1

If a failure occurs while running the ARP command, it can be bound in another way, as shown in Figure 14.8:

  1. Enter the netsh i i show in command to view the number of the local connection, such as the “23” of the computer used this time.
  2. Enter netsh -c “i i” add neighbors 23 (number) “192.168.0.2” “00-0A-35-01-FE-C0”
  3. Enter arp -a to view the binding result (since it has been bound before, it will display as shown below in Figure 14.8)

Next, the DOS command window is used again for connectivity detection, as shown in Figure 14.9. Ping is an executable command that comes with the Windows family. Use it to check if the network can be connected. It can help analyze and determine network faults. Application format: Ping IP address (not host computer IP).

Figure 14.9 Send data

Start SignalTap II, after sending the command, as shown in Figure 14.10. The data is ordinary and the hardware fucntions well.

Figure 14.10 SignalTap II data capture

  1. Special IP core configuration (test2)

Because it is the RGMII interface, the data is bilateral along 4-bit data. Therefore, when data processing is performed inside the FPGA, it needs to be converted into 8-bit data. Go to Installed IP > Library > Basic Functions > I/O to find ALTDDIO_IN and ALTDDIO_OUT. IP core (ddio_in) is called to implement it, and after internal data processing, pass IP core (ddio_out) to convert 8-bit data into double-rolled edge 4-bit data transfer. It should be noted that, considering the enable signal and data signal synchronization, the enable signal is input into ddio for conversion. The specific settings are shown in Figure 14.11 and Figure 14.12.

Figure 14.11 ddio_in setting

Figure 14.12 ddio_out setting

Considering that the driving ability of the clock provided by the PHY chip is relatively poor, after the phase-locked loop processing, unlike the prior part, the input clock rxc selects the homologous input, as shown in Figure 14.13, and output C0 clock ddio_clk as the driving clock of two ddio IP cores, as shown in Figure 14.14, outputs the C1 clock txc as the data transmission clock (note that due to hardware circuit and timing reasons, txc needs to be 90° phase difference). See Figure 14.15.

Figure 14.13 PLL input clock setting

Figure 14.14 PLL output clock (c0) setting

Figure 14.15 PLL output clock (c1) setting

The three IP cores are instantiated into the previous loopback test, and the data transmission correctness test is performed. (It is necessary to notice the orderly timing. The ddio_out input data needs to be reversed. For details, refer to the project file (test2)). A network debugging assistant applet is used as an auxiliary testing tool. Program the board and verify it.

As shown in Figure 14.16, after setting the correct address and data type, the detection information (love you!) is sent through the host computer. The data packet is captured by Wireshark, as shown in Figure 14.17. The data is correctly transmitted back to the PC.

Figure 14.16 The host computer sends the test data

Figure 14.17 Correct reception of data on the PC side

  1. Complete Ethernet data transmission design

For complete Ethernet data transmission, it is necessary to have the receiving part of the data and the transmitting part of the data. For the convenience of experiment, the data sent by the PC is first sotred in the RAM. After reading via the transmitting end, it is sent to the PC. A series of data unpacking and packaging referring to the project file “ethernet”. A brief introduction to each module is as follows.

  1. Data receiving module (ip_receive)

The problem to be solved by this module is to detect and identify the data frame, unpack the valid data frame, and store the real data in the RAM.

always @ (posedge clk) begin

if (clr) begin

rx_state <= idle;

data_receive <= 1’b0;

end

else

case (rx_state)

 

idle :

begin

valid_ip_P <= 1’b0;

byte_counter <= 3’d0;

data_counter <= 10’d0;

mydata <= 32’d0;

state_counter <= 5’d0;

data_o_valid <= 1’b0;

ram_wr_addr <= 0;

if (e_rxdv == 1’b1) begin

if (datain[7:0] == 8’h55) begin //Receive the first 55//

rx_state <= six_55;

mydata <= {mydata[23:0], datain[7:0]};

end

else

rx_state <= idle;

end

end

 

six_55 :

begin //Receive 6 0x55//

if ((datain[7:0] == 8’h55) && (e_rxdv == 1’b1)) begin

if (state_counter == 5) begin

state_counter <= 0;

rx_state <= spd_d5;

end

else

state_counter <= state_counter + 1’b1;

end

else

rx_state <= idle;

end

 

spd_d5 :

begin //Receive 1 0xd5//

if ((datain[7:0] == 8’hd5) && (e_rxdv == 1’b1))

rx_state <= rx_mac;

else

rx_state <= idle;

end

 

rx_mac :

begin //Target mac address and source MAC address

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d11) begin

mymac <= {mymac[87:0], datain};

state_counter <= state_counter + 1’b1;

end

else begin

board_mac <= mymac[87:40];

pc_mac <= {mymac[39:0], datain};

state_counter <= 5’d0;

if((mymac[87:72] == 16’h000a) && (mymac[71:56] == 16’h3501) && (mymac[55:40] == 16’hfec0)) //Judge the MAC Address is PRA006’s

rx_state <= rx_IP_Protocol;

else

rx_state <= idle;

end

end

else

rx_state <= idle;

end

 

rx_IP_Protocol :

begin //Receive 2 bytes IP TYPE

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d1) begin

myIP_Prtcl <= {myIP_Prtcl[7:0], datain[7:0]};

state_counter <= state_counter+1’b1;

end

else begin

IP_Prtcl <= {myIP_Prtcl[7:0],datain[7:0]};

valid_ip_P <= 1’b1;

state_counter <= 5’d0;

rx_state <= rx_IP_layer;

end

end

else

rx_state <= idle;

end

 

rx_IP_layer :

begin //Receive 20 bytes udpvirtual header,ip address

valid_ip_P <= 1’b0;

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d19) begin

myIP_layer <= {myIP_layer[151:0], datain[7:0]};

state_counter <= state_counter + 1’b1;

end

else begin

IP_layer <= {myIP_layer[151:0], datain[7:0]};

state_counter <= 5’d0;

rx_state <= rx_UDP_layer;

end

end

else

rx_state <= idle;

end

 

rx_UDP_layer :

begin //Receive 8 bytes UDP port number and total length of UDP packet

rx_total_length <= IP_layer[143:128];

pc_IP <= IP_layer[63:32];

board_IP <= IP_layer[31:0];

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d7) begin

myUDP_layer <= {myUDP_layer[55:0], datain[7:0]};

state_counter <= state_counter + 1’b1;

end

else begin

UDP_layer <= {myUDP_layer[55:0], datain[7:0]};

rx_data_length <= myUDP_layer[23:8]; //Length of UDP packet

state_counter <= 5’d0;

rx_state <= rx_data;

end

end

else

rx_state <= idle;

end

 

rx_data :

begin // Receive UDP data

if (e_rxdv == 1’b1) begin

if (data_counter == rx_data_length-9) begin //Save the last ata

data_counter <= 0;

rx_state <= rx_finish;

ram_wr_addr <= ram_wr_addr + 1’b1;

data_o_valid <= 1’b1; //Write RAM

if (byte_counter == 3’d3) begin

data_o <= {mydata[23:0], datain[7:0]};

byte_counter <= 0;

end

else if (byte_counter==3’d2) begin

data_o <= {mydata[15:0], datain[7:0],8’h00}; //Less than 32-bit, add ’0’

byte_counter <= 0;

end

else if (byte_counter==3’d1) begin

data_o <= {mydata[7:0], datain[7:0], 16’h0000}; // Less than 32-bit, add ’0’

byte_counter <= 0;

end

else if (byte_counter==3’d0) begin

data_o <= {datain[7:0], 24’h000000}; // Less than 32-bit, add ’0’ byte_counter <= 0;

end

end

else begin

data_counter <= data_counter + 1’b1;

if (byte_counter < 3’d3) begin

mydata <= {mydata[23:0], datain[7:0]};

byte_counter <= byte_counter + 1’b1;

data_o_valid <= 1’b0;

end

else begin

data_o <= {mydata[23:0], datain[7:0]};

byte_counter <= 3’d0;

data_o_valid <= 1’b1// Accept 4bytes of data, write RAM request ram_wr_addr <= ram_wr_addr+1’b1;

end

end

end

else

rx_state <= idle;

end

 

rx_finish :

begin

data_o_valid <= 1’b0; //added for receive test//

data_receive <= 1’b1;

rx_state <= idle;

end

default : rx_state <= idle;

endcase

end

The receiving module is to perform step by step analysis on the received data.

Idle state: If 55 is received, it jumps to the six_55 state.

six_55 state: If it continues to receive six consecutive 55s, it will jump to the spd_d5 state, otherwise it will return the idle state.

spd_d5 state: If continues to receive d5, it proves that the complete packet preamble 55_55_55_55_55_55_55_d5 has been received, and jumps to rx_mac, otherwise it returns the idle transition.

rx_mac state: This part is the judgment of the target MAC address and the source MAC address. If it matches, it will jump to the rx_IP_Protocol state, otherwise it will return the idle state and resend.

rx_IP_Protocol state: Determine the type and length of the packet and jump to the rx_IP_layer state.

rx_IP_layer state: Receive 20 bytes of udp virtual header and IP address, jump to rx_UDP_layer state

rx_UDP_layer state: Receive 8-byte UDP port number and UDP packet length, jump to rx_data state

rx_data state: Receive UDP data, jump to rx_finish state

rx_finish state: A packet of data is received, and jumps to the idle state to wait for the arrival of the next packet of data.

  1. Data sending module (ip_send)

The main content of this module is to read out the data in the RAM, package and send the data with the correct packet protocol type (UDP). Before sending, the data is also checked by CRC.

initial begin

tx_state <= idle;

//Define IP header

preamble[0] <= 8’h55; //7 preambles 55, one frame start character d5

preamble[1] <= 8’h55;

preamble[2] <= 8’h55;

preamble[3] <= 8’h55;

preamble[4] <= 8’h55;

preamble[5] <= 8’h55;

preamble[6] <= 8’h55;

preamble[7] <= 8’hD5;

 

mac_addr[0] <= 8’h00; // Destination MAC address ff-ff-ff-ff-ff-ff, all ff is broadcast packet

mac_addr[1] <= 8’h0A; //Destination MAC address 00-0A-35-01-FE-C0, is the PC address used for this experiment. In the debugging phase changes content according to the value of actual PC

mac_addr[2] <= 8’h35;

mac_addr[3] <= 8’h01;

mac_addr[4] <= 8’hFE;

mac_addr[5] <= 8’hCO;

 

mac_addr[6] <= 8’h00; // Source MAC address 00-0A-35-01-FE-C0

mac_addr[7] <= 8’h0A; // Modify to the specified value according to actual needs

mac_addr[8] <= 8’h35;

mac_addr[9] <= 8’h01;

mac_addr[10]<= 8’hFE;

mac_addr[11]<= 8’hC0;

 

mac_addr[12]<= 8’h08; // 0800: IP packet type

mac_addr[13]<= 8’h00;

 

i<=0;

end

This part defines the preamble of the data packet, the MAC address of the PC, the MAC address of the development board, and the IP packet type. It should be noted that in the actual experiment, the MAC address of the PC needs to be modified, and the MAC address of the PC needs to be modified according to the address bound by itself, but the premise is that the consistency must be guaranteed. Otherwise the subsequent experiments will not receive data.

always @ (posedge clk) begin

case (tx_state)

idle :

begin

e_txen <= 1’b0;

crcen <= 1’b0;

crcre <= 1;

j <= 0;

dataout <= 0;

ram_rd_addr <= 1;

tx_data_counter <= 0;

if (time_counter == 32’h04000000) begin // Waiting for delay, sending a packet every once in a while

tx_state <= start;

time_counter <= 0;

end

else

time_counter <= time_counter + 1’b1;

end

 

start :

begin //IP header

ip_header[0] <= {16’h4500, tx_total_length}; // Version number: 4; length of the packet header: 20; total length of the IP packet

ip_header[1][31:16] <= ip_header[1][31:16]+1’b1; // Package serial number

ip_header[1][15:0] <= 16’h4000; //Fragment offset

ip_header[2] <= 32’h80110000; // Mema[2][15:0] Protocol: 17 (UDP)

ip_header[3] <= 32’hc0a80002; //192.168.0.2 source MAC

ip_header[4] <= 32’hc0a80010; //192.168.0.10 Destination address broadcast address

ip_header[5] <= 32’h1f901f90; //2-byte source port number and 2-byte destination port number

ip_header[6] <= {tx_data_length, 16’h0000}; //2 bytes of data length and 2 bytes of checksum (none)

tx_state <= make;

end

 

make :

begin // Generate a checksum of the header

if (i == 0) begin

check_buffer <= ip_header[0][15:0] + ip_header[0][31:16] +

ip_header[1][15:0] + ip_header[1][31:16] +

ip_header[2][15:0] + ip_header[2][31:16] +

ip_header[3][15:0] + ip_header[3][31:16] +

ip_header[4][15:0] + ip_header[4][31:16];

i <= i + 1’b1;

end

else if(i == 1) begin

check_buffer[15:0] <= check_buffer[31:16] + check_buffer[15:0];

i <= i+1’b1;

end

else begin

ip_header[2][15:0] <= ~check_buffer[15:0]; //header checksum

i <= 0;

tx_state <= send55;

end

end

 

send55 :

begin // Send 8 IP preambles: 7 55, 1 d5

e_txen <= 1’b1; // GMII data transmission is valid

crcre <= 1’b1; //Reset crc

if(i == 7) begin

dataout[7:0] <= preamble[i][7:0];

i <= 0;

tx_state <= sendmac;

end

else begin

dataout[7:0] <= preamble[i][7:0];

i <= i + 1’b1;

end

end

 

sendmac :

begin // Send destination MAC address, source MAC address and IP packet type

crcen <= 1’b1; // Crc check enable, crc32 data check starts from the target MAC

crcre <= 1’b0;

if (i == 13) begin

dataout[7:0] <= mac_addr[i][7:0];

i <= 0;

tx_state <= sendheader;

end

else begin

dataout[7:0] <= mac_addr[i][7:0];

i <= i + 1’b1;

end

end

 

sendheader :

begin // Send 7 32-bit IP headers

datain_reg <= datain; // Prepare the data needed to send

if(j == 6) begin

if(i == 0) begin

dataout[7:0] <= ip_header[j][31:24];

i <= i + 1’b1;

end

else if(i == 1) begin

dataout[7:0] <= ip_header[j][23:16];

i <= i + 1’b1;

end

else if(i == 2) begin

dataout[7:0] <= ip_header[j][15:8];

i <= i + 1’b1;

end

else if(i == 3) begin

dataout[7:0] <= ip_header[j][7:0];

i <= 0;

j <= 0;

tx_state <= senddata;

end

end

else begin

if(i == 0) begin

dataout[7:0] <= ip_header[j][31:24];

i <= i + 1’b1;

end

else if(i == 1) begin

dataout[7:0] <= ip_header[j][23:16];

i <= i + 1’b1;

end

else if(i == 2) begin

dataout[7:0] <= ip_header[j][15:8];

i <= i + 1’b1;

end

else if(i == 3) begin

dataout[7:0] <= ip_header[j][7:0];

i <= 0;

j <= j + 1’b1;

end

end

end

 

senddata :

begin //Send UDP packets

if(tx_data_counter == tx_data_length – 9) begin // Send the last data

tx_state <= sendcrc;

if (i == 0) begin

dataout[7:0] <= datain_reg[31:24];

i <= 0;

end

else if (i == 1) begin

dataout[7:0] <= datain_reg[23:16];

i <= 0;

end

else if (i == 2) begin

dataout[7:0] <= datain_reg[15:8];

i <= 0;

end

else if (i == 3) begin

dataout[7:0] <= datain_reg[7:0];

datain_reg <= datain; // Prepare data

i <= 0;

end

end

else begin // Send other packets

tx_data_counter <= tx_data_counter+1’b1;

if (i == 0) begin

dataout[7:0] <= datain_reg[31:24];

i <= i + 1’b1;

ram_rd_addr <= ram_rd_addr + 1’b1; // Add 1 to the RAM address, let the RAM output data in advance.

end

else if (i == 1) begin

dataout[7:0] <= datain_reg[23:16];

i <= i + 1’b1;

end

else if (i == 2) begin

dataout[7:0] <= datain_reg[15:8];

i <= i + 1’b1;

end

else if (i == 3) begin

dataout[7:0] <= datain_reg[7:0];

datain_reg <= datain; // Prepare data

i <= 0;

end

end

end

 

sendcrc :

begin // Send a 32-bit crc check

crcen <= 1’b0;

if (i == 0) begin

dataout[7:0] <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]};

i <= i + 1’b1;

end

else begin

if (i == 1) begin

dataout[7:0] <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]};

i <= i + 1’b1;

end

else if (i == 2) begin

dataout[7:0] <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]};

i <= i + 1’b1;

end

else if (i == 3) begin

dataout[7:0] <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]};

i <= 0;

tx_state <= idle;

end

end

end

 

default : tx_state <= idle;

endcase

end

Idle state: Waiting for delay, sending a packet at regular intervals and jumping to the start state.

start state: Send the packet header and jump to the make state.

make state: Generates the checksum of the header and jumps to the send55 state.

send55 status: Send 8 preambles and jump to the sendmac state.

sendmac state: Send the destination MAC address, source MAC address and IP packet class, and jump to the sendheader state.

sendheader state: Sends 7 32-bit IP headers and jumps to the senddata state.

senddata state: Send UDP packets and jump to the sendcrc state.

sendcrc state: Sends a 32-bit crc check and returns the idle state.

Thus, the entire packet of data is transmitted, and the idle state is returned to wait for the transmission of the next packet of data.

  1. CRC check module (crc)

The CRC32 check of an IP packet is calculated at the destination MAC Address and is calculated until the last data of a packet. The CRC32 verilog algorithm and polynomial of Ethernet can be generated directly at the following website: http://www.easics.com/webtools/crctool

  1. UDP data test module (UDP)

This module only needs to instantiate the first three sub-modules together, paying attention to the correctness of each connection.

  1. Top level module settings (ethernet)

The PLL, ddio_in, ddio_out, RAM, and UDP modules are instantiated to the top layer, and specific information is stored in advance in the RAM (Welcome To ZGZNXP World!). When there is no data input, the FPGA always sends this information. With data input, the received data is sent. Refer to the project files for more information.

14.4 Experiment Verification

The pin assignment of this test procedure is identical to that in Test 1.

Before programming the development board, it is necessary to note that the IP address of the PC and the MAC address of the development board must be determined and matched, otherwise the data will not be received.

As shown in Figure 14.18, the FPGA is keeping sending information to the PC. The entire transmitted packet can also be seen in Wireshark, as shown in Figure 14.19.

Figure 14.18 Send specific information

Figure 14.19 Specific information package

When the PC sends data to the FPGA, as shown in Figure 14.20, the entire packet arrives at the FPGA, and then the FPGA repackages the received data and sends it to the PC. See Figure 14.21, the network assistant also receives the transmitted data information accurately, as shown in Figure 14.22. Similarly, through SignalTap we can see the process of writing the received data, as shown in Figure 14.23.

Figure 14. 20 PC send data package

Figure 14.21 The FPGA repackages the received data and sends it to the PC

Figure 14.22 Information received by PC from FPGA

Figure 14.23 FPGA end data and stored in the RAM process

It should be noted that Ethernet II specifies the Ethernet frame data field is a minimum of 46 bytes, that is, the minimum Ethernet frame is 6+6+2+46+4=64. The 4-byte FCS is removed, so the packet capture is 60 bytes. When the length of the data field is less than 46 bytes, the MAC sublayer is padded after the data field to satisfy the data frame length of not less than 64 bytes. When communicating over a UDP LAN, “Hello World” often occurs for testing, but “Hello World” does not meet the minimum valid data (64-46) requirements. It is less than 18 bytes but the other party is still available for receiving, because data is complemented in the MAC sublayer of the link layer, less than 18 bytes are padded with ‘0’s. However, when the server is on the public network and the client is on the internal network, if less than 18 bytes of data is transmitted, the receiving end cannot receive the data. Therefore, if there is no data received, the information to be sent should be increased to more than 18 bytes.

References

Quartus II Introduction Using VHDL Designs https://www.ee.ryerson.ca/~courses/coe328/Quartus_II_Introduction-V13.pdf

Switch Debouncing

https://www.nxp.com/docs/en/data-sheet/PCF8591.pdf

Related posts

Leave a Comment