Skip to content

RS232

1. Introtroducción

Diagrama de tiempo

Image title

Figura 1. Diagrama a bloques.

Image title

Figura 3. Diagrama como caja negra.

2. Códigos

2.1. Multiplexor

mux_tx.v
module mux_tx(
  input [7:0] d_i,     // Datos a transmitir
  input       pbit_i,  // Bit de paridad
  input [3:0] sel_i,   // Selector de bit
  output  reg tx_o     // Transmision
);

  always @(d_i, pbit_i, sel_i) begin
    case (sel_i)
      4'b0000 : tx_o = 1'b1;    // Stop bit
      4'b0001 : tx_o = 1'b0;    // Start bit
      4'b0010 : tx_o = d_i[0];  // LSB de d_i 
      4'b0011 : tx_o = d_i[1];
      4'b0100 : tx_o = d_i[2];
      4'b0101 : tx_o = d_i[3];
      4'b0110 : tx_o = d_i[4];
      4'b0111 : tx_o = d_i[5];
      4'b1000 : tx_o = d_i[6];
      4'b1001 : tx_o = d_i[7];  
      4'b1010 : tx_o = pbit_i;  // Bit de paridad
      default : tx_o = 1'b1;    // Stop bit
    endcase
  end

endmodule

2.2. Paridad

parity.v

2.3. Divisor de frecuencia

\[ \text{BAUD} = \frac{1}{9600} \cdot 100 \text{MHz} - 1 = 10415.66 \approx 10415 \]
\[ \log_{2} (10415) = 13.34 \approx 14 \]
freq_div.v

2.4. FSM transmisión

Image title

Figura 3. Máquina de estados de transmisión con protocolo Rs232.
fsm_tx.v
module fsm_tx (
  input            rst_i,   // Reset del sistema
  input            clk_i,   // Reloj del sistema
  input            sttx_i,  // Start
  input            z_i,     // Base de tiempo
  input            psel_i,  // Selector de paridad
  output reg [3:0] sel_o,   // Habilitador de mux
  output reg       eot_o    // Fin de transmision
);

  localparam [3:0] s0  = 4'b0000, // Wait y stop bit
                   s1  = 4'b0001, // Sincronizacion
                   s2  = 4'b0010, // Start bit
                   s3  = 4'b0011, // D0
                   s4  = 4'b0100, // D1
                   s5  = 4'b0101, // D2
                   s6  = 4'b0110, // D3
                   s7  = 4'b0111, // D4
                   s8  = 4'b1000, // D5
                   s9  = 4'b1001, // D6
                   s10 = 4'b1010, // D7
                   s11 = 4'b1011; // Parity

  reg [3:0] present_state, next_state;

  // Logica proximo estado y decodificacion de salida
  always @(sttx_i, z_i, psel_i, present_state) begin
    next_state = present_state;
    sel_o = 4'b0000; eot_o = 1'b0;
    case (present_state)
      s0 : begin // Wait y stop bit
             sel_o = 4'b0000; eot_o = 1'b1;
             if (sttx_i)
               next_state = s1;
           end
      s1 : begin // Sincronizacion
             sel_o = 4'b0000; eot_o = 1'b0;
             if (z_i)
               next_state = s2;
           end
      s2 : begin // Start bit
             sel_o = 4'b0001; eot_o = 1'b0;
             if (z_i)
               next_state = s3;
           end
      s3 : begin // D0
             sel_o = 4'b0010; eot_o = 1'b0;
             if (z_i)
               next_state = s4;
           end
      s4 : begin // D1
             sel_o = 4'b0011; eot_o = 1'b0;
             if (z_i)
               next_state = s5;
           end
      s5 : begin // D2
             sel_o = 4'b0100; eot_o = 1'b0;
             if (z_i)
               next_state = s6;
           end
      s6 : begin // D3
             sel_o = 4'b0101; eot_o = 1'b0;
             if (z_i)
               next_state = s7;
           end
      s7 : begin // D4
             sel_o = 4'b0110; eot_o = 1'b0;
             if (z_i)
               next_state = s8;
           end
      s8 : begin // D5
             sel_o = 4'b0111; eot_o = 1'b0;
             if (z_i)
               next_state = s9;
           end
      s9 : begin // D6
             sel_o = 4'b1000; eot_o = 1'b0;
             if (z_i)
               next_state = s10;
           end
     s10 : begin // D7
             sel_o = 4'b1001; eot_o = 1'b0;
             if (z_i) begin
               if (psel_i)
                 next_state = s11;
               else
                 next_state = s0;
             end
           end
     s11 : begin // Paridad
             sel_o = 4'b1010; eot_o = 1'b0;
             if (z_i)
               next_state = s0;
           end
 default : begin // Regresar a S0 por default
             next_state = s0;
           end
    endcase 
  end

  // Registro de estado
  always @(posedge clk_i, posedge rst_i) begin
    if (rst_i)
      present_state <= s0;
    else
      present_state <= next_state;
  end

endmodule

2.5. Top

rs232_tx.v
module rs232_tx (
  input         rst_i,
  input         clk_i,
  input         sttx_i,  // Start
  input   [7:0] d_i,     // Datos de entrada
  input  [14:0] baud_i,  // Constante de baudios
  input         psel_i,  // Selector de paridad
  output        tx_o,    // Transmision
  output        eot_o    // Fin de transmision
);

  wire       z;
  wire       p; 
  wire [3:0] sel; 

  mux_tx mod_mux_tx (
    .d_i(d_i),
    .pbit_i(p),
    .sel_i(sel),
    .tx_o(tx_o)
  );

  parity_tx mod_parity_tx (
    .d_i(d_i), 
    .pbit_o(p)
  );

  clk_div_tx #(.Width(15)) mod_clk_div_tx(
    .rst_i(rst_i),
    .clk_i(clk_i),
    .en_i(1'b1),
    .baud_i(baud_i),
    .z_o(z)
  );

  fsm_tx mod_fsm_tx (
    .rst_i(rst_i),
    .clk_i(clk_i),
    .sttx_i(sttx_i),
    .z_i(z),
    .psel_i(psel_i),
    .sel_o(sel),
    .eot_o(eot_o)
  );


endmodule

3. Verificación

rs232_tx_tb.v
`timescale 1ns / 100 ps
`include "mux_tx.v"
`include "parity_tx.v"
`include "clk_div_tx.v"
`include "fsm_tx.v"
`include "rs232_tx.v"

module rs232_tx_tb ();
  // Definición de señales de entrada y salida
  reg         rst;
  reg         clk;
  reg         sttx;
  reg   [7:0] d;
  reg  [14:0] baud;
  reg         psel;
  wire        tx;
  wire        eot;

  // Instanciacion del modulo
  rs232_tx dut (
    .rst_i(rst), 
    .clk_i(clk),
    .sttx_i(sttx),
    .d_i(d),
    .baud_i(baud),
    .psel_i(psel),
    .tx_o(tx),
    .eot_o(eot)
  );

  // Generador de reloj de 100 MHz con duty-cycle de 50 %
  always #5 clk = ~clk;

  // Secuencia de reset y condiciones iniciales
  initial begin
    clk = 0; rst = 1; sttx = 0; d = 8'b01110011; baud = 15'd10415; psel = 0; #10;
             rst = 0;                                                        #10;
  end

  initial begin
    // Configuracion de archivos de salida
    $dumpfile("rs232_tx_tb.vcd");
    $dumpvars(0,rs232_tx_tb);

    // Sincronizacion
    #30;

    //Estimulos de prueba
    sttx = 1; #10;
    sttx = 0; #10;

    // Esperar que acabe la transmision
    #(10*10415*11);


    //Estimulos de prueba
    psel = 1; #10;
    sttx = 1; #10;
    sttx = 0; #10;

    // Esperar que acabe la transmision
    #(10*10415*12);

    $display("Test completed");
    $finish;
  end

endmodule;

4. Resultados

Image title

Figura 4. Resultados de simulación en GTKWave de transmisión con protocolo RS232.