Forum Discussion
Well the verilog code tells me basically nothing.
What clock frequency are you using, what baud rate, how many data bits and stop bits have you configured?
The serial program needs to set the same parameters for the serial line as well (baud rate, number of data and stop bits).
You also will need to invert the data line, or not, to get the correct polarity based on your serial connection.
Configuring the UART code to send some fixed pattern (ie, like the letter 'A' or something) would be a start.
And viewing the serial line result on a simulator (like modelsim, etc) to validate the waveform.
Based on your experience you have jumped about five steps ahead when you need to take one step at a time.
As an example, here is a waveform output from a UART module I wrote years ago.
Once I validated the RXD and TXD waveform patterns and timing were right I could connect it up to a real serial interface.
And here is the testbench code I use to test my UART module ...
`timescale 1ns / 1ns module test; parameter SYSFREQ = 50000, // KHz BAUDRATE = 38400, // baud SYSPER = 1000000/SYSFREQ, // ns/clk BITPER = 1000000000/BAUDRATE, // ns/bit TPD = 1; // ns reg sysclk; reg reset; wire txd; reg rxd; reg rxdd; wire [7:0] rxdata; wire rxferr; wire rxoerr; wire rxperr; wire rxerr; wire rxrdy; wire rxrd; reg [7:0] txdata; wire txrdy; wire txwr; parameter START = 1'b0, STOP = 1'b1; initial rxdd = 1'b1; always @(rxd) rxdd <= #(10.5*BITPER+48*SYSPER) rxd; wire delta = rxdd ^ txd; initial begin sysclk = 1; forever #(500000.0/SYSFREQ) sysclk = ~sysclk; end initial begin $timeformat(-6, 3, "us", 15); $dumpfile("test.vcd"); $dumpvars(2,test); reset = 1'b1; #950; reset = 1'b0; end task rxchar; input [7:0] char; reg [9:0] bits; reg [3:0] i; begin rxd = 1'b1; bits = {STOP,char[7:0],START}; for (i = 0; i <= 9; i = i+1) #BITPER rxd = bits[i]; end endtask // rxchar initial begin rxd = 1'b1; #(2.0*BITPER); rxchar(8'b01111111); #(1.5*BITPER); rxchar(8'b10101010); #(2.5*BITPER); rxchar(8'b01010101); #(2.0*BITPER); rxchar(8'b10000000); #(1.5*BITPER); rxchar(8'b00000010); #(1.0*BITPER); rxchar(8'b00000000); rxchar(8'b01010101); rxchar(8'b01000101); rxchar(8'b01010101); rxchar(8'b01000101); rxchar(8'b01010101); rxchar(8'b00000000); #(3.0*BITPER); rxd = 1'b0; #(15.0*BITPER); rxd = 1'b1; #(2.0*BITPER); $write("\n\n"); $finish; end reg txrdyd, rxrdyd, txgo; wire rxrdy_rising = rxrdy & ~rxrdyd; wire txrdy_falling = ~txrdy & txrdyd; always @(posedge sysclk) begin if (reset) begin txgo <= #TPD 0; rxrdyd <= #TPD 0; txrdyd <= #TPD 0; txdata <= #TPD 0; end else begin rxrdyd <= #TPD rxrdy; txrdyd <= #TPD txrdy; if (rxrdy_rising) txdata <= #TPD rxdata; if (rxrdy_rising) txgo <= #TPD 1'b1; else if (txrdy_falling) txgo <= #TPD 1'b0; end end always @(posedge sysclk) begin if (!reset) begin if (rxrdy_rising) $write("\n%t rxdata=%o\n", $time, rxdata); if (txrdy_falling) $write("%t txdata=%o\n", $time, txdata); end end assign rxrd = txgo; assign txwr = txgo; assign rxerr = rxferr|rxoerr|rxperr; uart #(.TPD(TPD)) uart ( .clk (sysclk), .reset (reset), .bauddiv (16'd163), .stopbits (4'd1), .databits (4'd8), .rxd (rxd), .rxrd (rxrd), .rxrdy (rxrdy), .rxferr (rxferr), .rxoerr (rxoerr), .rxperr (rxperr), .rxdata (rxdata), .txd (txd), .txwr (txwr), .txrdy (txrdy), .txdata (txdata) ); endmodule // test
I tested the code for UART transmission that I had in modelsim and it looks working fine! (I only tested the transmission, since I only need transmission)
I again tested it on FPGA with baud rate of 9600, clk of 50 M and CLKS_PER_BIT = 5208 (BITPER in your code), also with baud rate of 115200, clk of 50 M and CLKS_PER_BIT = 435, but I am still not monitoring the correct data from serial pin!
I set the data to be transmitted a constant value in the code for testing purposes. Based on DE2-115 datasheet set the serially out put transmitted data to PIN_G9.
Is my pin assignment wrong ? or the parameters?
- _AK6DN_3 years ago
Frequent Contributor
That would be the correct pin to send the TX data on to the RS232 connector.
Either 3.3V LVTTL or 3.3V LVCMOS should work as the signal type.
It would be interesting if you could post a sample ModelSim waveform for the TX data line for some known character.
- MG0073 years ago
New Contributor
As I mentioned before, I need to transmit data from FPGA for 7 bit and I need it binary. So I didn't check for characters, only for binary bits.
here is waveforms when I sent 01010101. tx_dv should be on to send the data, tx_serial is serial data (PIN_G9).
based on the waveform it is sending the each bit data for CLK_PER_BIT (clk/baud rate) times of clk.
- _AK6DN_3 years ago
Frequent Contributor
Well that waveform is really not useful at all.
Sending the same data over and over like that (a 0/1 pattern) it is virtually impossible to determine the start and stop bits.
Their is no bit timing measurement, and the clock waveform can't be used as is to determine the bit period is valid.
I would suggest sending more varied data patterns (ie, not the same one over and over).
Space them out in time a bit, so that the start and stop bits can be easily discerned.
And show a measurement of edge-edge transitions of a bit cell to be able to validate the baud rate is correct.
- MG0073 years ago
New Contributor
Thank you for the feedback.
I tried different data strings, 01010101, 00000000,11111111,10101010,11110000, and 00001111.
It seems to work fine.
It starts sending bit 0 as starting bit then sending the 8 bit data and sending 1 as ending bit. all 10 bits sent for 435 clk(50M/115200). And it sends data from MSB to LSB.
- MG0073 years ago
New Contributor
I again tested the UART transmitted with some constant 8 bit data, and it looks working fine. But I have some other issue to resolve. I am using Serial Port Monitor Software to read the transmitted data, but it reads it continiously in large length. How can I get the data in 8 bits only?
For example I sent 01010101 which is "55" in hex and I get this:
Or when I sent 10101010 which is "aa" in hex I get this:
How I only get 55 or aa only ?
- _AK6DN_3 years ago
Frequent Contributor
Do you mean how do you get a single character 0x55 or 0xAA in your receiver?
I suspect you are probably enabling the UART module to transmit a blast of characters, rather than just one.
Maybe unintentionally, but that is what it appears to be doing.
You need to adjust the control inputs to your UART module to transmit just one character, and then stopping.
You don't show what the top level control signals driving your uart look like so I am just speculating based on the waveform.
- MG0073 years ago
New Contributor
Yes, I meant 0xAA or any data.
I was also guessing that the enable being one is the issue (just wanted to make sure I am not doing sth wrong), for this testing I used the switches on the FPGA for implementing the enable for transmit.
I also wanted to know if there is any software I can use for reading the serial data in PC that I can put the recorded data in excel easily. This one I am using, Serial port monitor, shows the data in a table but does not save it in a table. it only can be saved as text. I need to save the received data like a table in excel.
- _AK6DN_3 years ago
Frequent Contributor
Excel can easily import data from text files using a .CSV (comma separated value) file format. For example:
1,123,456 2,789,345 3,000,123so just output a comma between data values on a line, and end a line with a LF character.
Just about any Windows terminal program allows you to capture the text from the serial link and save it to a file.
I happen to like an use a program called TeraTerm just because I've used it for like 25+ years.
But there are lots of other choices.