Jump to content
  • 0

Sending a ASCII character from PC to FPGA through UART to control other processes in FPGA


Archana Narayanan

Question

Hello, 

I am trying to send a character to FPGA from PC hyper terminal , for eg : 's' to start other processes in FPGA like initiating generation of CCD signals and sampling ADC et al and a different ascii character to stop the processes.

I am able to send a ASCII character from PC hyper terminal and receive binary value it on FPGA LED's however I'm unable to use this for control. 

Please find my top level code below. 'Start' signal is to be controlling the initiation of other processes. 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

Library UNIMACRO;
use UNIMACRO.vcomponents.all;

use IEEE.MATH_REAL.ALL;
-----------------------------------------------------

entity top_module is

	port(
	--------------------UART_GUI-------------------------------
	
	      RxD          : IN STD_LOGIC;
    RxData       : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
	---COMMON INPUTS---
		clk, rst : in std_logic;
		--send_ccd : in std_logic;---------------CCD control
                SH,ICG,master_ccd_clock : out std_logic;
    ----FOR AD7980--------
		--sample: in std_logic; -------------- to start sampling
		samp_ind: out std_logic;---------------indicates sampling in process
		
		adc_cnv : out std_logic;---------------cnv for AD7980
		adc_clk : inout std_logic;--------------SPI clock
		adc_miso : in std_logic;------------------output from AD7980
	-------FIFO SIGNALS--------
		WriteEn	, ReadEn : in std_logic; -------------fifo controls
		full,  empty : out std_logic ------------------indicates fifo status

	);
end top_module;

architecture structural of top_module is
----------------------------------------------------------------------------UART CONTROL GUI-------------------------------------
 component receiver IS
   PORT (
      clk          : IN STD_LOGIC;
      reset        : IN STD_LOGIC;
      RxD          : IN STD_LOGIC;
      RxData       : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0)
   );
END component receiver;
----------------------------------------FIFO COMPONENT DECLARATION -----------------------------------------------------------------
 component fifo is
  port (
    reset_rtl_0 : in STD_LOGIC;
    clk_100MHz : in STD_LOGIC;
    full_0 : out STD_LOGIC;
    din_0 : in STD_LOGIC_VECTOR ( 15 downto 0 );
    wr_en_0 : in STD_LOGIC;
    empty_0 : out STD_LOGIC;
    dout_0 : out STD_LOGIC_VECTOR ( 15 downto 0 );
    rd_en_0 : in STD_LOGIC
  );
  end component fifo;
 -------------------------------------------------------------------------------------------------------------------------- 
  
signal 	fifo_data_out	: STD_LOGIC_VECTOR (15 downto 0);
signal adc_out : std_logic_vector(15 downto 0);
signal start :std_logic;

-------------------------UART_RX_FOR CONTROL_ OF_PROCESSES---------------------------------------------------------------    
    process(Clk,RxData)
    begin
  if RxData = "01110011" then
   start <= '1' ;
   elsif 
   RxData = "01110000" then 
   start <= '0';
   else start <= '0';
 end if;
  end process;
    
    
    --------------------AD7980PORTMAP----------------------------------------------------------------------------------
	AD7980 : entity work.AD7980 
	
	port map (
     clock   => clk,
    sample  => start,

    -- data output
    Dout   => adc_out(15 downto 0),
    samp_ind  => samp_ind,
    -- ADC connection
    adc_miso => adc_miso,
    adc_cnv  => adc_cnv,
    adc_clk  =>adc_clk 
    );
---------------------------------------------FIFO PORTMAP----------------------------------------------------------------
fifo_i: component fifo
         port map (
          clk_100MHz => clk,
          din_0(15 downto 0) => adc_out(15 downto 0),
          dout_0(15 downto 0) => fifo_data_out(15 downto 0),
          empty_0 => empty,
          full_0 => full,
          rd_en_0 => ReadEn,
          reset_rtl_0 => rst,
          wr_en_0 => WriteEn
        );
                    

ccd_control : entity work.TCD1103GFG
port map (
clock    => clk,
      send => start,    
     SH => SH,
     ICG => ICG,
     master_ccd_clock => master_ccd_clock);
     ---------------------------------------------------------------UART GUI CONTROL---------------------------------------
     
     uart_gui : entity work.receiver 
     
     port map (
       
        clk          => clk,
        reset        => rst,
        RxD          => RxD,
        RxData       => RxData 
     );
end structural;

Here is the UART receiver open source code I'm using that works


LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

ENTITY receiver IS
   PORT (
      clk          : IN STD_LOGIC;
      reset        : IN STD_LOGIC;
      RxD          : IN STD_LOGIC;
      RxData       : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0)
   );
END receiver;

ARCHITECTURE behavioural OF receiver IS
   SIGNAL shift               : STD_LOGIC;
   SIGNAL state               : STD_LOGIC;
   SIGNAL nextstate           : STD_LOGIC;
   SIGNAL bitcounter          : STD_LOGIC_VECTOR(3 DOWNTO 0);
   SIGNAL samplecounter       : STD_LOGIC_VECTOR(1 DOWNTO 0);
   SIGNAL counter             : STD_LOGIC_VECTOR(13 DOWNTO 0);
   SIGNAL rxshiftreg          : STD_LOGIC_VECTOR(9 DOWNTO 0);
   SIGNAL clear_bitcounter    : STD_LOGIC;
   SIGNAL inc_bitcounter      : STD_LOGIC;
   SIGNAL inc_samplecounter   : STD_LOGIC;
   SIGNAL clear_samplecounter : STD_LOGIC;
   
   constant clk_freq: integer := 100000000;
   constant baud_rate :integer := 9600;
   constant div_sample :integer := 4;
   constant div_counter :integer := (clk_freq/(baud_rate*div_sample));
   constant mid_sample : integer := (div_sample/2);
   constant div_bit : integer := 10;
   
BEGIN
   
   RxData <= rxshiftreg(8 DOWNTO 1);
   
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         IF (reset = '1') THEN
            state <= '0';
            bitcounter <= "0000";
            counter <= "00000000000000";
            samplecounter <= "00";
         ELSE
            counter <= counter + "00000000000001";
         if (counter>= div_counter - 1) then 
               counter <= "00000000000000";
               state <= nextstate;
               IF (shift = '1') THEN
                  rxshiftreg <= (RxD & rxshiftreg(9 DOWNTO 1));
               END IF;
               IF (clear_samplecounter = '1') THEN
                  samplecounter <= "00";
               END IF;
               IF (inc_samplecounter = '1') THEN
                  samplecounter <= samplecounter + "01";
               END IF;
               IF (clear_bitcounter = '1') THEN
                  bitcounter <= "0000";
               END IF;
               IF (inc_bitcounter = '1') THEN
                  bitcounter <= bitcounter + "0001";
               END IF;
            END IF;
         END IF;
      END IF;
   END PROCESS;
   
   
   PROCESS (clk)
   BEGIN
      IF (clk'EVENT AND clk = '1') THEN
         shift <= '0';
         clear_samplecounter <= '0';
         inc_samplecounter <= '0';
         clear_bitcounter <= '0';
         inc_bitcounter <= '0';
         nextstate <= '0';
         CASE state IS
            WHEN '0' =>
               IF (RxD = '1') THEN
                  nextstate <= '0';
               ELSE
                  nextstate <= '1';
                  clear_bitcounter <= '1';
                  clear_samplecounter <= '1';
               END IF;
            WHEN '1' =>
               nextstate <= '1';
               IF (samplecounter = (mid_sample - 1)) THEN
                  shift <= '1';
               END IF;
               IF (samplecounter = (div_sample - 1)) THEN
                  IF (bitcounter = (div_bit - 1)) THEN
                     nextstate <= '0';
                  END IF;
                  inc_bitcounter <= '1';
                  clear_samplecounter <= '1';
               ELSE
                  inc_samplecounter <= '1';
               END IF;
            WHEN OTHERS =>
               nextstate <= '0';
         END CASE;
      END IF;
   END PROCESS;
  end behavioural;

I'm unsure if the issue is because of the number of clock cycles for which the character 's' exists. Please help me understand the miss here. 

Link to comment
Share on other sites

6 answers to this question

Recommended Posts

12 hours ago, Archana Narayanan said:

however I'm unable to use this for control

And....

I have this sense that if you keep describing what you did you will answer your own question. I don't have enough information yet to help. [I confess that I haven't bothered to read through your code]

Verbalizing problems, if you go into enough detail,  is often a fairly reliably way to resolve them. Sometimes it helps to have someone throw in a good question or two.

Link to comment
Share on other sites

@Archana Narayanan,

Try working this through from one end to the other. 

Do you know that your PC->FPGA link works?  I usually debug this link by first making sure the transmit FPGA->PC link works.  That will verify that your serial port is using the right pin for transmit.  Once I know FPGA->PC works, I'll typically composing a PC->FPGA->PC design together.  The first time I do this, I place no logic between RX and TX.  This verifies that I have the right transmit pin.  (Be aware, the labels on a lot of Digilent's schematics are misleading!)    The second time I do this I use a serial decoder followed by a serial encoder.  This will verify that your serial receiver works.

Once you know both work, then let's go back to simulation: can you simulate your entire design end to end before placing it onto your board at all?

Dan

Link to comment
Share on other sites

Hi @D@n,

My PC-FPGA link works fine since I had this tested by sending characters to FPGA and displaying them on the LED's. Then,I also made sure I tried a simple UART transmitter receiver code to send and read-back the same character .This ensured the PC-FPGA-PC link works fine as well.

Hi @jpeyron,

As suggested,since I wanted to control all the  processes (ADC,CCD,FIFO,UART), I tested them one at a time. I replaced the switch control for CCD, then ADC and so on by a UART(PC->FPGA) receiver process. It seemed to work alright however I encountered a problem when I automated the reset switch.

On 2/11/2019 at 12:16 PM, Archana Narayanan said:

process(Clk,RxData) begin if RxData = "01110011" then start <= '1' ; elsif RxData = "01110000" then start <= '0'; else start <= '0'; end if; end process;

So, my UART receiver code here has a reset input. All the reset inputs in multiple parts of my code were controlled by one UART-RX process. 

I could start the processes with an ASCII input from hyperterminal and stop it. But when I reset it,with say 'r' from the hyperterminal, I wasn't able to resume .  After stumbling on it for a while, I realised, this was since the UART_RX(PC->FPGA link) in itself was reset and there was no way I could resume processes using UART link. A rather silly miss of course.

 I removed the reset in PC-> FPGA UART link and the problem seems to be resolved. 

Thanks y'all for your inputs. :)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...