I'm trying to design a rs232 receiver in VHDL : I send numbers with a python script that it have to catch and show to some leds. I hope to have understood how RS232 works and went to work to make that design. The design doesn't behave the way I hope it would and I wonder if someone could help me identify my mistakes.
Of course I went to look how serial receiver works. But as a begineer, I often feel overwhelmed with the solution proposed (exemple : VHDL RS-232 Receiver" or even worse : https://www.nandland.com/vhdl/modules/module-uart-serial-port-rs232.html), i lack the vocabulary and experience to understand what is going on in there.
I made this design on quartus II web edition:
the entity at the bottom just latches to any data coming through the rs232 input to insure the python script is actually doing something.
with these two files : rs232_test
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity rs232_receiver is
port (
clock : in std_logic;
r : in std_logic;
reset : in std_logic;
data : out std_logic_vector (7 downto 0)
);
end rs232_receiver;
architecture rs232_receiver_arch of rs232_receiver is
signal data_buffer : std_logic_vector (12 downto 0);
signal state : integer; -- 1000 => idle;
begin
process
begin
wait until rising_edge (clock);
if (reset = '0') then
if (state = 1000) then
if (r = '0') then
state <= 0; -- startbit as been detected => time to READ !
end if;
elsif (state < 13 and state > -1) then
data_buffer(state) <= r;
state <= state + 1;
else
state <= 1000; -- go back to idle
data <= data_buffer(7 downto 0);
data_buffer <= (others => '0');
end if;
else
data_buffer <= (others => '0');
data <= (others => '0');
state <= 1000;
end if;
end process;
end rs232_receiver_arch;
clock ajustement (raw clock is 24 MHz, I hope that the way i made this divider, output is 1200 Hz which is i believe a baud rate of 1200).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity div1000 is
port (
clock : in std_logic;
clockOut : out std_logic
);
end div1000;
architecture div1000_arch of div1000 is
signal count : integer;
begin
clockOut <= '1' when count < 10000 else '0';
process begin
wait until rising_edge (clock);
if (count > 19999 or count < 0) then
count <= 1;
else
count <= count + 1;
end if;
end process;
end div1000_arch;
I load number with this python script :
# -*- coding: utf-8 -*-
"""
Created on Thu May 2 14:52:12 2019
@author: nathan hj ragot
"""
import time
import serial
import serial.tools.list_ports
print ("hello world !")
# initialisation des variables
port = "" # port choisit
ports = [] # ports listes
# recherche et choix du port
print ("merci de rentrer le nom d'un port :")
print ("ps : automatiquement, le script a detecte ces ports :")
print ("**************")
ports = serial.tools.list_ports.comports()
for i in range (len(ports)):
print ("-> [" + str(i) + "] : " + str (ports[i]))
print ("**************")
port = input("? votre choix :")
print ("ok cool")
# open serial port
ser = serial.Serial(
port=port,
baudrate=1200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_TWO,
bytesize=serial.EIGHTBITS
)
print(ser.isOpen())
#start writing
ser.write(bytearray([255]))
for i in range(15):
input("press enter to print " + str(i))
ser.write (bytearray([i]))
#stop writing
ser.close()
print(ser.isOpen())
print ("bye")
I was expecting that every time I press enter on my keyboard, the python script would send a byte to my fpga board and the design would latch on the number and show it to the leds. Instead, the leds flash to some random places which do not correspond to the number sent then immediatly turn off.