USB Communication (RS232)

By xantus on Wednesday 17 February 2010 08:01 - Comments (4)
Category: Verilog examples, Views: 5.008

The USB 2.0 capabilities are provided by the FT232RL, which is an USB to UART converter IC. So we just have to write some verilog to create an UART module to interface with the FT232RL for USB communication :) .
The verilog consists of 3 modules: baud_generator, uartrx and uarttx.
Baud Rate Generator
The baud_generator module generats (as expected) the baud clock. It has a parameter for ClkFrequency input and the required baud rate.

C: Baud rate generator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module baud_generator(clk, BaudTick);
// Port declarations
 input clk;        // Clock input
 output BaudTick;  // Baud clock output
 
// Parameters
 parameter ClkFrequency = 50000000; // 50MHz for Bluebird board
 parameter Baud = 115200;           // Baudrate
 parameter BaudGeneratorInc = ((Baud<<12)+(ClkFrequency>>5))/(ClkFrequency>>4);
 
// Internal Variables 
 reg [16:0] BaudGeneratorAcc;
 
// Accumulator
 always @(posedge clk)
  BaudGeneratorAcc <= BaudGeneratorAcc[15:0] + BaudGeneratorInc;
 
// Clock generator
 wire BaudTick = BaudGeneratorAcc[16];
endmodule

Transmitter
The transmitter transmits the data from tx_data on the tx pin. Once data is available on the tx_data port, you have to strobe the ld_tx_data for it to start sending the data. After strobing, the data on the tx_data port may be changed directly (it is buffered internally). The tx_empty pin will go high as soon as transmitting is completed. The code is only capable of sending 8 bits, no parity, and one stopbit.

C: Transmitter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module uarttx (txclk,tx_data,ld_tx_data,tx_out,tx_empty);
// Port declarations
 input txclk;          // Baud Rate Clock
 input ld_tx_data;     // Load data's data from tx_data
 input  [7:0] tx_data; // Transmitting data
 output tx_out;        // Output
 output tx_empty;      // Busy flag
 
// Internal Variables 
 reg [7:0] tx_reg;
 reg tx_empty;
 reg [3:0] tx_cnt;
 reg tx_out;
 
// Initial value's
 initial tx_empty = 1;  // not busy
 initial tx_out = 1;    // idle UART level is high
 
// UART TX logic
always @ (posedge txclk)
 begin
   if (!ld_tx_data)
    begin
     tx_reg   <= tx_data;  // Load data into transmitting register
     tx_empty <= 0;
     tx_cnt <= 8;
    end
 
   if (!tx_empty)
    begin
     tx_cnt <= tx_cnt - 1; // LSB first
     if (tx_cnt == 8)
      begin
       tx_out <= 0;
      end 
     else
      if (tx_cnt < 8) 
       begin
        tx_out <= tx_reg[7-tx_cnt]; // Output bit
       end
      else         // Done transmitting byte
       begin
        tx_out <= 1;
        tx_empty <= 1;
      end
    end
 end
endmodule

Receiver
The receiver receives the UART data from pin rx. Once data is available the rx_empty pin will go low. Strobing the uld_rx_data pin will cause it to unload to the rx_data port, where it is buffered. The receiver is only capable of receiving 8 bits, no parity, and one stopbit.

C: Receiver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
module uartrx (rxclk,uld_rx_data,rx_data,rx_in,rx_empty);
// Port declarations
 input rxclk;           // Baude Rate Clock
 input uld_rx_data;     // Unloads data from rx_data
 output [7:0] rx_data;  // Received data
 input rx_in;           // Input
 output rx_empty;       // Busy flag
 
// Internal Variables 
 reg [7:0] rx_reg;
 reg [7:0] rx_data;
 reg [3:0] rx_cnt;
 reg rx_empty;
 reg rx_d1;
 reg rx_d2;
 reg rx_busy;
 
// Initial value's
 initial rx_empty = 1;
 initial rx_busy = 0;
 
// UART RX logic
 always @ (posedge rxclk)
  begin
   rx_d1 <= rx_in; // Sync data from rx tot rxclk
   rx_d2 <= rx_d1;
   if (!uld_rx_data) begin  // Unload data
     rx_data  <= rx_reg;
     rx_empty <= 1;
   end
   if (!rx_busy && !rx_d2) begin // Find starting bit
     rx_busy <= 1;
     rx_cnt <= 0;
   end
   if (rx_busy) begin 
     if (rx_cnt < 8) begin
       rx_reg[rx_cnt] <= rx_d2; // Receive byte
       rx_cnt <= rx_cnt + 1; 
     end
     else
      begin // Done ^_^
       rx_busy <= 0;
       rx_empty <= 0;
     end
   end 
  end
endmodule

Conclusion
The following verilog may be used to glue the 3 modules together. When compiled for speed, the above (and below) verilog code will use 69 LE's.

C: RS232 peripheral
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module RS232(clk, uld, rx, ld, tx_data, tx, rx_empty, tx_empty, rx_data);
  input clk;            // Clock input (50 MHz)
  input uld;            // Unload RX data
  input rx;             // RX data stream input
  input ld;             // Load TX data 
  input [7:0] tx_data;  // TX data input
 
  output tx;            // TX stream output
  output rx_empty;      // RX buffer flag
  output tx_empty;      // TX buffer flag
  output [7:0] rx_data; // RX data output
 
  uartrx(baud_tick, uld, rx_data, rx, rx_empty);
  uarttx(baud_tick, tx_data, ld, tx, tx_empty);
  baud_generator(clk, baud_tick);
endmodule


http://www.greenbird.info/img.php?h&b=usb-communication&f

Volgende: PS/2 Keyboard Communication 02-'10 PS/2 Keyboard Communication
Volgende: SRAM controller 02-'10 SRAM controller

Comments


By huda, Wednesday 14 April 2010 06:41

hye there,
may i ask u, what is BaudGeneratorInc used for?
thank you

By Tweakers user xantus, Friday 23 April 2010 12:31

hye there,
may i ask u, what is BaudGeneratorInc used for?
thank you
BaudGeneratorInc is the number with which BaudGeneratorAcc increments every clock cycle. This number is calculates so that the frequency of BaudGeneratorAcc[16] equals the desired baudrate

By Hardik, Tuesday 3 January 2012 10:07

Good Afternoon,
Respected sir,
can u plz explain in brief each statement u wrote on your baud_generator module.?
Thank You.

By Susantha, Sunday 13 January 2013 02:33

Similar code is explained in detail in fpga4fun website including the baud_generator.
Good luck!
-Susantha

Comments are closed