tutorial 3 (uart)

Finished the third tutorial from from the Toni T800 YouTube channel.  This one gave me some trouble for a bit because PuTTY was acting a little strange, so I switched to Windows and used the RealTerm serial program that he demonstrates in his video.  In RealTerm you can send a single character by just typing it, while in PuTTY you have to hit Enter; I think hitting Enter sends more info to the board, which was messing up my receiving display. I probably could have messed with PuTTY more, but just went with the software that Toni used.

Anyway, for this one use RealTerm to make it easy: 9600 baud rate, no parity, 1 stop bit.  I also used a USB to RS232 cable to connect to my pc because the DE2 UART output is via RS232 only.

Code here: https://github.com/christopherhays/my-modules

Link to the video:

Here’s a pic of the RealTerm output: I sent an ‘a’, ‘b’, and ‘c’.  All of those sends are from one press of KEY0 each.

screenshot_3

A picture of my DE2 board with the red LEDs showing the ascii code for a ‘d’ that was received.

2017-01-02-14-57-14

 // Christopher Hays
// 12/31/2016 
// tutorial 3, uart on the de2 development board
// using verilog

// set parity to none, no flow control, 9600 baud

module uart(CLOCK_50, KEY, SW, LEDG, LEDR, UART_TXD, UART_RXD);

   input CLOCK_50;
   input [17:0] SW;
   input [3:0] KEY;
   output [7:0] LEDG;
   output [17:0] LEDR;
   output UART_TXD;
   input UART_RXD;
   
   reg [7:0] tx_data, ledg_out, ledr_out;
   reg tx_start = 0;
   wire tx_busy, rx_busy;
   wire [7:0] rx_data;
   
   // connect the modules
   tx T0 (.CLK(CLOCK_50), .START(tx_start), .BUSY(tx_busy), .DATA(tx_data), .TX_LINE(UART_TXD));
   rx R0 (.CLK(CLOCK_50), .RX_LINE(UART_RXD), .DATA(rx_data), .BUSY(rx_busy));

   always@(posedge CLOCK_50) begin
      if (KEY[0] == 0 && tx_busy == 0) begin    // when key0 is pressed and not busy
         tx_data = SW[7:0];                     // set the data and start tx
         tx_start = 1;
         ledg_out = tx_data;
      end
      else
         tx_start = 0;
   end   // end always
   
   always@(negedge rx_busy) begin         // as soon as receiver is not busy
      ledr_out = rx_data;                 // write the data to leds
   end   // end always
   
   assign LEDR = ledr_out;
   assign LEDG = ledg_out;

endmodule


 // UART receiver

module rx(CLK, RX_LINE, DATA, BUSY);
   
   input CLK, RX_LINE;
   
   output [7:0] DATA; 
   output BUSY;

   reg [9:0] datafll;
   reg rx_flag = 0;
   reg busy_out = 0;
   reg [12:0] prescalar = 0;
   reg [3:0] index = 0;
   reg [7:0] data_out;
   
   always@(posedge CLK) begin
   
      if (rx_flag == 0 && RX_LINE == 0) begin   // if we are not receiving
         index = 0;                             // and there is a start bit on RX
         prescalar = 0;
         busy_out = 1;
         rx_flag = 1;
      end
      
      if (rx_flag == 1) begin             // begin receiving
         datafll[index] = RX_LINE;        // fill one data bit
         if (prescalar < 5207)
            prescalar = prescalar + 1;
         else
            prescalar = 0;
         if (prescalar == 2600) begin     // roughly every half cycle
            if (index < 9) 
               index = index + 1;
            else begin
               if (datafll[0] == 0 && datafll[9] == 1)   // verify a correct frame
                  data_out = datafll[8:1];               // write data
               else 
                  datafll = 0;            // all zeros if the frame is bad
               rx_flag = 0;
               busy_out = 0;
            end
         end
      end
         
   end // end always

   assign BUSY = busy_out;
   assign DATA = data_out;
   

endmodule


 // UART transmitter

module tx (CLK, START, BUSY, DATA, TX_LINE);

   input CLK, START;
   input [7:0] DATA;
   output BUSY, TX_LINE;
   
   reg [12:0] prescalar = 0;  // roughly 8k
   reg [3:0] index = 0;       // need room for 0-9
   reg [9:0] datafll = 0;     // 8 bits of data plus start/stop bits
   reg tx_flag = 0;           // 1 if we are transmitting
   
   reg busy_out = 0;
   reg tx_out = 1;            // idle is data high
   
   always@(posedge CLK) begin
      if (tx_flag == 0 && START == 1) begin
         tx_flag = 1;
         busy_out = 1;
         datafll[0] = 0;         // place data in datafll inbetween the control bits
         datafll[9] = 1;
         datafll[8:1] = DATA;   
      end
      
      if (tx_flag == 1) begin          // data is ready to transmit
         if (prescalar < 5207)         // 50MHz/9600 baud = 5207
            prescalar = prescalar + 1;
         else
            prescalar = 0;
         if (prescalar == 2600) begin  // every half of a cycle, roughly
            tx_out = datafll[index];   // place a bit on the data line 
            if (index < 9)
               index = index + 1;
            else begin                 // until the data is full
               tx_flag = 0;
               index = 0; 
               busy_out = 0;
            end
         end
      end
   end   // end always

   assign BUSY = busy_out;
   assign TX_LINE = tx_out;

endmodule

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s