Tuesday, 1 December 2015

rs232 - Implement serial port on fpga (verilog)


I don't know if this belongs here or stackoverflow. I assume here as although verilog looks like software it's actually describing hardware connections?


I have a Spartan-3AN evaluation board and I'm trying to implement a simple rs232 port interface on it which I can't get to work. I'm an experienced software developer but new to verilog and digital design. I want to move up from flashing a single LED to the next step.


I've tried to implement it like this - 1) Generate a clock pulse "serclock" at the baud rate, so at the start of each bit. 2) Implement a state machine that once it's told to start steps through the states at the correct speed. 3) Implement a lookup to output the correct data bit depending on the state that 2) is in.


If there is a better way I'd appreciate any help. However I would expect this to work but I get nothing at all. Can anyone spot anything stupid that I've done? I'd appreciate any advice.


// Serial port demo program
//
// Assumptions: 50Mhz clock rate

module SerDemo(input clk, output ser);



// Start signal tells it to start sending bits
reg start;

//The bits of data to send
reg [7:0] data;

/////////////////////////////////////////////////////////////////////////////
// Serial port clock generator

// Generate a 9600 baud clock signal for the serial port by dividing the
// 50Mhz clock by 5208

reg [14:0] clockdiv;

// Count from 0..5207 then reset back to zero
always @(posedge clk)
begin
if (clockdiv == 5207)
clockdiv <= 0;

else
clockdiv <= clockdiv + 1;
end

// The serclock is a short pulse each time we are reset
wire serclock = (clockdiv == 0);

/////////////////////////////////////////////////////////////////////////////
// Serial port state machine
// Only start the state machine when "start" is set. Only advance to the

// next state when serclock is set.

reg [3:0] state;

always @(posedge clk)
begin
case (state)
4'b0000: if (start) state <= 4'b0001;
4'b0001: if (serclock) state <= 4'b0010; // Start bit
4'b0010: if (serclock) state <= 4'b0011; // Bit 0

4'b0011: if (serclock) state <= 4'b0100; // Bit 1
4'b0100: if (serclock) state <= 4'b0101; // Bit 2
4'b0101: if (serclock) state <= 4'b0110; // Bit 3
4'b0110: if (serclock) state <= 4'b0111; // Bit 4
4'b0111: if (serclock) state <= 4'b1000; // Bit 5
4'b1000: if (serclock) state <= 4'b1001; // Bit 6
4'b1001: if (serclock) state <= 4'b1010; // Bit 7
4'b1010: if (serclock) state <= 4'b0000; // Stop bit
default: state <= 4'b0000; // Undefined, skip to stop
endcase

end


///////////////////////////////////////////////////////////////////////////////
// Serial port data
// Ensure that the serial port has the correct data on it in each state

reg outbit;

always @(posedge clk)

begin
case (state)
4'b0000: outbit <= 1; // idle
4'b0001: outbit <= 0; // Start bit
4'b0010: outbit <= data[0]; // Bit 0
4'b0011: outbit <= data[1]; // Bit 1
4'b0100: outbit <= data[2]; // Bit 2
4'b0101: outbit <= data[3]; // Bit 3
4'b0110: outbit <= data[4]; // Bit 4
4'b0111: outbit <= data[5]; // Bit 5

4'b1000: outbit <= data[6]; // Bit 6
4'b1001: outbit <= data[7]; // Bit 7
4'b1010: outbit <= 0; // Stop bit
default: outbit <= 1; // Bad state output idle
endcase
end

// Output register to pin
assign ser = outbit;


///////////////////////////////////////////////////////////////////////////////
// Test by outputting a letter 'd'

always @(posedge clk)
begin
data = 100;
start = 1;
end

endmodule


Answer



I don't speak Verilog, but I noticed that your stopbit is zero, which should be 1. Are you reading the port on a scope, or are you reading on a UART? In the latter case you may not have a character received if it doesn't see the stopbit.


No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...