El protocolo RS232 (por sus siglas en inglés Recommended Standard 232) es una norma creada en 1962 y que es reconocida mundialmente. El protocolo ha tenido cambios a lo largo del tiempo, sin embargo, en su forma más simple se requieren únicamente de 10 bits de transferencia:
- 1 bit de inicio (activo en bajo)
- 8 bits de datos
- 1 bit de paro (activo en alto)
La línea se mantiene en ‘1’ lógico mientras está en reposo.
La librería utiliza esa configuración para implementar el protocolo. La conexión entre los dispositivos se hace de la siguiente manera:
Gracias a la concurrencia del FPGA se pueden conectar múltiples dispositivos y trabajar con ellos en paralelo:
Los puertos que componen a la librería son:
- FPGA_CLK: Puerto genérico de tipo entero donde se especifica la frecuencia en Hertz.
- BAUD_RS232: Puerto genérico de tipo entero donde se especifica la velocidad de transferencia en Baudios.
- CLK: Puerto de entrada de la señal de reloj.
- RX y TX: Puerto de recepción y transmisión que forman parte del estándar del protocolo.
- DATAIN: Puerto de 8 bits donde se colocará el byte con la información a enviar.
- DOUT: Puerto de 8 bits que muestra el byte recibido.
- TX_INI: Puerto de 1 bit que inicia la transmisión.
- TX_FIN: Puerto de 1 bit que indica el fin de la transmisión.
- RX_IN: Puerto de 1 bit que indica el fin de recepción.
La librería deberá ser declarada como componente en el TOP de nuestro diseño.
component RS232 is generic ( FPGA_CLK : integer := 50000000; BAUD_RS232 : integer := 9600 ); port( CLK : in std_logic; RX : in std_logic; TX_INI : in std_logic; DATAIN : in std_logic_vector(7 downto 0); TX_FIN : out std_logic; TX : out std_logic; RX_IN : out std_logic; DOUT : out std_logic_vector(7 downto 0) ); end component RS232;
En la instancia se deberá especificar la frecuencia de reloj y los baudios del protocolo.
u1 : rs232 generic map( FPGA_CLK => 50000000, BAUD_RS232 => 3000000 ) port map( CLK => CLK, RX => RX, TX_INI => tx_in_s, TX_FIN => tx_fin_s, TX => TX, RX_IN => rx_in_s, DATAIN => datain_s, DOUT => dout_s );
El código debe contener las máquinas de estados para controlar la recepción y transmisión, por ejemplo para realizar la recepción se deben monitorear las señales “RX_IN” y dependiendo el byte recibido mostrado en “DOUT” se encenderán o apagarán los LEDs.
process(CLK) begin if rising_edge(CLK) then if edo = 0 then if rx = '1' then if dout = x"0A" then edo <= 1; elsif dout = x"0b" then edo <= 2; else edo <= 3; end if; else edo <= 0; end if; elsif edo = 1 then LEDS <= x"0A"; edo <= 0; elsif edo = 2 then LEDS <= x"0B"; edo <= 0; elsif edo = 3 then LEDS <= x"00"; edo <= 0; end if; end if;
Ejemplo de transmisión:
process(CLK) begin if rising_edge(CLK) then if edo = 0 then if SW = "01" then edo <= 1; elsif SW = "11" then edo <= 3; else edo <= 0; end if; elsif edo = 1 then datain <= x"AA"; edo <= 2; elsif edo = 2 then if tx_fin = '1' then edo <= 0; tx_ini <= '0'; else edo <= 2; tx_ini <= '1'; end if; elsif edo = 3 then datain <= x"FF"; edo <= 4; elsif edo = 4 then if tx_fin = '1' then edo <= 0; tx_ini <= '0'; else edo <= 4; tx_ini <= '1'; end if; end if; end if; end process;