- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a problem with implementation of finite state machine, which is responsible for detection of motor direction based on signals from HALL sensors. The system has three inputs (HALL1, HALL2, HALL3) and one output (DIR - '1' for clockwise and '0' for counterclockwise direction). The problem is, that I don't have access to any external clock signal with I could synchronize the work of state machine and involve transitions of states. I tried to solve this problem in few ways, which finally failed:
I have tried to produce synchronization signal using HALL signals - I've just put them together to XOR gate, which gave me a square wave. I wanted to make a transition between states during falling, as also rising edge of the square signal, but I got an error message: "Error (10628): VHDL error at DIR_AUT_SL.vhd(87): can't implement register for two clock edges combined with a binary operator". Actually, I've done some research in this case and found information, that is impossible to make a signal sensitive on both (rising and falling edge). And here is my question - maybe is somebody on this forum, who had some similar problem and would like to give me an advice. Maybe I should implement an asynchronous state machine, which doesn't need a clock signal? But how can I make a transition between states in such a case? I would be very grateful for any help. My VHDL code is below:
library ieee ;
use ieee.std_logic_1164 .all;
use ieee.std_logic_signed .all;
entity DIR_AUT_SL is
port ( H1_SL, H2_SL, H3_SL, clock: in STD_LOGIC ;
DIR_SIGNAL_1 : out STD_LOGIC );
END DIR_AUT_SL;
architecture behavior of DIR_AUT_SL is
type state_type is (A, B, C, D, E, F, G, H, I, J, K, L);
signal y_act, y_next : state_type ;
signal hall: std_logic_vector (0 to 2);
begin
hall <= H1_SL&H2_SL&H3_SL;
process (hall, y_act) -- state table
begin
case y_act is
when A => case hall is
when "101" => y_next <= B;
when "110" => y_next <= L;
when others => y_next <= A;
end case;
when B => case hall is
when "001" => y_next <= C;
when "100" => y_next <= G;
when others => y_next <= B;
end case;
when C => case hall is
when "011" => y_next <= D;
when "101" => y_next <= H;
when others => y_next <= C;
end case;
when D => case hall is
when "010" => y_next <= E;
when "001" => y_next <= I;
when others => y_next <= D;
end case;
when E => case hall is
when "110" => y_next <= F;
when "011" => y_next <= J;
when others => y_next <= E;
end case;
when F => case hall is
when "100" => y_next <= A;
when "010" => y_next <= K;
when others => y_next <= F;
end case;
when G => case hall is
when "101" => y_next <= B;
when "110" => y_next <= L;
when others => y_next <= G;
end case;
when H => case hall is
when "001" => y_next <= C;
when "100" => y_next <= G;
when others => y_next <= H;
end case;
when I => case hall is
when "011" => y_next <= D;
when "101" => y_next <= H;
when others => y_next <= I;
end case;
when J => case hall is
when "010" => y_next <= E;
when "001" => y_next <= I;
when others => y_next <= J;
end case;
when K => case hall is
when "110" => y_next <= F;
when "011" => y_next <= J;
when others => y_next <= K;
end case;
when L => case hall is
when "100" => y_next <= A;
when "010" => y_next <= K;
when others => y_next <= L;
end case;
when others => y_act <= A;
end case ;
end process ; -- state_table
process (clock)
begin
if (rising_edge(clock) OR falling_edge (clock)) then
y_act <= y_next ;
end if;
end process ;
process ( y_act ) -- output states
begin
case y_act is
when A => DIR_SIGNAL_1 <= '1';
when B => DIR_SIGNAL_1 <= '1';
when C => DIR_SIGNAL_1 <= '1';
when D => DIR_SIGNAL_1 <= '1';
when E => DIR_SIGNAL_1 <= '1';
when F => DIR_SIGNAL_1 <= '1';
when G => DIR_SIGNAL_1 <= '0';
when H => DIR_SIGNAL_1 <= '0';
when I => DIR_SIGNAL_1 <= '0';
when J => DIR_SIGNAL_1 <= '0';
when K => DIR_SIGNAL_1 <= '0';
when L => DIR_SIGNAL_1 <= '0';
end case ;
end process ; -- output states
end behavior ;
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can't infer a register with two edges.
I wouldn't advice you to go without clock. You need a faster clock that can cover both edge of your square signal. Then you can use the rise/fall of your square signal as clock enable.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, I understand - but how can I make my square signal twice faster in order to use it as clock enable? I need to add, that I have only access to 3 inputs (3 hall signals).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Yes, I understand - but how can I make my square signal twice faster in order to use it as clock enable? I need to add, that I have only access to 3 inputs (3 hall signals). --- Quote End --- isn't your clock input fast enough. then you can enable a clocked register on your squre signal edges.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did as you wrote and created register - code is below
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY CLK_REG IS
port (clk, reset : IN STD_LOGIC;
q1, q2 : OUT STD_LOGIC );
END CLK_REG;
ARCHITECTURE arch9 OF CLK_REG IS
BEGIN
-- Register with active-high clock
PROCESS (clk, reset)
BEGIN
IF reset = '0' THEN
q1 <= '0';
ELSIF clk'EVENT AND clk = '1' THEN
q1 <= '1';
END IF;
END PROCESS;
-- Register with active-low clock
PROCESS (clk, reset)
BEGIN
IF reset = '1' THEN
q2 <= '0';
ELSIF clk'EVENT AND clk = '0' THEN
q2 <= '1';
END IF;
END PROCESS;
END arch9;
I enabled this by clock created from hall signals and expected to get on my outputs: q1 = 1, and q2 = 0 when clock = 1; q1 = 0, and q2 = 1 when clock = 0; And this part works. Then I changed a synchronous part of my state machine as below:
process (q1, q2)
begin
if (q1 = '0' and q2 = '0') then
y_act <= A;
elsif (q2 = '1' and q1 = '0' ) then
y_act <= y_next;
elsif (q1 = '1' and q2 = '0') then
y_act <= y_next;
end if;
end process ;
Unfortunatelly this part doesn't work at all. It changes all the time states only between A and B. Can you tell what mistake I do in this case?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
your above logic will simply set q1 to 1 and q2 to 1 for ever once a clock edge arrives (assuming reset applied once).
What you need is a proper clock signal and not one gated from xoring HALL1/HALL2/HALL3. your clock signal could be just fast enough to sample the HLL signals as below. Without clock you cannot design safely. Once yu have clock independent of HALL signals then you sample to detect rising/falling edge of your original square signal as follows:
process
begin
if rising_edge(clk) then
sq_d <= square;
if square = '1' and sq_d = '0' then -- this is now clk enable
--do whatever at this edge
end if;
if square = '0' and sq_d = '1' then -- another clk enable
-- do whatever for falling edge
end if;
end if;
end process;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your answer. So, if I good understand - without external clock signal I can not deal with this task?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Thank you for your answer. So, if I good understand - without external clock signal I can not deal with this task? --- Quote End --- FPGA design is based on clk. However in some cases one can do without it (as did old digital engineers) provided you are really skilled in asynchronous design, I am not and so are most of fpga designers. Is't that difficult to get clock signal? designing asynchronously will be more difficult than getting a clk on board. At the end it might be just possible if your design is simple and accepts delay variations.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would like to renew this topic. After some time, I decided to design an asynchronous state machine. Code is below:
library ieee ;
use ieee.std_logic_1164 .all;
use ieee.std_logic_signed .all;
entity DIR_AUT is
port ( H1_SL, H2_SL, H3_SL: in STD_LOGIC ;
DIR_SIGNAL : out bit;
count : out STD_LOGIC_VECTOR (2 downto 0));
END DIR_AUT;
architecture behavior of DIR_AUT is
type state_type is (A, B, C, D, E, F);
signal y_act : state_type;
signal hall: std_logic_vector (0 to 2);
begin
hall <= H1_SL&H2_SL&H3_SL;
process (hall, y_act) -- state table
begin
case hall is
when "100" =>
if (y_act = B) then DIR_SIGNAL <= '1'; y_act <= A;
elsif (y_act = F) then DIR_SIGNAL <= '0'; y_act <= A;
else y_act <= A;
end if;
when "101" =>
if (y_act = C) then DIR_SIGNAL <= '1'; y_act <= B;
elsif (y_act = A) then DIR_SIGNAL <= '0'; y_act <= B;
else y_act <= B;
end if;
when "001" =>
if (y_act = D) then DIR_SIGNAL <= '1'; y_act <= C;
elsif (y_act = B) then DIR_SIGNAL <= '0'; y_act <= C;
else y_act <= C;
end if;
when "011" =>
if (y_act = E) then DIR_SIGNAL <= '1'; y_act <= D;
elsif (y_act = C) then DIR_SIGNAL <= '0'; y_act <= D;
else y_act <= D;
end if;
when "010" =>
if (y_act = F) then DIR_SIGNAL <= '1'; y_act <= E;
elsif (y_act = D) then DIR_SIGNAL <= '0'; y_act <= E;
else y_act <= E;
end if;
when "110" =>
if (y_act = A) then DIR_SIGNAL <= '1'; y_act <= F;
elsif (y_act = E) then DIR_SIGNAL <= '0'; y_act <= F;
else y_act <= F;
end if;
when others => y_act <= A;
end case ;
end process ; -- state_table
with y_act select
count <= "000" when A,
"001" when B,
"010" when C,
"011" when D,
"100" when E,
"101" when F,
"111" when others;
end behavior ;
I used additional count output as a help just see in every moment what is the actual state of FSM. So, transitions between states seems to be really well, bu the problem now is, taht the output DIR_SIGNAL doesn't change and during whole simulation is on the same level. I really can not find a mistake in above code. I would be really grateful, if you know where can be a problem.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Where is your testbench?
Have you also considered Kaz's comment that most FPGA designs are synchronous guys as that is how FPGAs are designed. You're unlikely to get Async help on this board. Why have you not used a clock?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Where is your testbench? Have you also considered Kaz's comment that most FPGA designs are synchronous guys as that is how FPGAs are designed. You're unlikely to get Async help on this board. Why have you not used a clock? --- Quote End --- The board, what I work with is self-built controller for BLDC motor, where Altera was prepared to do only combinational functions (CLK pins are not connected). I would like to implement additional feature in Altera without interference in hardware of this system - this is the reason, why I want to do this in asynchronous mode. Results of simulation are below. https://www.alteraforum.com/forum/attachment.php?attachmentid=8337 So, during first 30 ns DIR_SIGNAL is unsigned and this is correct. From 30 ns until 180 ns DIR_SIGNAL is 0 and this is also correct, because for clockwise direction this output should be 0. The problem is, that during changing direction of the motor (after 180 ns) the output DIR_SIGNAL doesn't change from 0 to 1 and I really don't understand why, because as you can see on 'count' output the transitions between states are good.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Have you checked the netlists to see if the logic it has created is as you expected?
You didnt show your testbench.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In my simulation(ModelSim) the output DIR_SIGNAL changes from 0 to 1 repeatedly. I used the three inputs set as clock patterns with periods 100,1000,2000

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page