sebmaster
Member level 1
Hello,
I have a very strange problem with my CPLD design.
In short, the excerpt below is designed to recieve a 22 bit word via SPI, then inform external logic it has recieved it. Only when the external logic signals that it has processed the word is the clear-to-send signal to be sent so the next one can be read in.
The problem is that sometimes it appears the word counter is incrementing too quickly or too slowly - if I look at it on the scope the CTS signal instead of changing at the end of the waveform will blip in the center between the rising edges of one SPI clock cycle. If I continue to send data it moves back and forth along the 22 cycles as if it was triggering too early and then being reset, or too late and it required another one or two cycles before the previous set was complete.
The 'jumping' doesnt happen all the time, it takes a few transmissions to throw it off, and when I first program the device it works fine for a while.
It isn't an off-by-one error with my VHDL as ive tested with both +/-1 on the threshold value and in both cases I could get consistent shifting of the CTS signal with respect to the waveform (left or right depending on whether the value was too small or too high).
Whats tricky about this is that the SPI clock is completely independant of the clock for the rest of the logic, hence the seperate process and 'propagate' signal to try and sync them.
I suspect it is something to do with the asynchronous clear resetting the counter somehow, or being high during an SPI clock cycle and throwing it off, but I just cant see how it could happen!
I have a very strange problem with my CPLD design.
In short, the excerpt below is designed to recieve a 22 bit word via SPI, then inform external logic it has recieved it. Only when the external logic signals that it has processed the word is the clear-to-send signal to be sent so the next one can be read in.
The problem is that sometimes it appears the word counter is incrementing too quickly or too slowly - if I look at it on the scope the CTS signal instead of changing at the end of the waveform will blip in the center between the rising edges of one SPI clock cycle. If I continue to send data it moves back and forth along the 22 cycles as if it was triggering too early and then being reset, or too late and it required another one or two cycles before the previous set was complete.
The 'jumping' doesnt happen all the time, it takes a few transmissions to throw it off, and when I first program the device it works fine for a while.
It isn't an off-by-one error with my VHDL as ive tested with both +/-1 on the threshold value and in both cases I could get consistent shifting of the CTS signal with respect to the waveform (left or right depending on whether the value was too small or too high).
Whats tricky about this is that the SPI clock is completely independant of the clock for the rest of the logic, hence the seperate process and 'propagate' signal to try and sync them.
I suspect it is something to do with the asynchronous clear resetting the counter somehow, or being high during an SPI clock cycle and throwing it off, but I just cant see how it could happen!
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.Numeric_STD.all;
ENTITY uC_Data_DeShifter IS
PORT(
serial_data_clock : IN STD_LOGIC;
serial_data_in : IN STD_LOGIC;
serial_clearToSend : OUT STD_LOGIC;
Word : OUT STD_LOGIC_VECTOR(21 downto 0);
WordReady : OUT STD_LOGIC;
Clear : IN STD_LOGIC;
SyncSystemClock : IN STD_LOGIC
);
END uC_Data_DeShifter;
ARCHITECTURE main OF uC_Data_DeShifter IS
shared variable data_register : BIT_VECTOR(21 downto 0);
shared variable word_counter : integer range 0 to 22 := 0;
signal propagate : std_logic := '0';
BEGIN
recv_data : PROCESS( serial_data_clock, Clear )
BEGIN
if Clear = '1' then
word_counter := 0;
serial_clearToSend <= '1';
propagate <= '0';
else
if serial_data_clock'event and serial_data_clock = '1' and propagate = '0' then
serial_clearToSend <= '0';
if word_counter < 21 then
data_register(0) := to_bit(serial_data_in);
data_register := data_register sll 1;
word_counter := word_counter + 1;
else
data_register(0) := to_bit(serial_data_in);
propagate <= '1';
end if;
end if;
end if;
END PROCESS;
sync_proc : PROCESS( SyncSystemClock )
BEGIN
if SyncSystemClock'event and SyncSystemClock = '1' then
if propagate = '1' then
Word <= to_stdlogicvector(data_register);
WordReady <= '1';
else
WordReady <= '0';
end if;
end if;
END PROCESS;
END main;