- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I mentioned the decimal constant syntax, cause I was searching for an explanation why you didn't calculate the correct baud rate divider, but set it 4,6 % too slow. But I think you should be able to set the value also using binary constants. DE2 can be connected to PC with a straigth (1:1) RS232 cable, DE2 has TX at pin 2, A PC at Pin 3. Regards, Frank- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
thanks.
Ok my clock is 50mhz which = 52428800hz now i want 9600 baud so: 52428800 / 9600 = 5461.3333333333333333333333333333 so using 5461 as my divisor, which = 1010101010101 or am I doing something stupid. Sinec I do require a null modem cable, i'm fairly sure that getting one will fix my problems, and make this work. I have arranged to pick one up tommorrow. I'll get back to you once i've tried the cable.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I see the misunderstanding. 50 MHz clock oszillator isn't 50*2^20 like MByte, it is really 50e6. Or Terasic would be the first company to introduce a binary 50 MHz crystal. But you don't need a nullmodem cable. I had written this first, but corrected after a few minutes. Regards, Frank- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
hmm, ok, thanks for the clock info, I've corrected it to:
if (waiter == 13'b1010001011000) //9600 times a second (aprox) I'm using: http://www.maplin.co.uk/module.aspx?moduleno=97733&doy=12m2 and http://www.maplin.co.uk/module.aspx?moduleno=97872&doy=12m2 and its not working. So if your sure it can be done with that cable, then there must be something up with my timing code, as I have the UART_TXD light flashing as it should. Any more ideas about what could be wrong. I'm running hyperterminal set to 9600bps, 1 stop bit, no parity bit, no flow control. Listening on port COM1. And when I switch switch 0 on the fpga hyperterminal picks up nothing. my latest code is:
module test5(input CLOCK_50,
output LEDR,
output UART_TXD,
input UART_RXD,
input SW
);
reg waiter = 13'b0000000000000; //counter to reduce clock rate
//reg waiter = 13'b0000000000000; //counter to reduce clock rate
reg 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
reg origData = 16'b0101001100111001; //S 9 in ascii
reg currData;
reg started = 0;
assign LEDR = data; //led outputs current data bit
assign LEDR = SW; //led outputs status of a switch
assign LEDR = 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 == 27'b111111111111111111111111111) //1/2 times a second
if (waiter == 13'b1010001011000) //9600 times a second (aprox)
begin
if (started == 0) //have we not started yet?
begin
if (SW) //start if switch 0 is high
begin
started = 1;
currData = origData; //set the current data register to be the original data register
end
end
else //we have started
begin
clk_new = !clk_new; //change clock led
waiter = 13'b0000000000000; //reset counter
if (currData == 16'b0000000000000000 && state == 4'h0) //end of transmit
begin
data = 1'b1; //idle bit
if (!SW) //if switch 0 is low, then reset to not started
begin
started = 1'b0;
end
end
else
begin
if (state == 4'h0) //start bit
begin
data = 1'b0;
end
else if(state == 4'h9) //stop bit
begin
data = 1'b1;
end
else if(state < 4'h9) //data bits
begin
data = (currData & 1'b1); //get first bit
currData = currData >> 1; //right shift, so as first bit is the next bit to send
end
if (state == 4'h9) //update state
begin
state = 4'h0;
end
else
begin
state = state + 1'b1;
end
end //end data left to transmit
end //end started == 1
end //end if (waiter == ...)
waiter = waiter + 1'b1; //inc waiter
end //end always @...
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'd suggest removing the inverter from your TxD signal again. Unless there's another external inversion going on, normally I'd expect the TTL/CMOS level signal to idle high and the RS232 level signal to idle negative. From what you said in an earlier post, this would also mean that the transmit LED would be off when idle, which makes sense.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
in the first example, the polarity has been correct for "logic-level" RS232, which is iverted by the MAX232 driver. Now polarity is incorrect. Apart from that, the module is now sending the intended two characters at corrcet baudrate, LSB "9" first, as I could see by Quartus internal simulator. I append my test vector file. Regards, Frank- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hey all, I finally solved my problem today. Using a multimeter, oscillascope, 2 different serial cables and a soldering iron.
problems: a) although the cable i was using, was the right one, it didn't work in my 25 pin rs232 port. The computer lab has 9 pin sockets, so that is fine. b) my code had a few bugs. Below is my completed working code, for archive purposes. Thanks for all your help.
module test(input CLOCK_50,
output LEDR,
output UART_TXD,
input UART_RXD,
input SW
);
wire serial_clk;
new_clock pll(.inclk0(CLOCK_50), .c0(serial_clock));
reg waiter = 12'b0000000000000; //counter to reduce clock rate
//reg waiter = 13'b0000000000000; //counter to reduce clock rate
reg 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
reg origData = 48'h00_4F_4C_4C_45_48; //HELLO in ascii, little endian
reg currData;
reg started = 0;
assign LEDR = data; //led outputs current data bit
assign LEDR = SW; //led outputs status of a switch
assign LEDR = clk_new; //led shows when new bit is sent
assign UART_TXD = data; //assert the transmit wire to the data bit
always @(posedge serial_clock) //every clock tick
begin
//if (waiter == 27'b111111111111111111111111111) //1/2 times a second
if (waiter == 12'b1100_0011_0100) //9600 times a second (aprox)
begin
waiter <= 12'b000000000000; //reset counter
if (started == 0) //have we not started yet?
begin
if (SW) //start if switch 0 is high
begin
started <= 1;
currData <= origData; //set the current data register to be the original data register
end
end
else //we have started
begin
clk_new <= !clk_new; //change clock led
if (currData == 48'd0 && state == 4'h0) //end of transmit
begin
data <= 1'b1; //idle bit
if (!SW) //if switch 0 is low, then reset to not started
begin
started <= 1'b0;
end
end
else
begin
if (state == 4'h0) //start bit
begin
data <= 1'b0;
end
else if(state == 4'h9) //stop bit
begin
data <= 1'b1;
end
else if(state < 4'h9) //data bits
begin
data <= currData; //get first bit
currData <= currData >> 1; //right shift, so as first bit is the next bit to send
end
if (state == 4'h9) //update state
begin
state <= 4'h0;
end
else
begin
state <= state + 1'b1;
end
end //end data left to transmit
end //end started == 1
end //end if (waiter == ...)
else
begin
waiter <= waiter + 1'b1; //inc waiter
end
end //end always @...
endmodule
thats 9600 baud, 1 stop bit, no parity to send a 40 bit string
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I come across a coding in verilog for the UART....
Just tat when i connect to the ALTERA DE-2 board i seem to stuck on the Tx busy OUTPUT...as by the pin assignmnt i assign PIN B_25 but how bout Tx busy for the output...wat shall i assign???... this is my coding.. // RS-232 TX module //`define DEBUG // in DEBUG mode, we output one bit per clock cycle (useful for faster simulations) module one(clk, TxD_start, TxD_data, TxD, TxD_busy); input clk, TxD_start; input [7:0] TxD_data; output TxD, TxD_busy; parameter ClkFrequency = 25000000; // 25MHz parameter Baud = 115200; parameter RegisterInputData = 1; // in RegisterInputData mode, the input doesn't have to stay valid while the character is been transmitted // Baud generator parameter BaudGeneratorAccWidth = 16; reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc; `ifdef DEBUG wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = 17'h10000; `else wire [BaudGeneratorAccWidth:0] BaudGeneratorInc = ((Baud<<(BaudGeneratorAccWidth-4))+(ClkFrequency>>5))/(ClkFrequency>>4); `endif wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth]; wire TxD_busy; always @(posedge clk) if(TxD_busy) BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc; // Transmitter state machine reg [3:0] state; wire TxD_ready = (state==0); assign TxD_busy = ~TxD_ready; reg [7:0] TxD_dataReg; always @(posedge clk) if(TxD_ready & TxD_start) TxD_dataReg <= TxD_data; wire [7:0] TxD_dataD = RegisterInputData ? TxD_dataReg : TxD_data; always @(posedge clk) case(state) 4'b0000: if(TxD_start) state <= 4'b0001; 4'b0001: if(BaudTick) state <= 4'b0100; 4'b0100: if(BaudTick) state <= 4'b1000; // start 4'b1000: if(BaudTick) state <= 4'b1001; // bit 0 4'b1001: if(BaudTick) state <= 4'b1010; // bit 1 4'b1010: if(BaudTick) state <= 4'b1011; // bit 2 4'b1011: if(BaudTick) state <= 4'b1100; // bit 3 4'b1100: if(BaudTick) state <= 4'b1101; // bit 4 4'b1101: if(BaudTick) state <= 4'b1110; // bit 5 4'b1110: if(BaudTick) state <= 4'b1111; // bit 6 4'b1111: if(BaudTick) state <= 4'b0010; // bit 7 4'b0010: if(BaudTick) state <= 4'b0011; // stop1 4'b0011: if(BaudTick) state <= 4'b0000; // stop2 default: if(BaudTick) state <= 4'b0000; endcase // Output mux reg muxbit; always @( * ) case(state[2:0]) 3'd0: muxbit <= TxD_dataD[0]; 3'd1: muxbit <= TxD_dataD[1]; 3'd2: muxbit <= TxD_dataD[2]; 3'd3: muxbit <= TxD_dataD[3]; 3'd4: muxbit <= TxD_dataD[4]; 3'd5: muxbit <= TxD_dataD[5]; 3'd6: muxbit <= TxD_dataD[6]; 3'd7: muxbit <= TxD_dataD[7]; endcase // Put together the start, data and stop bits reg TxD; always @(posedge clk) TxD <= (state<4) | (state[3] & muxbit); // register the output to make it glitch free endmodule- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't exactly understand the question. TxD_busy is nothing to connect at the external UART interface. It's an internal signal to inform the data source when the UART is ready to accept the next character.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ok then how bout the inputs....must i connect normal switch as inputs from the altera de-2 board
https://www.alteraforum.com/forum/attachment.php?attachmentid=5225 i have attached the picture of the pin assignment...im new in the rs232 section soe ur advise on wat input must i put is really valuable...is it the normal switch in altera de-2 which is from SW0 to SW17 ?? and for the Tx busy if its not connected in external wat output shall i assign since Tx will be assign externally to UART pin...pls Advise
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page