Electronic – 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) 
    if (clockdiv == 5207) 
        clockdiv <= 0;
        clockdiv <= clockdiv + 1;

// 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)
   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

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

reg outbit;

always @(posedge clk)
    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

// Output register to pin
assign ser = outbit;

// Test by outputting a letter 'd'

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


Best 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.