Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21611 Discussions

State Machine- State doesn't set logic as expected

Altera_Forum
Honored Contributor II
1,059 Views

The folowing code is designed to convert a 24 bit value in to 4x 6 bit values to transmit over a 6 conductor cable. At each state I define what my output clock should be by assinging a logic level to GeneratedClk. For some reason the output I get doesn't match what I expect. The clock only makes one cycle low and then back to high. I am sure there must be some easy explanation of how I don't understand variables vs. signals or something, but I would appreciate some advice. 

 

 

entity DataTransmitter is 

 

port ( 

ClkEnablePort : buffer std_logic; 

 

DataRateClk : in std_logic; 

 

SendData : in std_logic; 

DataOutClk : out std_logic;  

 

BusIn : in std_logic_vector(23 downto 0); 

BusOut : buffer std_logic_vector(5 downto 0);  

 

SendComplete : buffer std_logic; 

 

Reset : in std_logic  

); 

 

end DataTransmitter; 

 

architecture behavior of DataTransmitter is 

 

type state is ( WaitingForData, Triggered, 

SendBits0, LatchBits0, SendBits1, LatchBits1, 

SendBits2, LatchBits2, SendBits3, LatchBits3, 

SendFinish ); 

 

signal pr_state, nx_state : state; 

signal GeneratedClk : std_logic; 

 

signal Hold0 : std_logic_vector(5 downto 0); --Least Significant Bits 

signal Hold1 : std_logic_vector(5 downto 0); 

signal Hold2 : std_logic_vector(5 downto 0); 

signal Hold3 : std_logic_vector(5 downto 0);  

 

begin 

 

 

---------- Advance States ----------  

process( Reset, SendData, DataRateClk ) 

 

begin 

 

if( Reset = '1') then  

pr_state <= WaitingForData; 

 

elsif ( SendData = '1' and pr_state = WaitingForData ) then 

pr_state <= Triggered; 

Hold0 <= BusIn(5 downto 0); 

Hold1 <= BusIn(11 downto 6);  

Hold2 <= BusIn(17 downto 12);  

Hold3 <= BusIn(23 downto 18);  

 

elsif ( rising_edge(DataRateClk) ) then  

pr_state <= nx_state; 

 

end if; 

 

end process; 

 

---------- Create Results for State Change ----------  

process( pr_state ) 

 

variable SendThisData : std_logic_vector(5 downto 0);  

variable GeneratedClk : std_logic; 

 

begin 

 

case pr_state is  

when WaitingForData => 

 

nx_state <= WaitingForData; 

GeneratedClk := '1';  

SendComplete <= '0'; 

SendThisData := "000000"; 

 

 

when Triggered => 

nx_state <= SendBits0;  

GeneratedClk := '1';  

 

-----------------  

when SendBits0 => 

nx_state <= LatchBits0; 

 

GeneratedClk := '0';  

SendThisData := Hold0; 

 

when LatchBits0 => 

nx_state <= SendBits1;  

 

GeneratedClk := '1';  

SendThisData := Hold0; 

----------------- 

 

-----------------  

when SendBits1 => 

nx_state <= LatchBits1; 

 

GeneratedClk := '0';  

SendThisData := Hold1; 

 

when LatchBits1 => 

nx_state <= SendBits2;  

 

GeneratedClk := '1';  

SendThisData := Hold1; 

----------------- 

 

-----------------  

when SendBits2 => 

nx_state <= LatchBits2; 

 

GeneratedClk := '0';  

SendThisData := Hold2; 

 

when LatchBits2 => 

nx_state <= SendBits3; 

 

GeneratedClk := '1';  

SendThisData := Hold2; 

----------------- 

 

-----------------  

when SendBits3 => 

nx_state <= LatchBits3; 

 

GeneratedClk := '0';  

SendThisData := Hold3; 

 

when LatchBits3 => 

nx_state <= SendFinish;  

 

GeneratedClk := '1';  

SendThisData := Hold3; 

-----------------  

 

when SendFinish => 

GeneratedClk := '1';  

SendThisData := "000000"; 

 

SendComplete <= '1'; 

 

when others =>  

nx_state <= WaitingForData;  

 

end case; 

 

DataOutClk <= GeneratedClk;  

BusOut <= SendThisData; 

 

end process;
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
405 Views

Do not use buffer(obsolete).Your state transition is tied up to elsif... 

 

If you just want to serialise 24 bits into time muxed 6 bits then there might be easier ways of doing what you want e.g. 

 

signal count: integer range 0 to 3; process(reset,clk) begin if reset = '1' then count <= 0; input_en <= '0'; BusOut <= (others => '0'); elsif rising_edge(clk) then count <= count + 1; case count is when 0 => BusOut <= BusIn(17 downto 12); input_en <= '1'; when 1 => BusOut<= BusIn(23 downto 18); input_en <= '0'; when 2 => BusOut <= BusIn(5 downto 0); input_en <= '0'; when 3 => BusOut <= BusIn(11 downto 6); input_en <= '0'; end case; end process; 

 

the input_en pulse is to control the input rate(= input clk/4). It needs some care to synchronise the data request to the front module. I have assumed the request is raised at count 0, becomes high at count 1 and data is available soon at count 2. Such design is called pull data flow(not push)
0 Kudos
Altera_Forum
Honored Contributor II
405 Views

a good question

0 Kudos
Altera_Forum
Honored Contributor II
405 Views

Thanks for the tips. 

 

The state machine I had created was designed to latch-out the data on the SendBit(0-3) states and then send a rising edge (DataOutClk) on the LatchBits(0-3) states for the receiver to use to latch the data into the receiver. Unfortunately for some reason the DataOutClk doesn't toggle at every state as I would expect. It seems to skip the middle states. I believe that it enters the states but just doesn't toggle the DataOutClk by setting the GeneratedClk each time.
0 Kudos
Reply