0
votes

I have an sensor it has an unlocked byte sequence which needs to be sent to it to unlock it and then it can receive the other command data. The sensor receive data at a baudrate of 115200 bps, 8 data bits, even parity, 2 stop bits. and before receiving any command data( used to set parameters) It needs to recieve d4 (hexadecimal number, byte) 10 times at an interval of 1ms. I send the d4 converted into bits 11010100 added with parity and stop bits becomes 11010100011 to the TX port of uart at the baud rate of 115200 but how to create a delay between two d4 data byte sent ? I am writing the code if not clear please let me know I would put more details.

entity Uart_tx is

port (

  TX : out std_logic;
  clk_in : in std_logic;
  but_div_clk : out std_logic;
  clk_in_2 : in std_logic

);

end Uart_tx;

architecture Behavioral of Uart_tx is

  signal tx_clk : std_logic := '0';
  signal clk_1Khz : std_logic := '0';
  signal q : unsigned(8 downto 0) := (others => '0');
  signal p : unsigned(8 downto 0) := (others => '0');

  type state_type is (idle, start);
  signal state : state_type;

  signal tick_in : std_logic := '0';

  subtype byte is std_logic_Vector(7 downto 0);
  type byte_array is array(natural range <>) of byte;
  signal data_byte_array : byte_array(1 to 8);

  --  signal curr_byte : std_logic_vector(7 downto 0);
  signal byte_index : unsigned(2 downto 0) := "000";


  subtype reg is std_logic_Vector(10 downto 0);
  type reg_array is array(natural range <>) of reg;
  signal TxDataReg_array : reg_array(1 to 8);

  signal cur_Tx_reg : std_logic_vector(10 downto 0); 
  signal current_reg : unsigned(3 downto 0) := "0001";
  signal count : unsigned (4 downto 0) := (others => '0');

  signal count_d : unsigned (4 downto 0) := (others => '0');
  signal sent_d4 : unsigned (3 downto 0) := (others => '0');

  signal send_d4 : std_logic := '1';
  signal D_4 : std_logic_vector(10 downto 0) :="11000101011"; 

begin
  -- below are random entry ..actual data will come from slv_reg registers.
  data_byte_array(1) <= "10101010"; -- slv_reg0(7 downto 0);
  data_byte_array(2) <= "10101011"; -- slv_reg0(15 downto 8);
  data_byte_array(3) <= "10101010"; -- slv_reg0(23 downto 16);
  data_byte_array(4) <= "10101011"; -- slv_reg0(31 downto 24);
  data_byte_array(5) <= "10101010"; -- slv_reg1(39 downto 32);
  data_byte_array(6) <= "10101011"; -- slv_reg1(47 downto 40);
  data_byte_array(7) <= "10101010"; -- slv_reg1(55 downto 48);
  data_byte_array(8) <= "10101011"; -- slv_reg1(63 downto 56);
  tick_in <= '1';

  ---------------------------------------Clk_div-----------------------------------------

  process ( clk_in ) is 
  begin 
    if clk_in'event and clk_in = '1' then

      q <= q + 1;

      tx_clk <= q(8);   --- 58.gdfg/2^8 =~ 230Khz baud rate = 115200 

      but_div_clk <= tx_clk;
    end if;
  end process;

  ---------------------------------------Clk_div------------------------------------------


  ---------------------------------------Clk_div------------------------------------------

  process( clk_in_2 ) is 
  begin 

    if clk_in_2'event and clk_in_2 = '1' then

      p <= p + 1;

      clk_1Khz <= p(7);

    end if;
  end process;

  ---------------------------------------------------------------------------------------

  --------------------------------------TX_Process----------------------------------------   

  process( state, tx_clk , tick_in) is 

    variable parity : std_logic := '0';
    variable curr_byte : std_logic_vector(7 downto 0) := (others => '0');
  begin 

    case state is 

      when idle => TX <= '1';
        if tick_in = '1' then 
          state <= start;
        else 
          TX <= '1';
        end if;

      when start => 

        if send_d4 = '1' then 

          if (rising_edge(clk_1Khz)) then 

            case count_d is
              when "00000" => TX <= D_4(0);
              when "00001" => TX <= D_4(1);
              when "00010" => TX <= D_4(2);
              when "00011" => TX <= D_4(3);
              when "00100" => TX <= D_4(4);
              when "00101" => TX <= D_4(5);
              when "00110" => TX <= D_4(6);
              when "00111" => TX <= D_4(7);
              when "01000" => TX <= D_4(8);
              when "01001" => TX <= D_4(9);
              when "01010" => TX <= D_4(10);
              when others => TX <= '1';
            end case;

            count_d <= count_d +1;
            sent_d4 <= sent_d4 + 1;
            if to_integer(count_d) = 11 then
              count_d <= "00000";
            end if;

            if to_integer(sent_d4) = 10 then 
              send_d4 <= '0' ;    
            end if;
          end if;
        else 
          for i in 1 to 8 loop 

            curr_byte := data_byte_array(i);
            parity := '0';
            for j in curr_byte'range loop
              parity := parity xor curr_byte(j);
            end loop;

            if parity = '0' then
              TxDataReg_array(i) <= "110" & curr_byte ;
            else 
              TxDataReg_array(i) <= "111" & curr_byte ;
            end if;
          end loop;
          cur_Tx_reg <= TxDataReg_array(to_integer(byte_index)+1);
          byte_index <= byte_index + 1;   

          if rising_edge(tx_clk) then     
            case count is
              when "00000" => TX <= cur_Tx_reg(0);
              when "00001" => TX <= cur_Tx_reg(1);
              when "00010" => TX <= cur_Tx_reg(2);
              when "00011" => TX <= cur_Tx_reg(3);
              when "00100" => TX <= cur_Tx_reg(4);
              when "00101" => TX <= cur_Tx_reg(5);
              when "00110" => TX <= cur_Tx_reg(6);
              when "00111" => TX <= cur_Tx_reg(7);
              when "01000" => TX <= cur_Tx_reg(8);
              when "01001" => TX <= cur_Tx_reg(9);
              when "01010" => TX <= cur_Tx_reg(10);
              when others => TX <= '1';
            end case;
            count <= count+1;
            if to_integer(count) = 11 then
              count <= "00000";
              state   <= idle;
              --      TX  <= '1';
            end if;
          end if;         

        end if;

      when others => TX <= '1';
    end case;

  end process;

end Behavioral;
1
This may not synthesize (or even operate) the way you are expecting. You are assigning TX asynchronously in parts of your process, and synchronously in others, and then by 2 different clocks. You should probably clean that up.fru1tbat

1 Answers

0
votes

To get a timed delay you have to implement a counter that ticks off a computed number of clock cycles equal to 1 ms. You then need to insert states into your FSM that activate the counter and wait for it to complete when needed. It is possible to manually calculate the counter value but you can make the tools do the work for you and avoid having magic numbers in your code.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...

constant CLOCK_FREQ   : real := 50.0e6; -- 50 MHz system clock
constant SENSOR_DELAY : real := 1.0e-3; -- 1 ms delay
constant DELAY_COUNT  : natural := integer(CLOCK_FREQ * SENSOR_DELAY);

-- This could be auto calculated with a ceil_log2() function
constant TIMER_SIZE : natural := 16;

signal timer : unsigned(TIMER_SIZE-1 downto 0);
constant DELAY_INIT : unsigned(timer'range)
    := to_unsigned(DELAY_COUNT, timer'length);
...

-- Initialize the timer sometime before you want the delay
timer <= DELAY_INIT;
...

-- Somewhere in your FSM
when WAIT_1MS =>
  timer <= timer - 1;
  if timer = 0 then
    state <= WHATEVER_YOU_WANT_NEXT;
  end if;

This method of using real constants to compute integer values is subject to rounding errors and general floating-point inaccuracies. For these sort of long delays, the small error (typically off-by-one) that could happen isn't usually of concern.

Note that you need to rework your state machine to follow more conventional patterns. You have created a process that mixes pure combinational logic with synchronous. You should not mix the two. You should not have the rising_edge() tests inside your FSM case statement but rather there should be a single if-block evaluating rising_edge() that contains your FSM.

If you need a clock sensitive process then it should only have the clock and an (optional) asynchronous reset in its sensitivity list. Any other pure combinational code should be put in a separate process. In a design such as this that shouldn't be necessary though.

VHDL allows what you have now but synthesis tools expect the use of a more limited style when describing the hardware. You risk having unexpected results if they can handle your code at all.