Forum Discussion
Altera_Forum
Honored Contributor
18 years agouart communications
Hey, I'm doing a project involving the DE2 FPGA, where I need to communicate with a pc via a serial interface. I have checked the pin assignments file and noticed there are only 2 pins associated with UART: UART_TXD and UART_RXD.
I want to write my code in verilog, rather than running a soft core proccessor and using the NIOS 2 development suit to code c for it. My question is, how can I negotiate a clockspeed using just these two pins? I've been over most of the documentation I can find and there is nothing relevant that I can find. Thanks in advance for any help.14 Replies
- Altera_Forum
Honored Contributor
data being lsb first shouldn't make the interface not work, as it would surely just receive a different ascii symbol.
I'm aware i can use hex and decimal too, but sometimes its easier to read whats going on in binary, for me at least. Admitted the baud rate is possibly too inaccurate, what can I do about this? I tried using a megafunction to get a slower clock, but a divisor of 10 was apparantly too big. By a shift register, do you mean have a register with the data in, & 0x1 send data, next cycle >> 1 and repeat. If so then yes, this is going to be implemented shortly. However I don't see how it would help with my current problem. Also, I changed UART_TXD = data; to UART_TXD = !data; as when slowing down the rate, the TXD light next to the serial port was on, when the data i wanted to send was a 0, I assume it should be vice versa. Can anyone confirm that using a RS232 cable is fine, there has been a suggestion that I should use a null modem cable. - Altera_Forum
Honored Contributor
Hello,
I could verify, that the module doesn't operate fully correct: 1. RS232 data should be LSB first 2. If you have a 50 MHz clock, the baudrate is proabably too inaccurate. Actual Baudrate is 50e6/(0x1555+1) = 9154 Baud (- 4,6 %). By the way, Verilog knows also hex and decimal constants, e. g. 13'd5207. Operation would be much easier using a shiftregister for the UART. Regards, Frank - Altera_Forum
Honored Contributor
Ok, after making some posts on a c++ forum i've gained some insight. I'm trying to hardcode the data rate to 9600bps, and am using the following code:
module test5(input CLOCK_50, output [2:0] LEDR, //output LCD_ON, //output LCD_BLON, //output LCD_RW, //output LCD_EN, //output LCD_RS, //output [7:0] LCD_DATA, output UART_TXD, //input UART_RXD input [0:0] SW ); reg [13:0] waiter = 13'b0000000000000; //counter to reduce clock rate reg [3:0] state = 4'b0000; //current state. 0 = start bit, 1-8 = data bits, 9 = stop bit, other = ended reg data = 1'b1; //start high = idle state reg clk_new = 0; //changes the state of an led every time a bit is sent assign LEDR[0] = data; //led outputs current data bit assign LEDR[1] = SW; //led outputs status of a switch assign LEDR[2] = clk_new; //led shows when new bit is sent assign UART_TXD = data; //assert the transmit wire to the data bit always @(posedge CLOCK_50) //every clock tick begin if (waiter == 13'b1010101010101) //9600 times a second (aprox) begin clk_new = !clk_new; //change clock led waiter = 27'b000000000000000000000000000; //reset counter case (state) //switch on the current state 4'h0:begin //in state 0 if (SW) //check to see if switch is high, if so start, else do nothing begin data = 0; //start bit state = state + 1'b1; end end 4'h1:begin //data bits = 00111001b = 57d (9 in ascii) data = 1'b0; state = state + 1'b1; end 4'h2:begin data = 1'b0; state = state + 1'b1; end 4'h3:begin data = 1'b1; state = state + 1'b1; end 4'h4:begin data = 1'b1; state = state + 1'b1; end 4'h5:begin data = 1'b1; state = state + 1'b1; end 4'h6:begin data = 1'b0; state = state + 1'b1; end 4'h7:begin data = 1'b0; state = state + 1'b1; end 4'h8:begin data = 1'b1; state = state + 1'b1; end 4'h9:begin //stop bit data = 1'b1; state = state + 1'b1; end default:begin data = 1'b1; //idle bit end endcase end //end if (waiter == ...) waiter = waiter + 1'b1; //inc waiter end //end always @... endmodule transmits the ascii character '9' at 9600bps 1 start bit, 1 stop bit, 0 parity bits. I set up hyperterminal to those settings + flow control = none. And connected to com1. I run my verilog code and switch the switch to high, but nothing appears on the terminal. I set the data rate on the board to about 1/2 bit a second, so i could watch the leds, and they outputted correctly, so i'm definetly setting data to the correct values. My code looks correct to me, so i'm guessing i am formatting the frame incorrectly. Any help would be really apreciated. - Altera_Forum
Honored Contributor
Hello,
Don't know why baud rate should be negotiated. It is usually fixed by the application, in some cases may be autobaud. You only have to write a simple UART (or adapt an example from the internet, e. g. from opencores.org). With user specific UART designs, it is generally easier to achieve particular baud rates without a PLL, cause you are free to use non-standard oversampling counts in receiver. e. g. 13. Regards, Frank