Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
18 years ago

uart 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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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