UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor losspost
Visitor
215 Views
Registered: ‎12-02-2018

Usb Communication via RS 232 ?

Jump to solution

Hello.

I am currently trying to connect my PC to my FPGA. I only want to send some text to the board and back but I am Stuck. I first checked if the pin assingment is correct but this seems fine so far. I choose the correct port on my terminal. If I send a letter the RXD led blinks red for a second. But still my Programm doesnt seem to work, it doesnt get any data. Any idea what I can change?

 

module UART(clk,uart_rxd,uart_txd,uart_cts,uart_rts,led_out);



	input clk;
	input uart_rxd;
	output uart_txd;
	//Clear to send
	inout uart_cts;
	//Request to send;
	inout uart_rts; 
	
	output[7:0] led_out;
	
	
	
	localparam baud_counter_value = 5208;
	//localparam baud_counter_value = 2500000;
	reg[10:0] baud_counter;
	//BaudClock
	reg baud_clock_reg;
	wire baud_clock;
	//Inital CTS/RTS register
	reg cts;
	reg rts;
	
	//Data Register
	reg[7:0] data;
	
	//LED Test Register
	reg[7:0] led;
	
	//Counter
	reg counter;
	
	
	//Uart State Register
	localparam
		s_IDLE = 0,
		s_SEND_CLEAR = 1,
		s_SEND = 2,
		s_RECEIVE = 3,
		s_TEST = 4;
		
	reg[4:0] state;
		
		
	
	
	initial begin
		//Initialize Baud Clock
		baud_clock_reg = 0;
		baud_counter = 10'b0;
		cts = 0;
		//rts = 0;
		data = 8'b0;
		led = 8'b0;
		counter = 0;
		//Inital state
		state = 0;
		
	end
	
//Creating a Baud Clock Baudrate = 115200	
/*-------------------------------------------------------------------*/			
	always@(posedge clk) begin
	
		if(baud_counter == baud_counter_value) begin
			baud_clock_reg <= !baud_clock_reg;
			baud_counter = 0;
		end else begin
			baud_counter = baud_counter +1;
		end
	
	end	
/*-------------------------------------------------------------------*/			
//Getting Request from PC to receive Data
/*-------------------------------------------------------------------*/			
	always@(posedge baud_clock) begin
	
		case(state) 
		
			s_IDLE: begin
				//If Host Request to send Data
				
				led <= 8'b00110011;
				if(uart_rts == 0) begin
				led <= 8'b11111111;
					state <= s_SEND_CLEAR;
				end
			end
			
			s_SEND_CLEAR: begin
			//Signal Host That the device is read to receive
				led <= 1;
				cts <= 1;
				state <= s_RECEIVE;
			end
			//Receive the Data
			s_RECEIVE: begin
				//Setting Least Significant Bit
				data <= uart_rxd;
				//Shift 0 bit one to the Left 
				data[0] <= data << 1;
				counter = counter + 1;
			
				if(counter == 10) begin
					
					state <= s_TEST;
				end
			end
			
			s_TEST: begin
				led <= data;
			
			end
		endcase
		
	end

/*-------------------------------------------------------------------*/			


	//Update Baud Clock Signal
	assign baud_clock = baud_clock_reg;
	assign uart_cts = cts;
	assign uart_rts = rts;
	assign led_out = led;


endmodule
0 Kudos
1 Solution

Accepted Solutions
180 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

@losspost

Welcome to the Xilinx Forum!

-good start on writing HDL to read data from a serial communications port !

Here’s some thoughts that might help you get things going.

  1. First, bear with me. I am a VHDL programmer with poor knowledge of Verilog. Hopefully, any VHDL terminology that I use here won’t confuse you.
  2. USB is not the same as RS232. However, you can buy USB-to-RS232 convertors (eg. from <here>). I will assume you have done this are using the FPGA to read data from RS232.
  3. Put an oscope on the RS232 line, RXD, that brings data into your FPGA. Ensure that voltage levels on RXD are compatible with the IO standard you are using on the FPGA-pin that receives RXD.
  4. I see that RXD becomes uart_rxd in your HDL. Before this signal reaches your UART module, you should run it through a 2-flip-flop synchronizer. This is necessary to prevent metastability since uart_rxd is toggling asynchronously with the clocks in your FPGA.
  5. I don’t know frequency of your clock called clk. So, in your UART module, I will assume you have divided-down clk properly so that baud_clock is toggling at 115200 Hz, which is appropriate for a RS232 baud rate of 115200 bits-per-second (bps). This baud_clock is not actually a clock, rather it is a signal (also called a toggle) in the “clk” clock-domain.
  6. Instead of toggling baud_clock at the RS232 baud rate, I recommend that you toggle baud_clock at eight-times the RS232 baud rate (for reasons described below).
  7. In your procedure that begins with “always@(posedge baud_clock) begin”, I recommend that you instead use “always@(posedge clk) begin”.  Thus, this procedure will be clocked by a “real” clock (and not a toggle). Also, I recommend that the flow of this procedure go as follows:
    1. Wait to see an edge on uart_rxd that corresponds to RS232 start-bit.
    2. Count 4 tics of baud_clock and then read the start bit from uart_rxd into your data[0]. By waiting 4 tics of baud_clock before reading uart_rxd, you are doing what is called “sampling the RXD data in the middle of the data-eye”.
    3. Left-shift data[.] by 1 – as you are doing.
    4. Count 8 tics of baud_clock and then read the next bit from uart_rxd into data[0].
    5. Continue cycling through the last two steps until you have read all (10?) bits from the RS232 data packet. The number of bits in the RS232 packet will depend on how many start-bits, stop-bits, and parity-bits you have specified for the RS232 port.
    6. Return to the first step and wait for start of next RS232 packet.

-let me know how things turn out.

Mark

Tags (1)
0 Kudos
8 Replies
181 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

@losspost

Welcome to the Xilinx Forum!

-good start on writing HDL to read data from a serial communications port !

Here’s some thoughts that might help you get things going.

  1. First, bear with me. I am a VHDL programmer with poor knowledge of Verilog. Hopefully, any VHDL terminology that I use here won’t confuse you.
  2. USB is not the same as RS232. However, you can buy USB-to-RS232 convertors (eg. from <here>). I will assume you have done this are using the FPGA to read data from RS232.
  3. Put an oscope on the RS232 line, RXD, that brings data into your FPGA. Ensure that voltage levels on RXD are compatible with the IO standard you are using on the FPGA-pin that receives RXD.
  4. I see that RXD becomes uart_rxd in your HDL. Before this signal reaches your UART module, you should run it through a 2-flip-flop synchronizer. This is necessary to prevent metastability since uart_rxd is toggling asynchronously with the clocks in your FPGA.
  5. I don’t know frequency of your clock called clk. So, in your UART module, I will assume you have divided-down clk properly so that baud_clock is toggling at 115200 Hz, which is appropriate for a RS232 baud rate of 115200 bits-per-second (bps). This baud_clock is not actually a clock, rather it is a signal (also called a toggle) in the “clk” clock-domain.
  6. Instead of toggling baud_clock at the RS232 baud rate, I recommend that you toggle baud_clock at eight-times the RS232 baud rate (for reasons described below).
  7. In your procedure that begins with “always@(posedge baud_clock) begin”, I recommend that you instead use “always@(posedge clk) begin”.  Thus, this procedure will be clocked by a “real” clock (and not a toggle). Also, I recommend that the flow of this procedure go as follows:
    1. Wait to see an edge on uart_rxd that corresponds to RS232 start-bit.
    2. Count 4 tics of baud_clock and then read the start bit from uart_rxd into your data[0]. By waiting 4 tics of baud_clock before reading uart_rxd, you are doing what is called “sampling the RXD data in the middle of the data-eye”.
    3. Left-shift data[.] by 1 – as you are doing.
    4. Count 8 tics of baud_clock and then read the next bit from uart_rxd into data[0].
    5. Continue cycling through the last two steps until you have read all (10?) bits from the RS232 data packet. The number of bits in the RS232 packet will depend on how many start-bits, stop-bits, and parity-bits you have specified for the RS232 port.
    6. Return to the first step and wait for start of next RS232 packet.

-let me know how things turn out.

Mark

Tags (1)
0 Kudos
Visitor losspost
Visitor
150 Views
Registered: ‎12-02-2018

Re: Usb Communication via RS 232 ?

Jump to solution

Hi Thank your for your help.
I've implemented your ideas so far. What I haven't quite understood yet is what you mean by the text length using the start/stop bit. I thought the flow control is controlled by CTS and RTS. And I get different outputs but they have nothing to do with the real value?!The same input sometimes give out different values

 

module UART(clk,uart_rxd,uart_txd,uart_cts,uart_rts,led_out);



	input clk;
	input uart_rxd;
	output uart_txd;
	//Clear to send
	inout uart_cts;
	//Request to send;
	inout uart_rts; 
	
	output[7:0] led_out;
	
	
	//8 times the Baud Freq.
	localparam baud_counter_value = 5208/8;
	//localparam baud_counter_value = 2500000;
	reg[14:0] baud_counter;
	//BaudClock
	reg baud_clock_reg;
	wire baud_clock;
	//Inital CTS/RTS register
	reg cts;
	reg rts;
	
	//Data Register
	reg[7:0] data;
	
	//LED Test Register
	reg[7:0] led;
	
	//Counter
	reg[32:0] counter;
	
	
	//Uart State Register
	localparam
		s_IDLE = 0,
		s_DELAY = 1,
		s_DELAY_RESET =2,
		s_SEND = 3,
		s_RECEIVE = 4,
		s_TEST = 5,
		s_RECEIVE_DELAY_RESET=6;
		
	reg[4:0] state_uart;
		
	//Baud Delay Counter
	//Because baud_clock is baud_clock * 8. We have to wait 8 baud_clocks for 1 baud bid at 9600baud/s
	reg baud_delay;
	reg[4:0] baud_delay_counter;
	reg delay;
	
	initial begin
		//Initialize Baud Clock
		baud_clock_reg = 0;
		baud_counter = 14'b0;
		cts = 0;
		rts = 0;
		data = 8'b0;
		led = 8'b00000001;
		counter = 0;
		baud_delay = 0;
		baud_delay_counter = 4'b0;
		//Inital state
		state_uart = s_IDLE;
		
	end
	
//Creating a Baud Clock Baudrate = 9600	
/*-------------------------------------------------------------------*/			
	always@(posedge clk) begin
		
		if(baud_counter == baud_counter_value-1) begin
			baud_clock_reg <= !baud_clock_reg;
			baud_counter = 0;
		end else begin
			baud_counter <= baud_counter +1;
		end
	
	end	
	

/*-------------------------------------------------------------------*/
//Baud Delay Counter
/*-------------------------------------------------------------------*/
	always@(posedge baud_clock && baud_delay == 1) begin
		case(state_uart)
			s_DELAY: begin
				baud_delay_counter <= baud_delay_counter +1;	
				if(baud_delay_counter == 4) begin
					baud_delay_counter <= 0;
				end
			end
			s_RECEIVE: begin
				baud_delay_counter <= baud_delay_counter +1;
				if(baud_delay_counter == 8) begin
					baud_delay_counter <= 0;
				end
			end
			s_DELAY_RESET: baud_delay_counter <= 0;
			s_RECEIVE_DELAY_RESET: baud_delay_counter <=0;
		endcase
		
	end


/*-------------------------------------------------------------------*/			
//Getting Request from PC to receive Data
/*-------------------------------------------------------------------*/			
	always@(posedge clk) begin
	
		case(state_uart) 
		
			s_IDLE: begin
				//If Host Request to send Data
			
				//Waiting for start bit
				if(uart_rxd == 0) begin
					state_uart <= s_DELAY;
				end
			end
			
			s_DELAY: begin
				
				//Wait for 4 Baud Ticks to "sample Data"
				if(baud_delay_counter == 4) begin
					baud_delay <= 0;
					state_uart <= s_DELAY_RESET;
					
				end 
				//Activate Baud Counter
				baud_delay <= 1;
				
				
			end
			
			s_DELAY_RESET: begin
				if(baud_delay_counter == 0) begin
					state_uart <= s_RECEIVE;
				
				end
			end
			//Receive the Data
			s_RECEIVE: begin
				//Waiting for one "real" baud tick
				baud_delay <= 1;
				if(baud_delay_counter == 8) begin
					//Setting Least Significant Bit
					data[0] = uart_rxd;
					//Shift 0 bit one to the Left 
					//= because its only getting executed after the previous line was executed
					data = data << 1;
					counter = counter + 1;
					state_uart <= s_RECEIVE_DELAY_RESET;
				end
				
				if(counter == 8) begin
					baud_delay <= 0;
					state_uart <= s_TEST;
	
				end
			end
			
			s_RECEIVE_DELAY_RESET: begin
				if(baud_delay_counter == 0)begin
					state_uart <= s_RECEIVE;
				end
			end
			
			s_TEST: begin
				led <= data;
				data = 8'b0;
				counter = 0;
			
					
				state_uart <= s_IDLE;
	
			
			end
		endcase
		
	end

/*-------------------------------------------------------------------*/			


	//Update Baud Clock Signal
	assign baud_clock = baud_clock_reg;
	assign uart_cts = cts;
	assign uart_rts = rts;
	assign led_out = led;


endmodule

 

0 Kudos
135 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

@losspost

Sounds like you got things kinda working. Congratulations!

You might want to ignore CTS and RTS and all “flow-control” for now. These can be necessary if you have a fast transmitter talking to a slow receiver, since the receiver may sometimes need to slow up the transmitter by toggling the flow-control lines. This should not be a problem for you since you are sending data to the FPGA – which is definitely not a slow receiver.

RS232 communication consists of packets that have 8-bits data padded on the front by a start-bit(s) and on the back by a parity-bit and stop-bit(s) as shown <here>.   There will be dead-time between these packets where the line idles in the high(1) state. The number of start-bits, stop-bits, and whether-or-not to use a parity bit are things that you must tell the RS232-transmitter.

So, your job is to wait for the start-bit (a high-to-low transition) and then read all the bits (no-more and no-less) from the RS232 packet that follows. -and then wait for the next start-bit.

Mark

0 Kudos
Visitor losspost
Visitor
112 Views
Registered: ‎12-02-2018

Re: Usb Communication via RS 232 ?

Jump to solution

markg@prosensing.com

Its almost working. Sadly its receive wrong values. So I decided to send the same signal back which I send to the device. This are the results:

22 -> 0E

2->þ

3425 -> >þ

0 -> þ

It seems like there is a problem with the baud freq.

My FPGA Clock has works at 50Mhz. So i divide it by 9600 to get my counter value, or is this wrong?

0 Kudos
100 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

@losspost

For 9600bps baud rate, your 8x baud_clock needs to have a frequency of (8*9600=76800Hz).  So, if you divide your 50MHz clock by 651 then you get a baud_clock frequency of 76805 Hz, which differs from 76800Hz by less than 0.01%.  Baud clock errors up to 3.0% are usually acceptable.

Mark

0 Kudos
Visitor losspost
Visitor
95 Views
Registered: ‎12-02-2018

Re: Usb Communication via RS 232 ?

Jump to solution

markg@prosensing.com

Ok I can see in the simulation why the data i send back doesnt work. But My FPGA shows the wrong value it receives with the led's. But in the simulation I see that the receiving the data works fine in the simulation but not on the real FPGA

 

image.png

0 Kudos
75 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

     …in the simulation I see that the receiving the data works fine..
Good job!

     But My FPGA shows the wrong value it receives with the led's…
Be sure to route the RS232 data through a 2-flip-flop synchronizer before it reaches your UART module as uart_rxd.  Also, for each flip-flop in the synchronizer, set ASYNC_REG= TRUE using constraints like the following in your Vivado XDC constraints file.     
     set_property ASYNC_REG TRUE [ get_cells <netlist name of the flip-flip> ]

These constraints will cause the two flip-flops of the synchronizer to be placed close together - so they act properly as a synchronizer.

0 Kudos
47 Views
Registered: ‎01-22-2015

Re: Usb Communication via RS 232 ?

Jump to solution

@losspost

How’s the work going?  If things are still not working, try using an oscope on the RXD line to see if the RS232 transmitter is sending the correct number of bits in each RS232 packet.

FYI – we do almost exactly what you are doing for RS232 communications and run at baud rates near 1Mb/s (over short distances).

Mark

0 Kudos