RS232 dumper

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in February 2013.

I needed a way to monitor what was going on in a very fast clock domain (256MHz). So here's a module I wrote to capture upto 18 bits @ 256 MHz then send them down the serial port as ASCII ones and zeros. An extra NL is printed between capture blocks.

The output can then be captured using a generic terminal emulation program.

Please note that I haven't done any real verification on this, and am not sure that the first and last words are most probably not accurate

Source

This is set up to capture "data" using clk_data as the clock, then output the RS232 using clk_64 (64MHz). Baud rate is set by the clock date and bit_div_max. With a 64MHz clock it is 64,000,000/1110 = 57657 bps.

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Description: Capture data and send it down the serial port
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

library UNISIM;
use UNISIM.VComponents.all;

entity rs232_dumper is
    Port ( clk_data : in  STD_LOGIC;
           data : in  STD_LOGIC_VECTOR (17 downto 0);
           clk_64 : in  STD_LOGIC;
           rs232_xmit : out  STD_LOGIC);
end rs232_dumper;

architecture Behavioral of rs232_dumper is
   -- for the data capture
   signal write_data    : std_logic_vector(17 downto 0);
   signal write_enable  : std_logic;
   signal write_address : std_logic_vector( 9 downto 0);
   signal address_write : unsigned( 9 downto 0)         := (others => '0');
   signal address_read  : unsigned( 9 downto 0)         := (others => '0');
   signal go           : std_logic := '1';
   signal sending_sr   : std_logic_vector(16 downto 0);
   signal again        : std_logic := '1';
   signal pause        : std_logic := '1';
   signal xmit_sr      : std_logic_vector( 9 downto 0) := (others => '1');
   signal busy_sr      : std_logic_vector(12 downto 0) := (others => '1');
   signal read_data    : std_logic_vector(17 downto 0);
   signal read_address : std_logic_vector( 9 downto 0);
   signal bit_count    : std_logic_vector( 4 downto 0) := (others => '1');
   signal bit_div      : unsigned(11 downto 0) := "000000000000";
   constant bit_div_max : unsigned(11 downto 0) := "000000000000" + 1110;
begin
   RAMB16_S18_S18_inst : RAMB16_S18_S18
   generic map (
      INIT_A => X"00000",
      INIT_B => X"00000",
      SRVAL_A => X"00000", 
      SRVAL_B => X"00000", 
      WRITE_MODE_A => "WRITE_FIRST",
      WRITE_MODE_B => "WRITE_FIRST",
      SIM_COLLISION_CHECK => "ALL", 
      INIT_00 => X"00000000000000000000000000000000000000000000000000000000000000FF")
   port map (
      ENA   => '1',
      DOA   => open,
      DOPA  => open,
      ADDRA => write_address, 
      CLKA  => clk_data,
      DIA   => write_data(15 downto 0), 
      DIPA  => write_data(17 downto 16),
      SSRA  => '0',   
      WEA   => write_enable,      

      DOB   => read_data(15 downto 0), 
      DOPB  => read_data(17 downto 16),
      ADDRB => read_address,  
      CLKB  => clk_64,
      DIB   => (others => '0'),
      DIPB  => (others => '0'),
      ENB   => '1',
      SSRB  => '0',
      WEB   => '0'
   );

capture: process(clk_data)
begin
   -- Capture data when the 'go' signal goes high
   if rising_edge(clk_data) then
      write_data <= data;
      write_address <= std_logic_vector(address_write);
      if address_write = "1111111111" then
         pause <= '1';
      end if;
      
      if address_write = "0000000000" and go = '1' then
         pause <= '0';
      end if;
      
      if pause = '0' then
         write_enable <= '1';
         address_write <= address_write + 1;
      else
         write_enable <= '0';
      end if;
   end if;
end process;

   read_address <= std_logic_vector(address_read);
xmit: process(clk_64)
   begin
      if rising_edge(clk_64) then
         rs232_xmit <= xmit_sr(0);
         go <= '0';
         if bit_div = bit_div_max then
            -- restart the bit ticker
            bit_div <= (others => '0');
            -- update the output shift registers
            xmit_sr <= '1' & xmit_sr(xmit_sr'length-1 downto 1);
            busy_sr <= '0' & busy_sr(busy_sr'length-1 downto 1);
            
            if busy_sr(0) = '0' then               
               -- decide on the byte to send               
               if bit_count = "00000" then
                  -- Send the first bit of the data from memory
                  sending_sr <= read_data(read_data'length-2 downto 0);
                  if read_data(read_data'length-1) = '0' then 
                     xmit_sr <= "1" & x"30" & "0"; -- ASCII '0' + Start and stop bits
                  else
                     xmit_sr <= "1" & x"31" & "0"; -- ASCII '1' + Start and stop bits
                  end if;
                  address_read <= address_read + 1;                  
               elsif bit_count = "10010" then
                  -- Send the CR
                  xmit_sr <= "1" & x"0D" & "0"; -- ASCII CR + Start and stop bits
               elsif bit_count = "10011" then
                  -- Send the New Line
                  xmit_sr <= "1" & x"0A" & "0"; -- ASCII NL + Start and stop bits
               elsif bit_count = "10100" then
                  -- Send the New Line at end of block
                  go      <= '1';
                  xmit_sr <= "1" & x"0A" & "0"; -- ASCII NL + Start and stop bits
                  address_read <= (others => '0');

               elsif bit_count = "10101" then
                  -- Send nothing
                  xmit_sr <= "1" & x"FF" & "1"; -- Idle
               else
                  -- Send the next data bit until all are sent
                  if sending_sr(sending_sr'length-1) = '0' then 
                     xmit_sr <= "1" & x"30" & "0"; -- ASCII '0' + Start and stop bits
                  else
                     xmit_sr <= "1" & x"31" & "0"; -- ASCII '1' + Start and stop bits
                  end if;
                  sending_sr <= sending_sr(sending_sr'length-2 downto 0) & '0';
               end if;
               
               -- Set the busy shift register
               busy_sr <= (others => '1');

               -- If we have finished the byte, what do we do next?
               if bit_count = "10011" and address_read /= "1111111111" then
                  bit_count <= "10101";
               elsif bit_count = "10101" then
                  bit_count   <= "00000";
               else
                  bit_count <= std_logic_vector(unsigned(bit_count) +1);
               end if;
            end if;
         else
            bit_div <= bit_div + 1;
         end if;
      end if;
   end process;   
end Behavioral;

Sample Output

Here is an example of me capturing a 256MHz clock signal, using look up tables to create a delay line that is then sampled, giving about 0.5ns resolution.

Bit 17 is hardwired to 0, but you can see that bits 2, 9, 15 and 14 are less than perfect.... some more work is needed!

011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000110
011010011110000110
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010010110000101
011010010110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000110
011010011110000110
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010010110000101
011010010110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000110
011010011110000110
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000110
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000110
011010011110000110
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000110
011010011110000110
011010011110000110
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101
011010011110000101
011010011110000101
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000111
011010011110000101

Personal tools