Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

RS-232 between computer and virtex5 FPGA

Status
Not open for further replies.

Simon2

Junior Member level 2
Junior Member level 2
Joined
Jul 25, 2012
Messages
20
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Activity points
1,614
Hi guys,

I'm quite new to FPGA's and now I'm trying to make a serial rs232 interfase from my computer to my virtex 5 ml507 FPGA. I'm trying to light some LEDs depending on the character I type in HYPERTERMINAL on the computer. I think there is nothing wrong with the serial connection, because when I switch the non-configured FPGA on, the words of the display appear in hyperterminal.

So the problem should be in the code (see below), I think. The problem could be in the baud speed, I calculated this as 3437 because I have 9600 bits/s (done by the configuration of the hyperterminal) and use a 33 MHz clock signal. What would be my mistake? I'm totally stuck...

Thanks in advance :grin:,

Simon

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

--SIMONS RS232 project
ENTITY RS232 IS
PORT(
CLK : IN STD_LOGIC;
RS232_IN : IN STD_LOGIC;
LED_DISPLAY : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
end RS232;


ARCHITECTURE behavior of RS232 IS

--Numbers
CONSTANT zero : STD_LOGIC_VECTOR := "0000001";
CONSTANT one : STD_LOGIC_VECTOR := "0111101";
CONSTANT two : STD_LOGIC_VECTOR := "0010010";
CONSTANT three : STD_LOGIC_VECTOR := "0011000";
CONSTANT four : STD_LOGIC_VECTOR := "0101100";
CONSTANT five : STD_LOGIC_VECTOR := "1001000";
CONSTANT six : STD_LOGIC_VECTOR := "1000000";
CONSTANT seven : STD_LOGIC_VECTOR := "0011101";
CONSTANT eight : STD_LOGIC_VECTOR := "0000000";
CONSTANT nine : STD_LOGIC_VECTOR := "0001000";

--Letters
CONSTANT letter_a : STD_LOGIC_VECTOR := "0000100";
CONSTANT letter_b : STD_LOGIC_VECTOR := "1100000";
CONSTANT letter_c : STD_LOGIC_VECTOR := "1000011";
CONSTANT letter_d : STD_LOGIC_VECTOR := "0110000";
CONSTANT letter_e : STD_LOGIC_VECTOR := "1000010";
CONSTANT letter_f : STD_LOGIC_VECTOR := "1000110";
CONSTANT letter_g : STD_LOGIC_VECTOR := "1000000";
CONSTANT letter_h : STD_LOGIC_VECTOR := "0100100";
CONSTANT letter_i : STD_LOGIC_VECTOR := "0111101";
CONSTANT letter_j : STD_LOGIC_VECTOR := "0110001";
CONSTANT letter_l : STD_LOGIC_VECTOR := "1100011";
CONSTANT letter_n : STD_LOGIC_VECTOR := "0000101";
CONSTANT letter_o : STD_LOGIC_VECTOR := "0000001";
CONSTANT letter_p : STD_LOGIC_VECTOR := "0000110";
CONSTANT letter_s : STD_LOGIC_VECTOR := "1001000";
CONSTANT letter_u : STD_LOGIC_VECTOR := "0100001";
CONSTANT letter_y : STD_LOGIC_VECTOR := "0001000";
CONSTANT letter_z : STD_LOGIC_VECTOR := "0010010";


CONSTANT BAUD : INTEGER := 3157;


SIGNAL SHIFT_REG : STD_LOGIC_VECTOR(7 DOWNTO 0);

SIGNAL START_STOP : STD_LOGIC := '0';

BEGIN

PROCESS
variable timer_cnt: integer range 0 to 100000;
variable char_cnt: integer range 0 to 10;
BEGIN

WAIT UNTIL(clk'EVENT) AND (clk = '1');

--IDLE State
IF(RS232_IN = '0' AND START_STOP = '0')THEN
--Reset Counters
char_cnt := 0;
timer_cnt := 0;
--Start RS232 Capture Process
START_STOP <= '1';
ELSIF(RS232_IN = '1' AND START_STOP = '0')THEN

CASE SHIFT_REG is
--ASCII -> Number, Decoding
WHEN x"30" => LED_DISPLAY <= zero;
WHEN x"31" => LED_DISPLAY <= one;
WHEN x"32" => LED_DISPLAY <= two;
WHEN x"33" => LED_DISPLAY <= three;
WHEN x"34" => LED_DISPLAY <= four;
WHEN x"35" => LED_DISPLAY <= five;
WHEN x"36" => LED_DISPLAY <= six;
WHEN x"37" => LED_DISPLAY <= seven;
WHEN x"38" => LED_DISPLAY <= eight;
WHEN x"39" => LED_DISPLAY <= nine;
--ASCII -> Letter, Decoding
WHEN x"61" => LED_DISPLAY <= letter_a;
WHEN x"62" => LED_DISPLAY <= letter_b;
WHEN x"63" => LED_DISPLAY <= letter_c;
WHEN x"64" => LED_DISPLAY <= letter_d;
WHEN x"65" => LED_DISPLAY <= letter_e;
WHEN x"66" => LED_DISPLAY <= letter_f;
WHEN x"67" => LED_DISPLAY <= letter_g;
WHEN x"68" => LED_DISPLAY <= letter_h;
WHEN x"69" => LED_DISPLAY <= letter_i;
WHEN x"6A" => LED_DISPLAY <= letter_j;
WHEN x"6C" => LED_DISPLAY <= letter_l;
WHEN x"6E" => LED_DISPLAY <= letter_n;
WHEN x"6F" => LED_DISPLAY <= letter_o;
WHEN x"70" => LED_DISPLAY <= letter_p;
WHEN x"73" => LED_DISPLAY <= letter_s;
WHEN x"75" => LED_DISPLAY <= letter_u;
WHEN x"79" => LED_DISPLAY <= letter_y;
WHEN x"7A" => LED_DISPLAY <= letter_z;
--Clear 7 Seg When Others Pressed
WHEN OTHERS => LED_DISPLAY <= "1111111";
END CASE;

END IF;

--Start Getting Serial Data
IF(START_STOP = '1')THEN
IF(timer_cnt = BAUD) THEN
--Update Counter
timer_cnt := 0;

--Update Shift Register
SHIFT_REG <= RS232_IN & SHIFT_REG(7 DOWNTO 1);

--Is 8th Bit?
IF(char_cnt = 7)THEN
START_STOP <= '0';
ELSE
char_cnt := char_cnt + 1;
END IF;
ELSE
timer_cnt := timer_cnt + 1;
END IF;
END IF;

END PROCESS;

END behavior;

- - - Updated - - -

In the code above, the value 3437 isn't used yet, but that makes no difference. Nothing appears when i enter a character in hyperterminal
 

Several comments:

You have a whole bunch of things being assigned inside a single process. Although this might work, it makes things a lot harder to figure out.
Indenting would help to figure out where IF blocks start and end.
You are correct that 3437 would give you a 9600 Hz clock, however you are using a divider of 3157.
Generally, for serial communications, a faster clock is used to sample incoming data (16x, for example). That way you can make sure you are sampling in the middle of a bit, rather than near the transition. With a clock equal to the data rate you can't guarantee setup and hold times because the two signals are asynchronous.
 

Using a 'wait' command in a process is not typically used, except for test benches. It is more common to define a clocked process, as you define above, using:

Code:
process (clik)
begin
  if rising_edge(clk) then             -- == if (clk'event and clk='1') then
    ....
  end if;
end process

A good starting point of serial communication, including test benches, can be found in this post here:
https://www.edaboard.com/threads/156656/

A direct link to the code mentioned:

I expect you are not using a test bench to check your code. Be advised that a test bench/simulation is, more or less, a necessity. Without a test bench/simulation, finding out how/if your code operates correctly is very hard.
 

Thanks for the reply's guys, in the meantime I made it work already ;-)
I'm sending data from hyperterminal to the FPGA with the rs-232 to light some LEDs, very basic, I know ;)
If anyone would have the same problem I had, do contact me on simonvandenberge@hotmail.be
I made the same code for a PS/2 keyboard aswell.
 
please share your solution with all of us. Post your files here.

Thanks
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top