Date post: | 06-May-2015 |
Category: |
Engineering |
Upload: | rohit-singh |
View: | 240 times |
Download: | 6 times |
1
INTRODUCTION TO VLSI
A PROJECT REPORT
ON
MICROPROCESSOR-COMPATIBLE
QUADRATURE
DECODER/COUNTER DESIGN
ROHIT SINGH
M.TECH
VLSI SYSTEMS AND TECHNOLOGY
DEPARTMENT OF ELECTRICAL ENGINEERING
SHIV NADAR UNIVERSITY
2
Contents
1. Introduction 03
2. Quadrature decoder/counter 03
3. Optical shaft encoder (OSE) 03
3.1 Introduction 03
3.2 Signals having a quadrature phase relationship 04
4. Optical shaft encoder interface approach 05
4.1 Approach 1 05
4.2 Approach 2 05
5. Features of quadrature decoder/counter 05
5.1 Input signal noise filter 05
5.2 Four times decode 06
5.3 12-bit counter 07
5.4 Registered outputs that are readable “on the fly” 07
5.4.1 Reading the count “On the fly” 07
5.4.2 Double buffer register 08
5.5 8-bit microprocessor bus interfaces 08
6. Quadrature decoder/counter partition 08
7. VHDL Code 09
7.1 VHDL Code No. 1 (filter) 09
7.2 VHDL Code No. 2 (fx_decode) 10
7.3 VHDL Code No.3 (binary_cntr) 14
7.4 VHDL Code No.4 (inhibit_fsm) 15
7.5 VHDL Code No.5 (double_buff) 18
7.6 VHDL Code No.6 (mux) 19
7.7 VHDL Code No.7 (quad_decode) 19
3
1. Introduction
A microprocessor-compatible quadrature decoder/counter is used to interface an optical shaft
encoder (OSE) to a microprocessor‟s system bus. Quadrature decoder/counter find application in
digital data input subsystems and digital closed loop motion control systems.
2. Quadrature decoder/counter
Quadrature decoder/counter is used to decode the two input signal which are 90 degrees out of
phase. These signals are decoded to produce a count up pulse or a count down pulse. For
decoding in software, the A & B outputs are read by software, either via an interrupt on any edge
or polling, and the below table is used to decode the direction. For example, if the last value was
00 and the current value is 01, the device has moved one half step in the clockwise direction.
Coding for
clockwise rotation
Phase A B
1 0 0
2 0 1
3 1 1
4 1 0
Coding for
counter-clockwise
rotation
Phase A B
1 1 0
2 1 1
3 0 1
4 0 0
3. Optical shaft encoder (OSE)
3.1 Introduction
An optical shaft encoder (OSE) converts rotary mechanical motion into a digital output. It does
this by first converting the rotary of its shaft into interruptions of a light beam. It then converts
these light beam interruptions into electrical pulses.
One common use of OSE is on the front panel of an electronics instrument where it allows an
operator to increment or decrement a displayed parameter. For example, clockwise (CW)
rotation might cause the parameter to be incremented and counter clockwise (CCW) rotation
cause it to be decremented.
4
3.2 Signals having a quadrature phase relationship
When its shaft is rotated, the OSE produces two digital output waveforms, designated channel A
and channel B. These waveforms have a quadrature phase relationship.
5
4. Optical shaft encoder interface approach
There are two common approaches to interface an OSE to a microprocessor system‟s bus.
4.1 Approach 1
In a software-intensive approach, the microprocessor repeatedly inputs signals A and B from
OSE through input port. A software subroutine compares the newly read values of A and B with
a copy of the previously read values saved in memory. Based on this comparison, the subroutine
determines whether to increment or decrement a count variable in the microprocessor‟s memory.
This simple software approach requires that the microprocessor constantly monitor the OSE‟s
outputs to detect each change in their values.
4.2 Approach 2
To improve the performance of a system incorporating an OSE, the time-intensive
quadrature/decoder functions can be implemented in hardware. In this approach hardware
converts changes in A and B to a count that is stored in a register. A microprocessor-compatible
quadrature decoder/counter includes a bus interface that allows its count register to be read by a
microprocessor at any time.
5. Features of quadrature decoder/counter
Some features that quadrature decoder/counter IC might provide is:
1. Input signal noise filter
2. 4X decoder
3. 12-bit counter
4. Registered outputs that are readable “on the fly “
5. 8-bit microprocessor bus interface
5.1 Input signal noise filter
In an application environment, inputs A and B to the quadrature decoder/counter may be subject
to electrical noise. The quadrature decoder/counter must include features to minimize the effect
of both metastability from the asynchronous nature of inputs A and B and noise spikes of short
duration that might appear on these inputs.
Each input channel (A and B) is filtered by a separate copy of the digital noise filter (Shift
Register Digital Noise Filter).
6
Figure below shows a logic representation of a digital noise filter. The purpose of this filter is to
reject short duration noise spikes at its input cx. The filter‟s output y can change only after its
input has had the same value at three consecutive triggering clock edges. Input changes that have
duration of two or fewer clock cycles are rejected. Examination of the logic diagram indicates
that a valid input changes is delayed by five clock periods, one for each flip-flop, before it is seen
at the output.
A description of a functionally equivalent system is given in VHDL Code No. 1.
This code describes the functionality of the 4-bit shift register and J-K flip flop with gated inputs.
The first flip-flop of the shift register is used to reduce the chances of a metastable event if the
input data is asynchronous.
The filtered output is computed from the rightmost 3 bits of the shift register. If all three bits are
zeros “000”, then output Y is assigned a „0‟. If all three of these bits are ones “111”, then Y is
assigned a „1‟. For any other combination of these 3 bits, Y remains unchanged.
5.2 Four times decode
Since output signals A and B from the OSE have a quadrature relationship, if the counter in the
quadrature decoder/counter is enabled to count once for each quadrature of period of A, as
defined by its relationship with B, the effective resolution of the OSE is increased by a factor of
four.
The four times decode subsystem is a state machine that uses the system clock to detect each
time the combination of output values A and B changes. When this state machine detects such a
change, it asserts its count enable output (cnten) until the next triggering clock edge. A counter
enabled by cnten counts at the next triggering clock edge. The count enable output is
unasserted on this same clock edge. This finite state machine is described below.
7
5.3 12-bit counter
A counter enable input can also be added to a counter, so the counter only counts at a triggering
clock edge when it is enabled. If the counter is not enabled, its count remains the same at the
triggering clock edge.
A 12-bit binary up/down counter with a count enable input and a synchronous reset is described
in VHDL code No. 3. This counter‟s count direction can be reversed at any point in its count
sequence..
If an event on clk is positive edge, the inner if statement determines if the counter should be
reset. If not, the count enable signal cnten is checked to determine whether the counter is
enabled to count. If so, a case statement determines whether to count up or down. If the counter
is not enabled to count, its value remains unchanged.
5.4 Registered outputs that are readable “on the fly”
5.4.1 Reading the count “On the fly”
A problem can arise if a microprocessor directly reads the contents of a counter at the same time
the counter is being incremented (reads “on the fly”). The value read can be incorrect, containing
some bits from the old cont values that have not yet changed and some bits from the new count
value.
This problem is exacerbated in this application because the counter being read is wider than the
microprocessor‟s data bus. The counter is 12 bits and the microprocessor‟s data bus is only 8 bit
wide. This requires that the 12-bit data value be read as two different bytes, one containing the
most significant 4 bits of the count and the other containing the least significant 8 bits. Reading 2
bytes requires that the microprocessor execute two read bus cycles. The increased time period
8
over which the count is read increases the probability that the count might change while being
read.
5.4.2 Double buffer register
A double buffer register provides the solution to the problem of reading a counter “on the fly.”
The double buffer register is connected to the counter‟s output. While its inhibit input is „0‟, the
double buffer register stores a copy of the counter‟s output on each triggering clock edge.
However, when its inhibit input is a „1‟, the double buffer register leaves its stored value
unchanged.
A FSM is required to generate the inhibit signal. The FSM makes inhibit a „1‟ as soon as the
microprocessor starts to read the contents of the double buffer register, and returns inhibit to a
„0‟ after both bytes have been read.
5.5 8-bit microprocessor bus interfaces
Finally, a multiplexer is required to multiplex the 12-bit output of the double buffer register to
the 8-bit data bus output. The sel signal determines whether the high byte or low byte appears
on the multiplexer‟s outputs when oe_bar is asserted.
6. Quadrature decoder/counter partition
A block diagram of the first level partition of the quadrature decoder/counter‟s functions is
represented in figure below. There are seven components.
U0: shift register digital noise filter
U1: shift register digital noise filter
U2: four times decoder
U3: 12-bit counter
U4: double buffer
U5: inhibit FSM
U6: MUX
9
7. VHDL Code
7.1 VHDL Code No. 1 (filter)
library ieee;
use ieee.std_logic_1164.all;
entity filter is
port (cx, clk, rst_bar : in std_logic;
y : out std_logic) ;
end;
architecture behavior of filter is
begin
synch: process (clk)
variable q : std_logic_vector (3 downto 0) ;
begin
10
if rising_edge (clk) then
if rst_bar = '0' then
q := "0000";
y <= '0' ;
else
if q(2 downto 0 ) = "111" then --- filter
y <= '1' ;
elsif q(2 downto 0) = "000" then
y <= '0';
else
null ;
end if ;
q := cx & q (3 downto 1) ; -- right shift
end if ;
end if ;
end process ;
end behavior ;
7.2 VHDL Code No. 2 (fx_decode)
library ieee ;
use ieee.std_logic_1164.all ;
entity fx_decode is
port ( a, b, clk, rst_bar : in std_logic ;
cnten, up : out std_logic ) ;
end fx_decode ;
11
architecture behavior of fx_decode is
subtype state is std_logic_vector ( 1 downto 0) ;
signal present_state, next_state : state ;
constant state_p : state := "00" ;
constant state_q : state := "01" ;
constant state_r : state := "11" ;
constant state_s : state := "10" ;
begin
state_reg: process (clk)
begin
if rising_edge (clk ) then
if (rst_bar = '0' ) then
present_state <= (b, a);
else
present_state <= next_state ;
end if ;
end if ;
end process state_reg ;
outputs : process (a, b, present_state )
variable input : std_logic_vector (1 downto 0);
begin
input := (b, a) ;
case present_state is
12
when state_p =>
if input = "01" then up <= '1' ; cnten <= '1' ;
elsif input = "10" then up <= '0' ; cnten <= '1' ;
else up <= '-' ; cnten <= '0' ;
end if ;
when state_q =>
if input = "11" then up <= '1' ; cnten <= '1' ;
elsif input = "00" then up <= '0' ; cnten <= '1' ;
else up <= '-' ; cnten <= '0' ;
end if ;
when state_r =>
if input = "10" then up <= '1' ; cnten <= '1' ;
elsif input = "01" then up <= '0' ; cnten <= '1' ;
else up <= '-' ; cnten <= '0' ;
end if ;
when state_s =>
if input = "00" then up <= '1' ; cnten <= '1' ;
elsif input = "11" then up <= '0' ; cnten <= '1' ;
else up <= '-' ; cnten <= '0' ;
end if ;
13
when others => null ;
end case ;
end process ;
nxt_state: process (a, b, present_state)
variable input : std_logic_vector (1 downto 0);
begin
input := (b, a) ;
case present_state is
when state_p =>
if input = "01" then next_state <= state_q ;
elsif input = "10" then next_state <= state_s ;
else next_state <= state_p ;
end if ;
when state_q =>
if input = "11" then next_state <= state_r ;
elsif input = "00" then next_state <= state_p ;
else next_state <= state_q ;
end if ;
when state_r =>
if input = "10" then next_state <= state_s ;
14
elsif input = "01" then next_state <= state_q ;
else next_state <= state_r ;
end if ;
when state_s =>
if input = "00" then next_state <= state_p ;
elsif input = "11" then next_state <= state_r ;
else next_state <= state_s ;
end if ;
when others => null ;
end case ;
end process ;
end behavior ;
7.3 VHDL Code No.3 (binary_cntr)
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
entity binary_cntr is
port (clk, cnten, up, rst_bar : in std_logic;
q : out std_logic_vector (11 downto 0)) ;
end binary_cntr ;
architecture behavioral of binary_cntr is
begin
15
cntr: process (clk)
variable count_v : unsigned (11 downto 0) ;
begin
if rising_edge (clk) then
if rst_bar = '0' then
count_v := (others => '0' ) ;
elsif cnten = '1' then
case up is
when '1' => count_v := count_v + 1 ;
when others => count_v := count_v - 1 ;
end case ;
end if ;
end if ;
q <= std_logic_vector (count_v) ;
end process ;
end behavioral ;
7.4 VHDL Code No.4 (inhibit_fsm)
library ieee ;
use ieee.std_logic_1164.all ;
entity inhibit_fsm is
port ( rst_bar : in std_logic ;
clk, sel, oe_bar : in std_logic ;
inhibit : out std_logic );
end inhibit_fsm ;
16
architecture behav of inhibit_fsm is
type inhib_state is ( idle, byte1, byte2) ;
signal present_state, next_state : inhib_state;
begin
inhib_sreg: process (clk)
begin
if rising_edge (clk) then
if rst_bar = '0' then
present_state <= idle;
else
present_state <= next_state ;
end if ;
end if ;
end process ;
inhib_output: process (present_state)
begin
case present_state is
when byte1 | byte2 =>
inhibit <= '1' ;
when others =>
inhibit <= '0' ;
end case ;
end process ;
inhib_nxt_state: process (present_state, sel, oe_bar)
begin
17
case present_state is
when idle =>
if sel = '0' and oe_bar = '0' then
next_state <= byte1 ;
else
next_state <= idle ;
end if ;
when byte1 =>
if sel = '1' and oe_bar = '0' then
next_state <= byte2 ;
else
next_state <= byte1 ;
end if ;
when byte2 =>
if oe_bar ='1' then
next_state <= idle ;
elsif sel = '0' and oe_bar = '0' then
next_state <= byte1 ;
else
next_state <= byte2 ;
end if ;
end case ;
end process ;
end behav ;
18
7.5 VHDL Code No.5 (double_buff)
library ieee ;
use ieee.std_logic_1164.all ;
entity double_buff is
port (din : in std_logic_vector (11 downto 0) ;
rst_bar : in std_logic ;
clk : in std_logic ;
inhibit : in std_logic ;
dout : out std_logic_vector (11 downto 0)) ;
end double_buff ;
architecture behav of double_buff is
begin
freeze : process (clk)
begin
if rising_edge (clk) then
if rst_bar = '0' then
dout <= x"000" ;
elsif inhibit = '0' then
dout <= din ;
end if ;
end if ;
end process ;
end behav ;
19
7.6 VHDL Code No.6 (mux)
ibrary ieee ;
use ieee.std_logic_1164.all ;
entity mux is
port ( din : in std_logic_vector (11 downto 0);
sel : in std_logic ;
oe_bar : in std_logic ;
dout : out std_logic_vector (7 downto 0));
end mux ;
architecture behav of mux is
begin
dout <= "0000" & din (11 downto 8) when oe_bar = '0' and sel =
'0' else
din (7 downto 0) when oe_bar = '0' and sel = '1' else
(others => 'Z' );
end behav ;
7.7 VHDL Code No.7 (quad_decode)
Top-level structural description of quadrature decoder/counter
library ieee ;
use ieee.std_logic_1164.all ;
entity quad_decode is
port ( ch_a, ch_b, rst_bar : in std_logic ;
clk, sel, oe_bar : in std_logic ;
d : out std_logic_vector (7 downto 0 )) ;
end quad_decode ;
20
architecture structure of quad_decode is
component filter
port ( cx, clk, rst_bar : std_logic ;
y : out std_logic );
end component ;
component fx_decode
port (a, b, clk, rst_bar : in std_logic ;
cnten, up : out std_logic );
end component ;
component binary_cntr
port ( clk, cnten, up, rst_bar : in std_logic ;
q : out std_logic_vector (11 downto 0 ) );
end component ;
component double_buff
port (din : in std_logic_vector (11 downto 0) ;
rst_bar : in std_logic ;
clk : in std_logic ;
inhibit : in std_logic ;
dout : out std_logic_vector (11 downto 0) );
end component ;
component inhibit_fsm
21
port ( rst_bar : in std_logic ;
clk : in std_logic ;
sel : in std_logic ;
inhibit : out std_logic ;
oe_bar : in std_logic );
end component ;
component mux
port (din : in std_logic_vector (11 downto 0);
sel : in std_logic ;
oe_bar : in std_logic ;
dout : out std_logic_vector (7 downto 0));
end component ;
signal ch_a_sig, ch_b_sig, cnten_sig, up_sig : std_logic;
signal count_sig : std_logic_vector (11 downto 0);
signal dbl_buff_sig : std_logic_vector (11 downto 0) ;
signal inhibit_sig : std_logic ;
begin
u0 : filter port map
( cx => ch_a , clk => clk, rst_bar => rst_bar, y => ch_a_sig );
u1 : filter port map (
cx => ch_b, clk =>clk, rst_bar => rst_bar, y => ch_b_sig );
22
u2 : fx_decode port map (
a => ch_a_sig, b => ch_b_sig, clk => clk, rst_bar => rst_bar,
cnten => cnten_sig, up => up_sig );
u3 : binary_cntr port map (
clk => clk, cnten => cnten_sig, up => up_sig, rst_bar =>
rst_bar,
q => count_sig );
u4 : double_buff port map (
din => count_sig, rst_bar => rst_bar, clk => clk, inhibit =>
inhibit_sig,
dout => dbl_buff_sig );
u5 : inhibit_fsm port map (
rst_bar => rst_bar, clk => clk, sel => sel, inhibit =>
inhibit_sig,
oe_bar => oe_bar );
u6 : mux port map (
din => dbl_buff_sig, sel => sel, oe_bar => oe_bar , dout => d );
end structure ;