OpenCores
URL https://opencores.org/ocsvn/quad_decoder/quad_decoder/trunk

Subversion Repositories quad_decoder

[/] [quad_decoder/] [trunk/] [quad_decoder.vhd] - Diff between revs 2 and 3

Show entire file | Details | Blame | View Log

Rev 2 Rev 3
Line 3... Line 3...
--  Desc:       HDL implementation of a quadrature decoder with a Wishbone bus
--  Desc:       HDL implementation of a quadrature decoder with a Wishbone bus
--              interface. See the "quad_decoder" datasheet for more information.
--              interface. See the "quad_decoder" datasheet for more information.
--  Date:       Initiated October, 2009
--  Date:       Initiated October, 2009
--  Auth:       Scott Nortman, COPYRIGHT 2009 Bridge Electronic Design LLC
--  Auth:       Scott Nortman, COPYRIGHT 2009 Bridge Electronic Design LLC
--                              scott.nortman@gmail.com
--                              scott.nortman@gmail.com
--------------------------------------------------------------------------------
 
--
--
--              REVISION INFORMATION
--  NOTE:       If you find this file useful / helpful, please let me know :)
--
--
--              Current Version:        0.9.0
--------------------------------------------------------------------------------
--              
--              
--      When                    Who                             What
--      REVISION INFORMATION
--      ---------------------------------------------------------------------------
 
--      02NOV09         S. Nortman              Initial Release, v0.9.0
 
--
--
 
--      Current Version:    1.0.0
--
--
 
--      Nov. 2009
 
--      1)Initial beta release, upload to OpenCores.org.
 
--      2)Tested HDL implementation with in a Xilinx Spartan 3 AN FPGA, with
 
--      a softcore processor, the Tasking TSK3000.  Emulated a quadrature
 
--      encoder for initial verification.
 
--
 
--      July, 2010
 
--      1)Release version v1.0.0
 
--      2)Changes from prior release:
 
--      a) Bit 3 of the Quadrature Control Register (offset 0x00) is now changed
 
--      functions, to enable / disable of the Index Zero Count function.  When
 
--      the bit is 0, an index event does not affect the count. When the bit is
 
--      1, and index events are permitted, the internal quadrature count is set
 
--      to 0.
 
--      b) Added control bit 13, Index Read Count Bit.  When set to 0, no count
 
--      is latched. When set to 1, and index events are permitted, the internal
 
--      quadrature count is automatically latched to the QRW (offset 0x08)
 
--      register when an index event is true.  This is VERY useful for detection
 
--      of missed encoder counts, as you can assume that the delta counts in
 
--      between each index event is fixed, so any deviation from the expected
 
--      amount indicates that there were missed encoder counts.
 
--      3)Tested the FPGA implementation with a real encoder, verified proper
 
--      operation with count frequencies up to  1.3MHz (50MHz system clock)
 
--      This test used an instrumented motor driver, with a hardware qudrature
 
--      decoder in parallel with this encoder module.  This module did not miss
 
--      any counts with a 2048 quad counts / rev encoder running at 40e3 rpm.
 
--      4) Fixed a minor bug with the QCR_PLCT bit and the QCR_INZC bit; under
 
--      a specific condition that both the PLCT bit and the INZC bit were asserted
 
--      at the same clock cycle, the PLCT would have been executed while the INZC
 
--      event would have been missed.
 
--      5) Added an additional feature:  Quadrature Count Compare Match Event;
 
--      when the CCME bit is set in the QCR register, and the quadrature count
 
--      matches the QRW register, a signal is asserted and the status bit of the
 
--      QSR register is set.  This event can also generate an interrupt.
--
--
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_unsigned.all;
Line 51... Line 82...
 
 
    --Register and bit definitions
    --Register and bit definitions
   -----------------------------------------------------------------------------
   -----------------------------------------------------------------------------
   --   Quadrature Control Register, QCR, offset 0x00
   --   Quadrature Control Register, QCR, offset 0x00
   --
   --
   --   Bit 0:  Enable Counting, ENCT
   --   Bit 0:  Enable Counting, ECNT
   --       0 -> Quadrature counting disabled
   --       0 -> Quadrature counting disabled
   --       1 -> Quadrature counting enabled
   --       1 -> Quadrature counting enabled
   --   Bit 1:  Set Count Direction, CTDR
   --   Bit 1:  Set Count Direction, CTDR
   --       0 -> Counts positive when A leads B
   --       0 -> Counts positive when A leads B
   --       1 -> Counts negative when A leads B
   --       1 -> Counts negative when A leads B
   --   Bit 2:  Index Enable Bit, INEN
   --   Bit 2:  Index Enable Bit, INEN
   --       0 -> Index input disabled
   --       0 -> Index input disabled
   --       1 -> Index input enabled
   --       1 -> Index input enabled
   --   Bit 3:  Index Function Bit, INFC
   --   Bit 3:  Index Zero Count Bit, INZC
   --       0 -> Internal count not affected.
   --       0 -> Internal count not affected.
   --       1 -> Load count from pre load register
   --       1 -> Zero internal quad_count when quad_index is asserted.
   --   Bit 4:  Index Interrupt Enable, INIE
   --   Bit 4:  Index Interrupt Enable, INIE
   --       0 -> Index interrupt request disabled
   --       0 -> Index interrupt request disabled
   --       1 -> Index interrupt request enabled
   --       1 -> Index interrupt request enabled
   --   Bit 5:  Pre Load Count register, PLCT
   --   Bit 5:  Pre Load Count register, PLCT
   --       0 -> No action.
   --       0 -> No action.
Line 90... Line 121...
   --       0 -> Index asserted when quadature index is logic low
   --       0 -> Index asserted when quadature index is logic low
   --       1 -> Index asserted when quadrature index is logic high
   --       1 -> Index asserted when quadrature index is logic high
   --   Bit 12: Quadrature Error Interrupt enable, QEIE
   --   Bit 12: Quadrature Error Interrupt enable, QEIE
   --        0 -> Quadrature Error Interrupt disabled
   --        0 -> Quadrature Error Interrupt disabled
   --        1 -> Quadrature Error Interrupt enabled
   --        1 -> Quadrature Error Interrupt enabled
   --   Bits 31:13 -> Reserved, must always be written to 0
   --   Bit 13: Index Read Count Bit, INRC
 
   --        0 -> Quadrature Read / Write register not affected.
 
   --        1 -> Read the value of the quad. count to the QRW reg, when index event is true.
 
   --   Bit 14: Count Compare Match Enable, CCME
 
   --        0 -> No compare match event may occur.
 
   --        1 -> Compare match event asserted when enabled and QRW == quad_count
 
   --   Bit 15:  Compare Match Interrupt Enable, CMIE
 
   --        0 -> No interrupt generated when a compare match event is asserted.
 
   --        1 -> An external interrupt will be generated when the compare event is asserted.
 
   --   Bits 31:16 -> Reserved, must always be written to 0
   --
   --
   -----------------------------------------------------------------------------
   -----------------------------------------------------------------------------
    constant    QCR_ECNT    : integer := 0; --test ok
    constant    QCR_ECNT    : integer := 0;
    constant    QCR_CTDR    : integer := 1; --test ok
    constant    QCR_CTDR    : integer := 1;
    constant    QCR_INEN    : integer := 2; --test ok
    constant    QCR_INEN    : integer := 2;
    constant    QCR_INFC    : integer := 3; --test ok
    constant    QCR_INZC    : integer := 3;
    constant    QCR_INIE    : integer := 4; --test ok
    constant    QCR_INIE    : integer := 4;
    constant    QCR_PLCT    : integer := 5; --test ok
    constant    QCR_PLCT    : integer := 5;
    constant    QCR_UNIE    : integer := 6; --test ok
    constant    QCR_UNIE    : integer := 6;
    constant    QCR_OVIE    : integer := 7; --test ok
    constant    QCR_OVIE    : integer := 7;
    constant    QCR_QLAT    : integer := 8; --test ok
    constant    QCR_QLAT    : integer := 8;
    constant    QCR_ICHA    : integer := 9;     --test ok
    constant    QCR_ICHA    : integer := 9;
    constant    QCR_ICHB    : integer := 10;--test ok
    constant    QCR_ICHB    : integer := 10;
    constant    QCR_IDXL    : integer := 11;--test ok
    constant    QCR_IDXL    : integer := 11;
    constant    QCR_QEIE    : integer := 12;--test ok
    constant    QCR_QEIE    : integer := 12;
    constant    QCR_BITS    : integer := 13;    --Number of bits used in QCR register
    constant    QCR_INRC    : integer := 13;
 
    constant    QCR_CCME    : integer := 14;
 
    constant    QCR_CMIE    : integer := 15;
 
    constant    QCR_BITS    : integer := 16;    --Number of bits used in QCR register
    signal      qcr_reg     : std_logic_vector(QCR_BITS-1 downto 0);     --QCR register
    signal      qcr_reg     : std_logic_vector(QCR_BITS-1 downto 0);     --QCR register
 
    constant    QCR_ADDR    : std_logic_vector(1 downto 0) := "00";
 
 
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    --  Quadrature Status Register, QSR, offset 0x04
    --  Quadrature Status Register, QSR, offset 0x04
    --  Note:  User clears set bits by writing a 1 to the correspoding register
    --  Note:  User clears set bits by writing a 1 to the correspoding register
    --         bit.
    --         bit.
Line 125... Line 169...
    --      0 -> No underflow detected
    --      0 -> No underflow detected
    --      1 -> Counter underflow from 0x0000 to 0xFFFF
    --      1 -> Counter underflow from 0x0000 to 0xFFFF
    --  Bit 3:  Index event, INEV, auto set, user cleared
    --  Bit 3:  Index event, INEV, auto set, user cleared
    --      0 -> Index event has not occurred
    --      0 -> Index event has not occurred
    --      1 -> Index event occured, interrupt requested if INIE set
    --      1 -> Index event occured, interrupt requested if INIE set
    --  Bits 31:4   -> Reserved, will always read 0
    --  Bit 4: Count Compare Match Event, CCME, auto set, user cleared
 
    --      0 -> Compare match event has not occurred
 
    --      1- > Compare match event occurred, interrupt genetated if enabled
 
    --  Bits 31:5   -> Reserved, will always read 0
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    constant    QSR_QERR    : integer := 0; --test ok
    constant    QSR_QERR    : integer := 0;
    constant    QSR_CTOV    : integer := 1; --test ok
    constant    QSR_CTOV    : integer := 1;
    constant    QSR_CTUN    : integer := 2; --test ok
    constant    QSR_CTUN    : integer := 2;
    constant    QSR_INEV    : integer := 3; --test ok
    constant    QSR_INEV    : integer := 3;
    constant    QSR_BITS    : integer := 4;                     -- Num bits in QSR reg
    constant    QSR_CCME    : integer := 4;
 
    constant    QSR_BITS    : integer := 5;                             -- Num bits in QSR reg
    signal      qsr_reg     : std_logic_vector(QSR_BITS-1 downto 0);     --QSR register
    signal      qsr_reg     : std_logic_vector(QSR_BITS-1 downto 0);     --QSR register
 
    constant    QSR_ADDR    : std_logic_vector(1 downto 0) := "01";
 
 
    --Signals indicating status information for the QSR process
    --Signals indicating status information for the QSR process
    signal      quad_error  : std_logic;
    signal      quad_error  : std_logic;
    signal      quad_ovflw  : std_logic;
    signal      quad_ovflw  : std_logic;
    signal      quad_unflw  : std_logic;
    signal      quad_unflw  : std_logic;
    signal      quad_index  : std_logic;
    signal      quad_index  : std_logic;
 
    signal      quad_index_d : std_logic;
 
    signal      quad_index_d2: std_logic;
 
    signal      quad_comp   : std_logic;
 
 
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    --  Quadrature Count Read / Write Register, QRW, offset 0x08
    --  Quadrature Count Read / Write Register, QRW, offset 0x08
    --  Note:   The actual quadrature count value must be latched prior to
    --  Note:   The actual quadrature count value must be latched prior to
    --          reading from this register.  This may be triggered two ways:
    --          reading from this register.  This may be triggered two ways:
Line 153... Line 205...
    --          copied to the QCT register.
    --          copied to the QCT register.
    --
    --
    --          This register is also used to hold the pre-load count value.
    --          This register is also used to hold the pre-load count value.
    --          After writing to this register, the pre-load value is
    --          After writing to this register, the pre-load value is
    --          transferred to the quadrature count register by writing a '1'
    --          transferred to the quadrature count register by writing a '1'
    --          to bit location 6, quadrature pre-load count (QPLCT) of the
    --          to bit location 5, quadrature pre-load count (PLCT) of the
    --          quadrature control register (QCR) offset 0x00.
    --          quadrature control register (QCR) offset 0x00.
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    signal      qrw_reg     : std_logic_vector(QUAD_COUNT_WIDTH-1 downto 0);
    signal      qrw_reg     : std_logic_vector(QUAD_COUNT_WIDTH-1 downto 0);
 
    constant    QRW_ADDR    : std_logic_vector(1 downto 0) := "10";
 
 
    --Actual quadrature counter register, extra bit for over/underflow detect
    --Actual quadrature counter register, extra bit for over/underflow detect
    signal      quad_count  : std_logic_vector(QUAD_COUNT_WIDTH downto 0);
    signal      quad_count  : std_logic_vector(QUAD_COUNT_WIDTH downto 0);
 
 
    --Input buffers / filters for quadrature signals
    --Input buffers / filters for quadrature signals
Line 175... Line 228...
    signal      quad_chb_j  : std_logic;
    signal      quad_chb_j  : std_logic;
    signal      quad_chb_k  : std_logic;
    signal      quad_chb_k  : std_logic;
    signal      quad_idx_j  : std_logic;
    signal      quad_idx_j  : std_logic;
    signal      quad_idx_k  : std_logic;
    signal      quad_idx_k  : std_logic;
 
 
 
 
    signal quad_lat_flt : std_logic;
    signal quad_lat_flt : std_logic;
        signal quad_lat_q       : std_logic;
        signal quad_lat_q       : std_logic;
        signal quad_lat_m       : std_logic;
        signal quad_lat_m       : std_logic;
 
 
    --Quadrature 4X decoding state machine signals
    --Quadrature 4X decoding state machine signals
Line 201... Line 253...
    signal ack_dly : std_logic;
    signal ack_dly : std_logic;
 
 
    --Internal irq signal
    --Internal irq signal
    signal      quad_irq_int: std_logic;
    signal      quad_irq_int: std_logic;
 
 
 
    -- Internal signal to latch quad count on index assertion
 
    signal qcnt_idx_latch   : std_logic;
 
 
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    --Start of RTL
    --Start of RTL
    ----------------------------------------------------------------------------
    ----------------------------------------------------------------------------
    begin
    begin
 
 
 
        --Assign internal signal to external signal
        quad_irq_o  <= quad_irq_int;
        quad_irq_o  <= quad_irq_int;
 
 
        -- Handle wishbone ack generation / internal write signals
        -- Handle wishbone ack generation / internal write signals
        wb_request  <= wb_stb_i and wb_cyc_i;
        wb_request  <= wb_stb_i and wb_cyc_i;
        wb_write    <= wb_request and wb_we_i;
        wb_write    <= wb_request and wb_we_i;
Line 224... Line 278...
                --                              operations have completed before acknowledging the 
                --                              operations have completed before acknowledging the 
                --                              master device.
                --                              master device.
                --      Signals:        wb_clk_i
                --      Signals:        wb_clk_i
                --                              ack_dly
                --                              ack_dly
                --                              wb_rst_i
                --                              wb_rst_i
                --      Notes:          
        --  Notes:      Verified using the Wishbone bus of the TSK3000 from
 
        --              Altium Designer.
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
        ack_dly_proc: process( wb_clk_i ) begin
        ack_dly_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    ack_dly <= '0';
                    ack_dly <= '0';
Line 254... Line 309...
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        qcr_reg_wr_proc: process( wb_clk_i ) begin
        qcr_reg_wr_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    qcr_reg <= (others => '0');
                    qcr_reg <= (others => '0');
                elsif wb_write = '1' and wb_adr_i ="00" then
                elsif wb_write = '1' and wb_adr_i = QCR_ADDR then
                    qcr_reg <= wb_dat_i(QCR_BITS-1 downto 0);
                    qcr_reg <= wb_dat_i(QCR_BITS-1 downto 0);
                end if;
                end if;
                --See if PLCT asserted, should be auto-cleared
                --See if PLCT asserted, should be auto-cleared
                if qcr_reg(QCR_PLCT) = '1' then
                if qcr_reg(QCR_PLCT) = '1' then
                    qcr_reg(QCR_PLCT) <= '0';
                    qcr_reg(QCR_PLCT) <= '0';
Line 293... Line 348...
                    qsr_reg     <= (others => '0');
                    qsr_reg     <= (others => '0');
                else
                else
                    --Set qsr_reg bit from signal quad_error
                    --Set qsr_reg bit from signal quad_error
                    if quad_error = '1' and qcr_reg( QCR_ECNT) = '1' then
                    if quad_error = '1' and qcr_reg( QCR_ECNT) = '1' then
                        qsr_reg(QSR_QERR) <= '1';
                        qsr_reg(QSR_QERR) <= '1';
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_QERR) = '1' and wb_dat_i(QSR_QERR) = '1' then
                    elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_QERR) = '1' and wb_dat_i(QSR_QERR) = '1' then
                        qsr_reg(QSR_QERR) <= '0';
                        qsr_reg(QSR_QERR) <= '0';
                    end if;
                    end if;
                    --Set qsr_reg bit rom signal quad_ovflw
                    --Set qsr_reg bit rom signal quad_ovflw
                    if quad_ovflw = '1'and qcr_reg( QCR_ECNT) = '1' then
                    if quad_ovflw = '1' then
                        qsr_reg(QSR_CTOV) <= '1';
                        qsr_reg(QSR_CTOV) <= '1';
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_CTOV) = '1' and wb_dat_i(QSR_CTOV) = '1' then
                    elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CTOV) = '1' and wb_dat_i(QSR_CTOV) = '1' then
                        qsr_reg(QSR_CTOV) <= '0';
                        qsr_reg(QSR_CTOV) <= '0';
                    end if;
                    end if;
                    --Set qsr_reg bit from signal quad_unflw
                    --Set qsr_reg bit from signal quad_unflw
                    if quad_unflw = '1' and qcr_reg( QCR_ECNT) = '1' then
                    if quad_unflw = '1' then
                        qsr_reg(QSR_CTUN) <= '1';
                        qsr_reg(QSR_CTUN) <= '1';
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_CTUN) = '1' and wb_dat_i(QSR_CTUN) = '1' then
                    elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CTUN) = '1' and wb_dat_i(QSR_CTUN) = '1' then
                        qsr_reg(QSR_CTUN) <= '0';
                        qsr_reg(QSR_CTUN) <= '0';
                    end if;
                    end if;
                    --Set qsr_reg bit from signal quad_index
                    --Set qsr_reg bit from signal quad_index
                    if quad_index = '1' and qcr_reg( QCR_ECNT) = '1' then
                    if quad_index = '1' then
                        qsr_reg(QSR_INEV) <= '1';
                        qsr_reg(QSR_INEV) <= '1';
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_INEV) = '1' and wb_dat_i(QSR_INEV) = '1' then
                    elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_INEV) = '1' and wb_dat_i(QSR_INEV) = '1' then
                        qsr_reg(QSR_INEV) <= '0';
                        qsr_reg(QSR_INEV) <= '0';
                    end if;
                    end if;
 
                    --check quadrature compare bit
 
                    if quad_comp = '1' then
 
                        qsr_reg(QSR_CCME) <= '1';
 
                    elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CCME) = '1' and wb_dat_i(QSR_CCME) = '1' then
 
                        qsr_reg(QSR_CCME) <= '0';
 
                    end if;
                end if;
                end if;
            end if;
            end if;
        end process qsr_reg_wr_proc;
        end process qsr_reg_wr_proc;
 
 
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        --  Process:    qrw_reg_wr_proc( wb_clk_i )
        --  Process:    qrw_reg_wr_proc( wb_clk_i )
        --  Desc:       Handles writing to the Quadrature Read / Write Register,
        --  Desc:       Handles writing to the Quadrature Read / Write Register,
        --              offset 0x08.
        --              offset 0x08.
        --  Signals:    
        --  Signals:    wb_rst, reset signal
 
        --              QLAT bit of QCR reg, Quadrature latch
 
        --              quad_lat_flt, filtered external quadrature latch signal
 
        --  Notes:      Use of this register is required to access the
 
        --              quadrature count.
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        qrw_reg_wr_proc: process( wb_clk_i ) begin
        qrw_reg_wr_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    qrw_reg <= (others =>'0');
                    qrw_reg <= (others =>'0');
                elsif wb_write = '1' and wb_adr_i = "10" then
                elsif wb_write = '1' and wb_adr_i = QRW_ADDR then
                    qrw_reg <= wb_dat_i;
                    qrw_reg <= wb_dat_i;
                elsif qcr_reg(QCR_QLAT) = '1' or quad_lat_flt = '1' then
                elsif qcr_reg(QCR_QLAT) = '1' or quad_lat_flt = '1' or (qcr_reg(QCR_INRC) = '1' and quad_index = '1') then
                    qrw_reg <= quad_count(QUAD_COUNT_WIDTH-1 downto 0);
                    qrw_reg <= quad_count(QUAD_COUNT_WIDTH-1 downto 0);
                end if;
                end if;
            end if;
            end if;
        end process qrw_reg_wr_proc;
        end process qrw_reg_wr_proc;
 
 
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        --  Process:    quad_regs_rd_proc( wb_clk_i )
        --  Process:    quad_regs_rd_proc( wb_clk_i )
        --  Desc:       Handles reading of all of the registers.
        --  Desc:       Handles reading of all of the registers.
        --  Signals:
        --  Signals:    wb_adr_i, Wishbone address input
 
        --              qcr_reg, Quadrature control register
 
        --              qsr_reg, Quadrature status register
 
        --              qrw_reg, Quadrature read/write register
 
        --  Notes:      None.
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        quad_regs_rd_proc: process( wb_rst_i, wb_adr_i, qcr_reg, qsr_reg, qrw_reg ) begin
        quad_regs_rd_proc: process( wb_adr_i, qcr_reg, qsr_reg, qrw_reg ) begin
                        case wb_adr_i is
                        case wb_adr_i is
                                when "00"   =>
                when QCR_ADDR   =>
                                        wb_dat_o(QCR_BITS-1 downto 0) <= qcr_reg;
                                        wb_dat_o(QCR_BITS-1 downto 0) <= qcr_reg;
                                        wb_dat_o(31 downto QCR_BITS) <= (others => '0');
                                        wb_dat_o(31 downto QCR_BITS) <= (others => '0');
                                when "01"   =>
                when QSR_ADDR   =>
                                        wb_dat_o(QSR_BITS-1 downto 0) <= qsr_reg;
                                        wb_dat_o(QSR_BITS-1 downto 0) <= qsr_reg;
                                        wb_dat_o(31 downto QSR_BITS) <= (others => '0');
                                        wb_dat_o(31 downto QSR_BITS) <= (others => '0');
                                when "10"   =>
                when QRW_ADDR   =>
                                        wb_dat_o(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
                                        wb_dat_o(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
                                when others =>
                                when others =>
                                        wb_dat_o    <= (others => '0' );
                                        wb_dat_o    <= (others => '0' );
                        end case;
                        end case;
        end process quad_regs_rd_proc;
        end process quad_regs_rd_proc;
 
 
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
                --      Process:        quad_lat_m_proc( wb_clk_i )
                --      Process:        quad_lat_m_proc( wb_clk_i )
                --      Desc:           Rising edge detect for input quad_lat_i
                --      Desc:           Rising edge detect for input quad_lat_i
                --
        --  Signals:    quad_lat_i, external quadratire latch input
 
        --              quad_lat_m, metastable quadature latch signal
 
        --  Note:       This is an asynchronous signal; the metastable
 
        --              output is later latched to a synchronized internal
 
        --              signal for other module processes.
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
                quad_lat_m_proc : process( quad_lat_i ) begin
                quad_lat_m_proc : process( quad_lat_i ) begin
                        if rising_edge( quad_lat_i ) then
                        if rising_edge( quad_lat_i ) then
                                if wb_rst_i = '1' then
                                if wb_rst_i = '1' then
                                        quad_lat_m <= '0';
                                        quad_lat_m <= '0';
Line 373... Line 446...
 
 
                                if quad_lat_m = '1' then
                                if quad_lat_m = '1' then
                                        quad_lat_m      <= '0';
                                        quad_lat_m      <= '0';
                                end if;
                                end if;
                        end if;
                        end if;
                end process;
        end process quad_lat_m_proc;
 
 
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
                --      Process:        quad_lat_proc
                --      Process:        quad_lat_proc
                --      Desc:           Metastable filter for quad_lat_i, sets internal signal
                --      Desc:           Metastable filter for quad_lat_i, sets internal signal
                --
        --  Signals:    quad_lat_m, metastable latch signal
 
        --              quad_lat_q, stable latched signal
 
        --              quad_lat_flt, filtered signal used by other processe
 
        --  Note:       Due to the filtering, there is a delay of 4 clk cycles
 
        --              from assertion of the signal until asserting internal
 
        --              processes.
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
        quad_lat_proc: process( wb_clk_i) begin
        quad_lat_proc: process( wb_clk_i) begin
 
 
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
 
 
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
 
 
                    quad_lat_flt    <= '0';
                    quad_lat_flt    <= '0';
                                        quad_lat_q              <= '0';
                                        quad_lat_q              <= '0';
 
 
                else
                else
                                        if quad_lat_m = '1' then
                                        if quad_lat_m = '1' then
                                                quad_lat_q      <= '1';
                                                quad_lat_q      <= '1';
                                        end if;
                                        end if;
                                        if quad_lat_q = '1' then
                                        if quad_lat_q = '1' then
                                                quad_lat_q              <= '0';
                                                quad_lat_q              <= '0';
                                                quad_lat_flt    <= '1';
                                                quad_lat_flt    <= '1';
                                        end if;
                                        end if;
 
 
                    if quad_lat_flt = '1' then
                    if quad_lat_flt = '1' then
                        quad_lat_flt <= '0';
                        quad_lat_flt <= '0';
                    end if;
                    end if;
                end if;
                end if;
            end if;
            end if;
Line 415... Line 488...
        quad_idx_j  <= quad_idx_buf(3) and quad_idx_buf(2) and quad_idx_buf(1);
        quad_idx_j  <= quad_idx_buf(3) and quad_idx_buf(2) and quad_idx_buf(1);
        quad_idx_k  <= not( quad_idx_buf(3) or quad_idx_buf(2) or quad_idx_buf(1) );
        quad_idx_k  <= not( quad_idx_buf(3) or quad_idx_buf(2) or quad_idx_buf(1) );
 
 
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
                --      Process:        quad_filt_proc
                --      Process:        quad_filt_proc
                --      Desc:           Digital filters for the quadrature inputs
        --  Desc:       Digital filters for the quadrature inputs.  This is
                --
        --              implemented with serial shift registers on all inputs;
 
        --              similar to the digital filters of the HCTL-2016.  See
 
        --              that datasheet for more information.
 
        --  Signals:    quad_cha_i, external input
 
        --              quad_chb_i, external input
 
        --              quad_idx_i, external input
 
        --              quad_cha_buf, input buffer for filtering
 
        --              quad_chb_buf, input buffer for filtering
 
        --              quad_cha_flt, filtered cha signal
 
        --              quad_chb_flt, filtered chb signal
 
        --              quad_cha_j, j signal for jk FF
 
        --              quad_cha_k, k signal for jk FF
 
        --  Note:       Upon reset, all buffers are filled with the values
 
        --              present on the input pins.
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
        quad_filt_proc: process( wb_clk_i ) begin
        quad_filt_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    quad_cha_buf    <= ( quad_cha_i & quad_cha_i & quad_cha_i & quad_cha_i );
                    quad_cha_buf    <= ( quad_cha_i & quad_cha_i & quad_cha_i & quad_cha_i );
Line 459... Line 545...
        end process quad_filt_proc;
        end process quad_filt_proc;
 
 
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
                --      Process:        quad_state_proc
                --      Process:        quad_state_proc
                --      Desc:           Reads filtered values quad_cha_flt, quad_chb_flt and 
                --      Desc:           Reads filtered values quad_cha_flt, quad_chb_flt and 
                --                              increments / decrements count based on prior state
        --              asserts the quad_trans and quad_dir signals.
                --
        --  Signals:    quad_st_old
 
        --              quad_st_new
 
        --              quad_trans
 
        --              quad_dir
 
        --              quad_error
 
        --  Notes:      See the datasheet for more info.
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
        quad_state_proc: process( wb_clk_i ) begin
        quad_state_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    quad_st_old     <= (quad_chb_i & quad_cha_i);
                    quad_st_old     <= (quad_chb_i & quad_cha_i);
Line 473... Line 564...
                    quad_dir        <= '0';
                    quad_dir        <= '0';
                    quad_error      <= '0';
                    quad_error      <= '0';
                else
                else
                    quad_st_new <= (quad_chb_flt & quad_cha_flt);
                    quad_st_new <= (quad_chb_flt & quad_cha_flt);
                    quad_st_old <= quad_st_new;
                    quad_st_old <= quad_st_new;
                    --state machine
                    --state machine enabled if counting
 
                    if qcr_reg(QCR_ECNT) = '1' then
                    case quad_st_new is
                    case quad_st_new is
                        when QUAD_STATE_0 =>    --"00"
                        when QUAD_STATE_0 =>    --"00"
                            case quad_st_old is
                            case quad_st_old is
                                when QUAD_STATE_0 =>
                                when QUAD_STATE_0 =>
                                    quad_trans      <= '0';
                                    quad_trans      <= '0';
Line 580... Line 672...
                        when others =>
                        when others =>
                            quad_error  <= '1';
                            quad_error  <= '1';
                            quad_trans  <= '0';
                            quad_trans  <= '0';
                    end case; --quad_st_new
                    end case; --quad_st_new
 
 
 
                    end if;
 
 
                    if quad_trans = '1' then
                    if quad_trans = '1' then
                        quad_trans  <= '0';
                        quad_trans  <= '0';
                    end if;
                    end if;
 
 
                    if quad_dir = '1' then
                    if quad_dir = '1' then
Line 625... Line 719...
                --Reset event
                --Reset event
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    quad_count  <= (others =>'0');
                    quad_count  <= (others =>'0');
                    quad_ovflw  <= '0';
                    quad_ovflw  <= '0';
                    quad_unflw  <= '0';
                    quad_unflw  <= '0';
 
                else
                --Pre-load count event; either from qcr_reg or index event
                --Pre-load count event; either from qcr_reg or index event
                elsif qcr_reg(QCR_PLCT) = '1' or (quad_index = '1' and qcr_reg(QCR_INFC) = '1') then
                    if qcr_reg(QCR_PLCT) = '1' then
                    quad_count(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
                    quad_count(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
                    quad_count(QUAD_COUNT_WIDTH)            <= '0';
                    quad_count(QUAD_COUNT_WIDTH)            <= '0';
                else
                    end if;
                    if quad_trans = '1' and qcr_reg(QCR_ECNT) = '1' then
                    if (quad_index = '1' and qcr_reg(QCR_INZC) = '1') then
 
                        quad_count  <= (others =>'0');
 
                    end if;
 
                    if quad_trans = '1' then
                        if quad_dir = '1' then
                        if quad_dir = '1' then
                            quad_count  <= quad_count + 1;
                            quad_count  <= quad_count + 1;
                        else
                        else
                            quad_count  <= quad_count - 1;
                            quad_count  <= quad_count - 1;
                        end if;
                        end if;
Line 648... Line 746...
                            quad_unflw  <= '1';
                            quad_unflw  <= '1';
                        else
                        else
                            quad_ovflw  <= '1';
                            quad_ovflw  <= '1';
                        end if;
                        end if;
                    end if;
                    end if;
 
                end if;
                    --reset signals
                    --reset signals
                    if quad_ovflw = '1' then
                    if quad_ovflw = '1' then
                        quad_ovflw  <= '0';
                        quad_ovflw  <= '0';
                    end if;
                    end if;
                    if quad_unflw = '1' then
                    if quad_unflw = '1' then
                        quad_unflw  <= '0';
                        quad_unflw  <= '0';
                    end if;
                    end if;
                end if;
                end if;
            end if;
 
        end process quad_count_proc;
        end process quad_count_proc;
 
 
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
 
        --  Preocess:   quad_comp_proc( wb_clk_i )
 
        --  Desc:       Monitors the quad_count and the qwr_reg to assert the
 
        --              the quad_comp signal.
 
        --  Signals:    wb_clk_i
 
        --              wb_rst_i
 
        --              quad_comp
 
        --  Note:       When enabled, the quad_comp signal will get asserted
 
        --              every time the quad_count is latched into the qrw reg.
 
        -----------------------------------------------------------------------
 
        quad_comp_proc : process( wb_clk_i ) begin
 
            if rising_edge( wb_clk_i ) then
 
                if wb_rst_i = '1' then
 
                    quad_comp <= '0';
 
                elsif (quad_count(QUAD_COUNT_WIDTH-1 downto 0) = qrw_reg) and qcr_reg(QCR_CCME) = '1' and qsr_reg(QSR_CCME) = '0' then
 
                    quad_comp <= '1';
 
                end if;
 
                if quad_comp = '1' then
 
                    quad_comp <= '0';
 
                end if;
 
            end if;
 
        end process quad_comp_proc;
 
 
 
        -----------------------------------------------------------------------
        --  Process:    quad_index_proc( wb_clk_i )
        --  Process:    quad_index_proc( wb_clk_i )
        --  Desc:       Controled the internal quad_index signal.  This signal is
        --  Desc:       Controls the internal quad_index signal.  This signal is
        --              asserted to indicated the occurance of an index event.
        --              asserted to indicated the occurance of an index event.
        --
        --  Signals:    quad_index
 
        --              quad_cha_flt
 
        --              quad_chb_flt
 
        --              quad_index
 
        --  Note:       None.
        -----------------------------------------------------------------------
        -----------------------------------------------------------------------
        quad_index_proc : process( wb_clk_i ) begin
        quad_index_proc : process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    quad_index <= '0';
                    quad_index <= '0';
                elsif qcr_reg(QCR_INEN) = '1' and qcr_reg(QCR_ICHA) = quad_cha_flt
                elsif qcr_reg(QCR_INEN) = '1'
                    and qcr_reg(QCR_ICHB) = quad_chb_flt and qcr_reg(QCR_IDXL) = quad_idx_flt then
                    and qcr_reg(QCR_ECNT) = '1'
 
                    and qcr_reg(QCR_ICHA) = quad_cha_flt
 
                    and qcr_reg(QCR_ICHB) = quad_chb_flt
 
                    and qcr_reg(QCR_IDXL) = quad_idx_flt then
 
                    quad_index_d  <= '1';
 
                end if;
 
                if quad_index_d = '1' then
 
                    quad_index_d <= '0';
 
                    quad_index_d2<= '1';
 
                end if;
 
                if quad_index_d2 ='1' then
 
                    quad_index_d2 <= '0';
                    quad_index  <= '1';
                    quad_index  <= '1';
                end if;
                end if;
                --If quad_index is asserted, clear signal
 
                if quad_index = '1' then
                if quad_index = '1' then
                    quad_index <= '0';
                    quad_index <= '0';
                end if;
                end if;
            end if;
            end if;
        end process quad_index_proc;
        end process quad_index_proc;
 
 
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
                --      Process:        quad_irq_proc
                --      Process:        quad_irq_proc
                --      Desc:
        --  Desc:       Handles writing to the internal signal quad_irq_int.
 
        --              This process checks to see if a valid interrupt signal
 
        --              is asserted along with the corresponding enable bit; if
 
        --              so, the external interrupt is asserted.
 
        --  Signals:    quad_irq_int
 
        --              quad_error
 
        --              quad_ovflw
 
        --              quad_unflw
 
        --              quad_index
 
        --              quad_comp
 
        --  Note:       The external interrupt is cleared after assertion when
 
        --              all status bits are cleared in the QSR register.
                --      
                --      
                -----------------------------------------------------------------------
                -----------------------------------------------------------------------
        quad_irq_proc: process( wb_clk_i ) begin
        quad_irq_proc: process( wb_clk_i ) begin
            if rising_edge( wb_clk_i ) then
            if rising_edge( wb_clk_i ) then
                if wb_rst_i = '1' then
                if wb_rst_i = '1' then
                    quad_irq_int  <= '0';
                    quad_irq_int  <= '0';
                elsif       ( quad_error = '1' and qcr_reg(QCR_QEIE) = '1' )
                elsif       ( quad_error = '1' and qcr_reg(QCR_QEIE) = '1' )
                        or  ( quad_ovflw = '1' and qcr_reg(QCR_OVIE) = '1' )
                        or  ( quad_ovflw = '1' and qcr_reg(QCR_OVIE) = '1' )
                        or  ( quad_unflw = '1' and qcr_reg(QCR_UNIE) = '1' )
                        or  ( quad_unflw = '1' and qcr_reg(QCR_UNIE) = '1' )
                        or  ( quad_index = '1' and qcr_reg(QCR_INIE) = '1' ) then
                        or  ( quad_index = '1' and qcr_reg(QCR_INIE) = '1' )
 
                        or  ( quad_comp  = '1' and qcr_reg(QCR_CMIE) = '1' ) then
                    quad_irq_int <= '1';
                    quad_irq_int <= '1';
                elsif quad_irq_int = '1' and
                elsif quad_irq_int = '1' and
                    not(    ( qsr_reg(QSR_QERR) = '1' and qcr_reg(QCR_QEIE) = '1' )
                    not(    ( qsr_reg(QSR_QERR) = '1' and qcr_reg(QCR_QEIE) = '1' )
                        or  ( qsr_reg(QSR_CTOV) = '1' and qcr_reg(QCR_OVIE) = '1' )
                        or  ( qsr_reg(QSR_CTOV) = '1' and qcr_reg(QCR_OVIE) = '1' )
                        or  ( qsr_reg(QSR_CTUN) = '1' and qcr_reg(QCR_UNIE) = '1' )
                        or  ( qsr_reg(QSR_CTUN) = '1' and qcr_reg(QCR_UNIE) = '1' )
                        or  ( qsr_reg(QSR_INEV) = '1' and qcr_reg(QCR_INIE) = '1' ) ) then
                        or  ( qsr_reg(QSR_INEV) = '1' and qcr_reg(QCR_INIE) = '1' )
 
                        or  ( qsr_reg(QSR_CCME) = '1' and qcr_reg(QCR_CMIE) = '1' ) ) then
                    quad_irq_int <= '0';
                    quad_irq_int <= '0';
                end if;
                end if;
            end if;
            end if;
        end process quad_irq_proc;
        end process quad_irq_proc;
 
 
 
 
end architecture quad_decoder_rtl;
end architecture quad_decoder_rtl;
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.