The VHDL code

In this section, we will take a look at the top-level entity in the VHDL project, to get an idea of what it does. This starts with the standard library includes for VHDL as shown:

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.std_logic_unsigned.ALL; 
use IEEE.numeric_std.all; 
 
entity FleaFPGA_Ohm_A5 is   
   port( 
   sys_clock         : in        std_logic;  -- 25MHz clock input from external xtal oscillator. 
   sys_reset         : in        std_logic;  -- master reset input from reset header. 

This maps to the underlying FPGA's system clock and reset line. We can also see the way that port mapping works, defining the direction of the entity port and the type. Here, the type is std_logic, which is a standard logic signal of either a binary one or zero:

   n_led1                  : buffer    std_logic; 
  
   LVDS_Red          : out       std_logic_vector(0 downto 0); 
   LVDS_Green        : out       std_logic_vector(0 downto 0); 
   LVDS_Blue         : out       std_logic_vector(0 downto 0); 
   LVDS_ck                 : out       std_logic_vector(0 downto 0); 
    
   slave_tx_o        : out       std_logic; 
   slave_rx_i        : in        std_logic; 
   slave_cts_i       : in        std_logic;  -- Receive signal from #RTS pin on FT230x 

We also use the status LED on the board, map the HDMI's video pins (LVDS signaling), and the UART interface, which uses the FDTI USB-UART chip on the board. The latter is what we will be using to send the data from the FPGA to the C++ application.

Next, the Raspberry Pi compatible header mapping, as shown in the following code:

   GPIO_2                  : inout           std_logic; 
   GPIO_3                  : inout           std_logic; 
   GPIO_4                  : inout           std_logic; 
   -- GPIO_5               : inout           std_logic; 
   GPIO_6                  : inout           std_logic;   
   GPIO_7                  : inout           std_logic;   
   GPIO_8                  : inout           std_logic;   
   GPIO_9                  : inout           std_logic;   
   GPIO_10                 : inout           std_logic; 
   GPIO_11                 : inout           std_logic;   
   GPIO_12                 : inout           std_logic;   
   GPIO_13                 : inout           std_logic;   
   GPIO_14                 : inout           std_logic;   
   GPIO_15                 : inout           std_logic;   
   GPIO_16                 : inout           std_logic;   
   GPIO_17                 : inout           std_logic; 
   GPIO_18                 : inout           std_logic;   
   GPIO_19                 : inout           std_logic;   
   GPIO_20                 : in        std_logic; 
   GPIO_21                 : in        std_logic;   
   GPIO_22                 : inout           std_logic;   
   GPIO_23                 : inout           std_logic; 
   GPIO_24                 : inout           std_logic; 
   GPIO_25                 : inout           std_logic;   
   GPIO_26                 : inout           std_logic;   
   GPIO_27                 : inout           std_logic; 
   GPIO_IDSD         : inout           std_logic; 
   GPIO_IDSC         : inout           std_logic; 

The reason that GPIO 5 is commented out is because we want to use it for the ADC functionality and not general-purpose input/output.

Instead, we enable the sigma-delta-capable ADC3 peripheral to work on that pin as follows:

   --ADC0_input      : in        std_logic; 
   --ADC0_error      : buffer    std_logic; 
   --ADC1_input      : in        std_logic; 
   --ADC1_error      : buffer    std_logic; 
   --ADC2_input      : in        std_logic; 
   --ADC2_error      : buffer    std_logic; 
   ADC3_input  : in        std_logic; 
   ADC3_error  : buffer    std_logic; 

Here, we see that we have another three ADC peripherals that we could use if we wanted to add additional channels to the oscilloscope , as shown in the following code:

   mmc_dat1          : in        std_logic; 
   mmc_dat2          : in        std_logic; 
   mmc_n_cs          : out       std_logic; 
   mmc_clk           : out       std_logic; 
   mmc_mosi          : out       std_logic; 
   mmc_miso          : in        std_logic; 
 
   PS2_enable        : out       std_logic; 
   PS2_clk1          : inout           std_logic; 
   PS2_data1         : inout           std_logic; 
    
   PS2_clk2          : inout           std_logic; 
   PS2_data2         : inout           std_logic 
   ); 
end FleaFPGA_Ohm_A5; 

The entity definition for the top-level ends with the MMC (SD card) and PS2 interfaces.

Next is the architecture definition of the module. This part is akin to the source file of a C++ application, with the entity definition functioning like a header as shown:

architecture arch of FleaFPGA_Ohm_A5 is 
   signal clk_dvi  : std_logic := '0'; 
   signal clk_dvin : std_logic := '0'; 
   signal clk_vga  : std_logic := '0'; 
   signal clk_50  : std_logic := '0'; 
   signal clk_pcs   : std_logic := '0'; 
 
   signal vga_red     : std_logic_vector(3 downto 0) := (others => '0'), 
   signal vga_green   : std_logic_vector(3 downto 0) := (others => '0'), 
   signal vga_blue    : std_logic_vector(3 downto 0) := (others => '0'), 
    
   signal ADC_lowspeed_raw     : std_logic_vector(7 downto 0) := (others => '0'), 
    
   signal red     : std_logic_vector(7 downto 0) := (others => '0'), 
   signal green   : std_logic_vector(7 downto 0) := (others => '0'), 
   signal blue    : std_logic_vector(7 downto 0) := (others => '0'), 
   signal hsync   : std_logic := '0'; 
   signal vsync   : std_logic := '0'; 
   signal blank   : std_logic := '0'; 

A number of signals are defined here. These allow us to connect the ports, entities, processes, and other elements of a VHDL module with each other.

We can see that some signals are defined here for VGA support. This allows compatibility with VGA-enabled FPGA boards, but parts of it are also compatible with the HDMI (or a DVI) peripheral, as we will see in a moment. Let's look at the following code:

begin 
 Dram_CKE <= '0';    -- DRAM Clock disable. 
 Dram_n_cs <= '1';   -- DRAM Chip disable. 
 PS2_enable <= '1'; -- Configures both USB host ports for legacy PS/2 mode. 
 mmc_n_cs <= '1';    -- Micro SD card chip disable. 

With the begin keyword, we indicate that this is the point where we want to start executing the commands in the architecture definition. Everything after this keyword and the terminating keyword (end architecture) will be executed simultaneously, unless a block of instructions is encapsulated within a process (not shown in this code).

We disable a number of hardware features by writing to the appropriate pins. We omitted the DRAM (external memory) section in the earlier entity definition for brevity's sake. The DRAM and SD card functionality are disabled, while PS2 (keyboard, mouse) functionality is enabled. This allows us to connect a PS2 input device if we wanted to:

 user_module1 : entity work.FleaFPGA_DSO 
    port map( 
         rst => not sys_reset, 
         clk => clk_50, 
         ADC_1 => n_led1, 
         ADC_lowspeed_raw => ADC_lowspeed_raw, 
         Sampler_Q => ADC3_error, 
         Sampler_D => ADC3_input, 
         Green_out => vga_green, 
         Red_out => vga_red, 
         Blue_out => vga_blue, 
         VGA_HS => hsync, 
         VGA_VS => vsync, 
         blank => blank, 
         samplerate_adj => GPIO_20, 
         trigger_adj => GPIO_21 
    ); 

Here, we define that we will be using an instance of the FleaFPGA Digital Storage Oscilloscope module. Only the first channel is mapped, though the module could support four channels. This simplification helps to demonstrate the principle of operation.

The DSO module is responsible for reading out the data from the ADC as it samples the signal we're measuring with the probe, and both renders it to a local cache for display on a local (HDMI or VGA) monitor and send it over the serial interface to the UART module (shown at the end of this section). . Let's look at the following code:

   red <= vga_red & "0000"; 
   green <= vga_green & "0000"; 
   blue <= vga_blue & "0000"; 

Here, the final colors for the display output are determined with the HDMI output signal:

   u0 : entity work.DVI_clkgen 
   port map( 
         CLKI              =>    sys_clock, 
         CLKOP             =>    clk_dvi, 
         CLKOS                   =>  clk_dvin, 
         CLKOS2                  =>  clk_vga, 
         CLKOS3                  =>  clk_50 
         );   
 
   u100 : entity work.dvid PORT MAP( 
      clk       => clk_dvi, 
      clk_n     => clk_dvin, 
      clk_pixel => clk_vga, 
      red_p     => red, 
      green_p   => green, 
      blue_p    => blue, 
      blank     => blank, 
      hsync     => hsync, 
      vsync     => vsync, 
      -- outputs to TMDS drivers 
      red_s     => LVDS_Red, 
      green_s   => LVDS_Green, 
      blue_s    => LVDS_Blue, 
      clock_s   => LVDS_ck 
   ); 

This whole section serves to output the video signal that gets generated by the DSO module, allowing us to also use the FPGA board as a standalone oscilloscope unit:

   myuart : entity work.simple_uart 
 
         port map( 
               clk => clk_50, 
               reset => sys_reset, -- active low 
               txdata => ADC_lowspeed_raw, 
               --txready => ser_txready, 
               txgo => open, 
               --rxdata => ser_rxdata, 
               --rxint => ser_rxint, 
               txint => open, 
               rxd => slave_rx_i, 
               txd => slave_tx_o 
         ); 
end architecture; 

Finally, the simple UART implementation that allows the DSO module to communicate with our C++ application.

The UART is configured to work at a baud rate of 19,200, 8 bits, 1 stop bit, and no parity. After building this VHDL project and programming the FPGA board with it, we can connect to it over this serial connection.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.147.124