FPGARelated.com
Forums

Clock triggered FSM

Started by electrin May 18, 2015
Hello boys,

I have got a small problem with my finite state machine which I have
written in VHDL recently. I tried to create "intelligent" counter
triggered by clock with frequency 2 Hz. 
This counter is built in one state of FSM and is started by pushing a
button on DE2 board.

Firstly, whole system is in IDLE state and if I push this button, state is
changed to COUNTING and counter begin to be incremented and his current
value is shown on LED display. After it reach value of modulo, the state
COUNTING is left back to IDLE and the counter is set up to zero.

My problem is that the counter doesn´t work correctly - the counting
value was too great. So I tried to solve it with this construction: if
(clk_tick´event and clk_tick = 1) then.... , there are some errors by
synthesis:
Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement
registers for assignments on this clock edge

Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for
"AUTOMAT:flg" because its behavior does not match any supported register
model


Please, does somebody have an idea to solve it? And what is it correct way
to write clock triggered FSM with two (or more) clock sources?
-----------------------------------------------------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

-- Entita
ENTITY Counter_FSM IS
GENERIC (
			REGSIZE  : integer := 8;    -- range of counter
			MODULO   : natural := 50  -- modulo value
			);  
PORT (
			CLK   	: IN STD_LOGIC;  -- puls 50 MHz
			CLK_tick : IN STD_LOGIC;  -- puls 2 Hz
			RESET   	: IN STD_LOGIC;  -- reset
			READY 	: OUT STD_LOGIC; -- counter is ready to start
			START_C	: IN STD_LOGIC;  -- start of counting
			DOUT 		: OUT STD_LOGIC_VECTOR(REGSIZE - 1 downto 0)  -- output
		);
END Counter_FSM;

--------------------------------------------------------------------------
--
-- Architecture of FSM
--
ARCHITECTURE Behavior OF Counter_FSM is

		type counterState is (IDLE, COUNTING);	-- states of FSM
		signal currCounterState : counterState;  	-- current state
		signal nextCounterState : counterState;	-- next state
		
		signal cnt : std_logic_vector(REGSIZE - 1 downto 0);  -- data register
for counter
	begin 
--------------------------------------------------------------------------
--
-- State update
		UPDATE: process(RESET, CLK)
			begin
				if (RESET = '0') then
					currCounterState <= IDLE;
				elsif (CLK'event and CLK = '1') then
					currCounterState <= nextCounterState;
				end if;
		end process;
--------------------------------------------------------------------------
--
-- Combi part

		COMBI: process (clk_tick, start_c, currCounterState)
			variable flg : std_logic := '0';
			 begin
				 if (clk_tick'event and clk_tick = '1') then
					 flg := '1';
 				end if;
				
				case currCounterState is
					when IDLE => 
						cnt <= (others => '0');	-- counter value = zero
					   READY <= '1';		       -- we can start
						if (start_c = '1') then -- if button is pushed
							nextCounterState <= COUNTING;	-- then go to COUNTING state
						end if;
					
					when COUNTING => 
						READY <= '0';
						if (flg = '1') then	-- Was there impuls of 2 Hz?
							cnt <= cnt + 1;			-- yes -> incrementing
							flg := '0';
							if (cnt = MODULO) then	-- if value of cnt = MODULO
								cnt <= (others => '0');	-- then cnt = zero
								nextCounterState <= IDLE;	-- and next state is IDLE
							end if;
						end if;
						
					when others => 
						nextCounterState <= IDLE;
				end case;
			-- OUTPUT 
				douT <= cnt;	
			end process;
--------------------------------------------------------------------------
			
end Behavior; 


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

Thank you very much.

Mirek

P.S.: I am sorry my English is not so good.
---------------------------------------
Posted through http://www.FPGARelated.com
Am Montag, 18. Mai 2015 11:29:37 UTC+2 schrieb electrin:
> My problem is that the counter doesn=B4t work correctly - the counting > value was too great. So I tried to solve it with this construction: if > (clk_tick=B4event and clk_tick =3D 1) then.... , there are some errors by > synthesis: > Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement > registers for assignments on this clock edge >=20 > Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for > "AUTOMAT:flg" because its behavior does not match any supported register > model
You should spend some time trying to figure out what discrete logic you wou= ld need to build your described logic, than figure out which logic you inte= nd to have and how to modify VHDL code to reach this. =20
> Please, does somebody have an idea to solve it? And what is it correct wa=
y
> to write clock triggered FSM with two (or more) clock sources?
Two clock sources in same architecture is something you should avoid unless= you are experienced. Each clock source builds one clock domain, signals co= rssing between different clock domains require proper handling (google for = clock domain crossing if you need more information about this topic) In your case, you should use the fast clock to oversample the slow clock an= d detect rising edge with a few clockcyles delay (of fast clock). if rising_edge(fastclock) then slow_sr <=3D slow_sr(3 downto 1) & slowclock; if slow_sr(3 downto 2) =3D "01" then -- rising edge on slowclock [..] =20 best regards, Thomas
On Monday, 18 May 2015 21:29:37 UTC+12, electrin  wrote:
> Hello boys,
Hi!
>
> I have got a small problem with my finite state machine which I have > written in VHDL recently. I tried to create "intelligent" counter > triggered by clock with frequency 2 Hz. > This counter is built in one state of FSM and is started by pushing a > button on DE2 board. >
In general, the latching of a flip flop can only be triggered by one edge (rising/faling) on clock signal, so when using multiple clocks things get tricky fast - you can't use one clock to load a value into a register and then another edge or clock to load a different value into the same register. You can sometimes use the flip-flop's async set and reset signals, but it is a slippery slope.... I think the easiest solution to your problem is rather than looking for an edge in the signal from the button, sample the signal in using the clock signal that runs the counter. Like this: clocked_proc: process(clk) begin if rising_edge(clk) then ... update the rest of your state ... btn_two_cycles_ago <= btn_one_cycle_ago; btn_one_cycle_ago <= btn; end if; end process; And then in your combinatorial process: if btn_two_cycles_ago = '0' and btn_one_cycle_ago = '1' then ... do this only when the button is pushed ... end if; Also, I'm not sure if the switches on the DE_0 board are debounced, but if the clock is slow enough (and 2Hz is..) this has the advantage of debouncing the button signal for you. Oh, and don't be tempted to use "if btn_one_cycle_ago = '0' and btn = '1' then....". If the btn signal changes at just as the clock edge hits (very unlikely at 2Hz!) then different parts of your design might see different values for 'btn' due to the time it takes for signals to propagate across your FPGA. A good rule is to always have at least one simple flip-flop between your design's logic and any outside signal with transitions that are not synchronized with the external clock. A better rule is to have at least two flip-flops, creating a two or three stage synchronizer, but for a button or switch one FFis plenty enough - the MTBF will be many times the rated life cycle of the switch, and with 2Hz clock extra 1/2 second delay for the extra FF will be quite noticeable. Mike.
On 5/18/2015 5:29 AM, electrin wrote:
> Hello boys, > > I have got a small problem with my finite state machine which I have > written in VHDL recently. I tried to create "intelligent" counter > triggered by clock with frequency 2 Hz. > This counter is built in one state of FSM and is started by pushing a > button on DE2 board. > > Firstly, whole system is in IDLE state and if I push this button, state is > changed to COUNTING and counter begin to be incremented and his current > value is shown on LED display. After it reach value of modulo, the state > COUNTING is left back to IDLE and the counter is set up to zero. > > My problem is that the counter doesn&acute;t work correctly - the counting > value was too great. So I tried to solve it with this construction: if > (clk_tick&acute;event and clk_tick = 1) then.... , there are some errors by > synthesis: > Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement > registers for assignments on this clock edge > > Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for > "AUTOMAT:flg" because its behavior does not match any supported register > model > > > Please, does somebody have an idea to solve it? And what is it correct way > to write clock triggered FSM with two (or more) clock sources?
I'm old school so when I write HDL code, I am actually "Describing Hardware" I picture in my head (the HD of HDL). Your hardware seems to have a split personality with part of it in the clocked portion of a process and part in the non-clocked portion. I expect this is not really what you intended. In fact, I expect your error is simply having a non-clocked portion of the process. I suggest you don't use your current clock edge detect code and return to using rising_edge(clk). http://lmgtfy.com/?q=rising_edge(clk) I also suggest you not use clk_tick as a clock, but rather use it as an enable to the main clock, clk. Then your entire circuit will be synchronous and no need to deal with clock domain crossings. -- Rick