• 0
Archana Narayanan

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



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;

Library UNISIM;
use UNISIM.vcomponents.all;

use UNIMACRO.vcomponents.all;


entity top_module is

	      RxD          : IN STD_LOGIC;
    RxData       : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
		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---------------------------------------------------------------    
  if RxData = "01110011" then
   start <= '1' ;
   RxData = "01110000" then 
   start <= '0';
   else start <= '0';
 end if;
  end process;
	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

   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;
   RxData <= rxshiftreg(8 DOWNTO 1);
   PROCESS (clk)
      IF (clk'EVENT AND clk = '1') THEN
         IF (reset = '1') THEN
            state <= '0';
            bitcounter <= "0000";
            counter <= "00000000000000";
            samplecounter <= "00";
            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;
   PROCESS (clk)
      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';
                  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';
                  inc_samplecounter <= '1';
               END IF;
            WHEN OTHERS =>
               nextstate <= '0';
         END CASE;
      END IF;
  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. 

Share this post

Link to post
Share on other sites

5 answers to this question

Recommended Posts

  • 0
12 hours ago, Archana Narayanan said:

however I'm unable to use this for control


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.

Edited by zygot

Share this post

Link to post
Share on other sites
  • 0

@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?


Share this post

Link to post
Share on other sites
  • 0

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. :)

Edited by Archana Narayanan

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now