Thursday, March 31, 2011

Building an SPI interface... (part 2)

Now that we have a flexible clock generator the next thing to consider is the detection of signals for the clock/MISO and MOSI bus lines...

We know that the important times to receive or transmit information are the clock edges (both positive/rising and negative/falling).
We also know that the intervals between these edges (when the signal on the clock is stable) are the times we can setup to transmit on MISO or MOSI (depending on whether we are acting as a master or a slave.  The easiest way to do this is to use the clock edges to change the state of a registers that indicate the states of MISO and MOSI at the positive and negative edges... This way the state is available until it changes again (remember that when the clock is stable MISO and MOSI can change so it's not a good idea to use them directly).  If we also add registers for the positive and negative edges we can directly trigger other modules that new information is available (it's much easier to get the timing right using a register for the clock rather than using it directly).

Like most modules the hdl is easy in verilog (you probably should start to realize now that if the hdl is hard to understand you probably have a more complicated solution than is needed, or you may want to separate the design into multiple modules).

// below here we are not in the clock domain - need to see things not in sync with clock   
   always @ (posedge spi_clock) begin
      busdetect_spi_pos <= ~busdetect_spi_pos;
      if (spi_mosi == 1'b0)
        busdetect_mosi0 <= 1'b0;                               
      else if (spi_mosi != 1'b0)
        busdetect_mosi0 <= 1'b1;
      if (spi_miso == 1'b0)
        busdetect_miso0 <= 1'b0;                               
      else if (spi_miso != 1'b0)
        busdetect_miso0 <= 1'b1;
   end // read0 signals detect    
   always @ (negedge spi_clock) begin
      busdetect_spi_neg <= ~busdetect_spi_neg;
      if (spi_mosi == 1'b0)
        busdetect_mosi1 <= 1'b0;                               
      else if (spi_mosi != 1'b0)
        busdetect_mosi1 <= 1'b1;
      if (spi_miso == 1'b0)
        busdetect_miso1 <= 1'b0;                               
      else if (spi_miso != 1'b0)
        busdetect_miso1 <= 1'b1;
   end // read1 signals detect    
As usual, all of the full verilog files can be found here.  

Next we will build upon these to extract and transmit data from the bus.