VHDL code for quadrature encoder receiver module

Original document: Quadrature Encoder Receiver Module : An Implementation on FPGA (.pdf)

In the original document cited above, we discussed some designs of quadrature encoder receiver module where Verilog code listings were included. This supplementary article provides the same implementations using VHDL. The development flows remain the same for both design A and B, so we basically list the codes and show simulation results here without repeating the design details.

Design A

For Design A, the receiver module generates pulses at output pin U (up) or D (down), corresponding to whether A leads B, or A lags B, respectively (*). We showed the design process using STG (State Transition Graph) that yielded the results in equation (1) – (4) . The VHDL code for this implementation is in Listing 1 with simulation result shown in Figure 1. (The synthesis and behavioral simulation was performed using Xilinx Webpack 13.4 and Isim simulation, which could be downloaded from Xilinx website.

(*) It turns out that in the original document, the Karnaugh map for output U and D shuffles, so as the resulting equations (3) and (4). You could verify from the simulation in Figure 9. If this gives the wrong sense for your motor setup, simply switch equation (3) and (4). We do so in the VHDL code below.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity x4enc1 is
    Port ( A,B,Clk : in  STD_LOGIC;
           U,D : out  STD_LOGIC);
end x4enc1;
architecture Behavioral of x4enc1 is
 signal Q0, Q1 : STD_LOGIC;
begin
process (Clk)
begin
 if (Clk'event and Clk='1') then
  Q0 <= A xor B;
  Q1 <= B;
 end if;
end process;
U <= (not A and not B and Q1) or (not A and Q1 and not Q0) 
or (A and not Q1 and not Q0) or (A and B and not Q1);
D <= (not A and B and not Q1) or (not A and not Q1 and Q0) 
or (A and Q1 and Q0) or (A and not B and Q1);
end Behavioral;
Listing 1: VHDL code for X4 receiver module (Design A, STG method)

Figure 1: Simulation result for X4 receiver module (Design A, STG method)

Manually solving for logic equations using STG might be fun for simple problem, though it’s quite easy to make mistakes (as you can see). Such implementation is often referred to as “structural model.” With the advancement of computer technology and software, it’s preferred that we benefit from development tools as much as possible. For the receiver module design A, we can draw an ASM (Algorithmic State Machine) chart like it Figure 2 and write VHDL code from it directly, such as in Listing 2. This approach is named “behavioral model,” since we just describe what the model must do and leave the low-level synthesis to the software. The simulation result in Figure 3 confirms that the module has similar behavior as the STG design version, with much less human effort in the design process.

Figure 2: ASM chart for X4 receiver module (design A)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity x4enc2 is
    Port ( AB : in  STD_LOGIC_VECTOR (1 downto 0);
           Clk : in  STD_LOGIC;
           UD : out  STD_LOGIC_VECTOR (1 downto 0));
end x4enc2;

architecture Behavioral of x4enc2 is
 signal State: STD_LOGIC_VECTOR (1 downto 0) := "00";
 -- State 0 = "00", State 1 = "01",
-- State 2 = "10", State 3 = "11"
begin
process (CLk)
begin
 if (Clk'event and Clk='1') then
  case State is
   when "00" => -- State 0
    case AB is
     when "00" => UD <= "00";-- stays at State 0
     when "01" => UD <= "01"; State <= "11"; -- to State 3
     when "10" => UD <= "10"; State <= "01"; -- to State 1
     when others => UD <= "00";
    end case;
   when "01" =>  -- State 1
    case AB is
     when "00" => UD <= "01"; State <= "00"; -- to State 0
     when "10" => UD <= "00"; -- stays at State 1
     when "11" => UD <= "10"; State <= "10"; -- to State 2
     when others => UD <= "00";
    end case;
   when "10" => -- State 2
     case AB is
     when "01" => UD <= "10"; State <= "11"; -- to State 3
     when "10" => UD <= "01"; State <= "01"; -- to State 1
     when "11" => UD <= "00";  -- stays at State 2
     when others => UD <= "00";
    end case;
   when "11" => -- State 3
    case AB is
     when "00" => UD <= "10"; State <= "00"; -- to State 0
     when "01" => UD <= "00"; -- stays at State 3
     when "11" => UD <= "01"; State <= "10"; -- to State 2
     when others => UD <= "00";
    end case;
   when others => null; 
  end case;
 end if;
end process;

end Behavioral;

Listing 2: VHDL code for X4 receiver module (Design A, ASM method )

Figure 3: Simulation result for X4 receiver module (Design A, ASM method)

Design B

Design B in the original document refers to the X4 encoder receiver module intended to be used with a counter that accepts pulse and direction inputs. So the module must provide output P (pulse) and DIR (direction). Following the same discussion there, the resulting VHDL code is as in Listing 3, with simulation result shown in Figure 4.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity x4enc3 is
    Port ( A,B, Clk : in  STD_LOGIC;
           P,Dir : out  STD_LOGIC);
end x4enc3;

architecture Behavioral of x4enc3 is
signal Ar, Br : STD_LOGIC_VECTOR (1 downto 0) := "00";
begin
process (Clk,A,B)
begin
 if (Clk'event and Clk='1') then
  Ar <= (Ar(0)&A);
  Br <= (Br(0)&B);
  if (Ar = "01") then -- rising edge of A
   P <= '1';
   if (B = '0') then Dir <= '1'; -- A leads B
   else Dir <= '0';     -- B leads A
   end if;
  elsif (Ar = "10") then -- falling edge of A
   P <= '1';
   if (B = '1') then Dir <= '1'; -- A leads B
   else Dir <= '0';     -- B leads A
   end if;
  elsif (Br = "01") then -- positive edge of B
   P <= '1';
   if (A = '1') then Dir <= '1'; -- A leads B
   else Dir <= '0';     -- B leads A
   end if;
  elsif (Br = "10") then -- positive edge of B
   P <= '1';
   if (A = '0') then Dir <= '1'; -- A leads B
   else Dir <= '0';     -- B leads A
   end if;
  else P <= '0';
  end if;
 end if;
 
end process;
end Behavioral;

Listing 3: VHDL code for X4 receiver module (Design B)

Comments

Popular posts from this blog

An Introduction to Finite State Machine Design

PIC24E I2C communication with MCP4725

A Note on Output Compare (PWM) Module of PIC24E