1
votes

I am trying to send multiple bytes on the SPI bus during the transmit window. Initially I am acquiring data from the flash ADC when the input pulse is high, then calculating its average and transmitting each average value sequentially on the SPI bus. I got the SPI vhdl module working, it was able to send data when I tried sending a single byte, but when I try to send more than 1 byte it just does not work. There is logic 0 on the MOSI line and the SS line is constantly high. This is the part where I try to send multiple bytes.

process(SPITrig, Clock, TX_Done, data_count, average2A_s, average2B_s)
begin
    case data_count is
        when 1 => 
            TX_Data <= average2A_s;
        when 2 => 
            TX_Data <= average2B_s;
        when others => TX_Data <= "0101010101010101";
    end case;
end process;

process(SPIBusy, SPITrig, SPI_Clock_base, data_count, TX_Start) 
begin
     if falling_edge(SPITrig) then
        SPIBusy <= '1';
        TX_Start <= '0';
        data_count <= 0;
        delay_counter <= 0;
     end if;
     if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
        if data_count < 3 then
            if delay_counter = 128 then
                TX_Start <= not TX_Start;
                delay_counter <= 0;
            elsif delay_counter < 128 then
                delay_counter <= delay_counter + 1;
            end if;

         elsif data_count >= 3 then
            TX_Start <= '0';
            delay_counter <= 0;
            SPIBusy <= '0';
        end if;
    end if; 
    if rising_edge(TX_Start) then
        data_count <= data_count + 1;
    end if;
end process;

It works perfectly well in simulation, but theres no output on the hardware. Need your help in finding out whats wrong. PS: This is my first FPGA project, so my code may not be so efficient. I have also attached the ISIM screenshot.

http://i.stack.imgur.com/TYDVZ.png clickable

tx = TX Done pin
trig = TX Start ping
c1 = data count

Note: SPI transmission sequence starts when average outputs are available and it is triggered using an internal signal"SPITRig".

2

2 Answers

3
votes

Take a look at the synthesis and timing (STA) warnings, since these will indicate if the synthesis tool could not implement the design to match the RTL VHDL code.

The edge condition by rising_edge(...) or falling_edge(...) should only be used on a single common clock signal, unless there is a good reason for use of multiple clock signals; and usually only rising_edge(...) is used.

In your design you have three different signal SPITrig, SPI_Clock_base, and TX_Start that work like clocks, and this is likely to give a timing violation.

As example, in the first if of the large process, the TX_Start and data_count are both updated on the falling_edge(SPITrig), and in the last if the rising_edge(TX_Start) is used to update data_count again based on current data_count value. This may work fine in simulation, but in HW you have signal propagation delay, which depends on routing and other factors that may wary for different signals, so a design construction like that is likely to give problems in implementation.

If you have a full Static Timing Analysis (STA) setup for your design, which you probably don't have for a first time FPGA project, then the STA tool will report if the timing can be meet, and a construction like the above is likely to not meet timing.

So instead, rewrite your design to use only a single clock edge, for example rising_edge(SPI_Clock_base). It is also much easier to make a correct STA timing setup for such a design, and the sensitivity list of the processes should then only contain the clock and any asynchronous reset signals, if used, like:

process (SPI_Clock_base) is 
begin
  if rising_edge(SPI_Clock_base) then
    ...
  end if;
end process;

Finally, the sensitivity list of the initial process should be reduced to only contain the signals that are read in the process, since the process need only to be sensitive to the these signals. The design won't fail if more signals are included, it makes the reader wonder what is wrong; the sensitivity list or the code.

2
votes

As suggested by Morten Zilmer, I made the necessary changes to synchronize everything with the Clock. following is the code and it is working. Might post a screenshot from an oscilloscope later.

process(SPITrig, data_count, average2A_s, average2B_s)
        begin
            case data_count is
                when 1 => 
                    TX_Data <= average2A_s;
                when 2 => 
                    TX_Data <= average2B_s;
                when others => TX_Data <= x"0000";
            end case;
        end process;

        SPICycler : process(delay_counter, data_count, SPITrig, SPI_Clock_base, SPIBusy)
        begin
            if rising_edge(SPI_Clock_base) and SPIBusy = '1' then
                if delay_counter < 511 then
                    delay_counter <= delay_counter + 1;
                    TX_Start <= '0';
                else
                    delay_counter <= 0;
                    TX_Start <= '1';
                    data_count <= data_count + 1;
                end if;

            end if;
            if rising_edge(SPI_Clock_base) then
                if SPITrig = '1' then
                    SPIBusy <= '1';
                    data_count <= 0;
                end if;
                if data_count = 3 then
                    SPIBusy <= '0';
                end if;
            end if;
        end process;