Forum Discussion
Have you installed any Windows serial terminal program. There are a few listed here ...
https://learn.adafruit.com/windows-tools-for-the-electrical-engineer/serial-terminal
PuTTY is pretty common, been around for a long time.
Personally I use a program called TeraTerm https://en.wikipedia.org/wiki/Tera_Term
its been around for 30+ years now. Runs fine on Windows 10.
You probably want to send your data as printable ascii text (ie numbers) to make it
easy to capture and save, but raw binary would work also.
I think I am doing something wrong.
I found this verilog code for UART transmitter online that I used. I wanted to test the transmitter so I set the input data to be controlled by switches on the fpga. I used puTTy as you recommended and also Serial Port Monitor to get the serial data in PC but what I get is not correct.
Here is the code for transmitter:
module uart_tx
#(parameter CLKS_PER_BIT = 44)
(
input i_Clock,
input i_Tx_DV,
input [7:0] i_Tx_Byte,
output o_Tx_Active,
output reg o_Tx_Serial,
output o_Tx_Done
);
parameter s_IDLE = 3'b000;
parameter s_TX_START_BIT = 3'b001;
parameter s_TX_DATA_BITS = 3'b010;
parameter s_TX_STOP_BIT = 3'b011;
parameter s_CLEANUP = 3'b100;
reg [2:0] r_SM_Main = 0;
reg [7:0] r_Clock_Count = 0;
reg [2:0] r_Bit_Index = 0;
reg [7:0] r_Tx_Data = 0;
reg r_Tx_Done = 0;
reg r_Tx_Active = 0;
always @(posedge i_Clock)
begin
case (r_SM_Main)
s_IDLE :
begin
o_Tx_Serial <= 1'b1; // Drive Line High for Idle
r_Tx_Done <= 1'b0;
r_Clock_Count <= 0;
r_Bit_Index <= 0;
if (i_Tx_DV == 1'b1)
begin
r_Tx_Active <= 1'b1;
r_Tx_Data <= i_Tx_Byte;
r_SM_Main <= s_TX_START_BIT;
end
else
r_SM_Main <= s_IDLE;
end // case: s_IDLE
// Send out Start Bit. Start bit = 0
s_TX_START_BIT :
begin
o_Tx_Serial <= 1'b0;
// Wait CLKS_PER_BIT-1 clock cycles for start bit to finish
if (r_Clock_Count < CLKS_PER_BIT-1)
begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_TX_START_BIT;
end
else
begin
r_Clock_Count <= 0;
r_SM_Main <= s_TX_DATA_BITS;
end
end // case: s_TX_START_BIT
// Wait CLKS_PER_BIT-1 clock cycles for data bits to finish
s_TX_DATA_BITS :
begin
o_Tx_Serial <= r_Tx_Data[r_Bit_Index];
if (r_Clock_Count < CLKS_PER_BIT-1)
begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_TX_DATA_BITS;
end
else
begin
r_Clock_Count <= 0;
// Check if we have sent out all bits
if (r_Bit_Index < 7)
begin
r_Bit_Index <= r_Bit_Index + 1;
r_SM_Main <= s_TX_DATA_BITS;
end
else
begin
r_Bit_Index <= 0;
r_SM_Main <= s_TX_STOP_BIT;
end
end
end // case: s_TX_DATA_BITS
// Send out Stop bit. Stop bit = 1
s_TX_STOP_BIT :
begin
o_Tx_Serial <= 1'b1;
// Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
if (r_Clock_Count < CLKS_PER_BIT-1)
begin
r_Clock_Count <= r_Clock_Count + 1;
r_SM_Main <= s_TX_STOP_BIT;
end
else
begin
r_Tx_Done <= 1'b1;
r_Clock_Count <= 0;
r_SM_Main <= s_CLEANUP;
r_Tx_Active <= 1'b0;
end
end // case: s_Tx_STOP_BIT
// Stay here 1 clock
s_CLEANUP :
begin
r_Tx_Done <= 1'b1;
r_SM_Main <= s_IDLE;
end
default :
r_SM_Main <= s_IDLE;
endcase
end
assign o_Tx_Active = r_Tx_Active;
assign o_Tx_Done = r_Tx_Done;
endmodule
This is the Quartus modules and pins:
This is what I get from using PuTTy:
What I get from Serial port Monitor:
- _AK6DN_3 years ago
Frequent Contributor
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- MG0073 years ago
New Contributor
I am using the clock on the FPGA which is 50 MHz, and baud rate of 115200.
based on the code, there is one start bit and one stop bit. (start bit =0, start sending data, and stop bit=1, end of data).
Yes I need to test it in ModelSim first.
I thought it might be simple since it is only transmitter and I can test it on pga right away.
- MG0073 years ago
New Contributor
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.