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

Subversion Repositories quad_decoder

[/] [quad_decoder/] [trunk/] [quad_decoder.vhd] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 scottnortm
--------------------------------------------------------------------------------
2
--  File:       quad_decoder.vhd
3
--  Desc:       HDL implementation of a quadrature decoder with a Wishbone bus
4
--              interface. See the "quad_decoder" datasheet for more information.
5
--  Date:       Initiated October, 2009
6
--  Auth:       Scott Nortman, COPYRIGHT 2009 Bridge Electronic Design LLC
7
--                              scott.nortman@gmail.com
8
--------------------------------------------------------------------------------
9
--
10
--              REVISION INFORMATION
11
--
12
--              Current Version:        0.9.0
13
--              
14
--      When                    Who                             What
15
--      ---------------------------------------------------------------------------
16
--      02NOV09         S. Nortman              Initial Release, v0.9.0
17
--
18
--
19
--
20
 
21
-------------------------------------------------------------------------------
22
 
23
library ieee;
24
use ieee.std_logic_1164.all;
25
use ieee.std_logic_unsigned.all;
26
 
27
entity quad_decoder is
28
    --Configurable quadrature counter width; default is 32 bits
29
    generic(    QUAD_COUNT_WIDTH    : integer   := 32 );
30
    port(   --Wishbone bus signals
31
            wb_clk_i    : in    std_logic;
32
            wb_rst_i    : in    std_logic;
33
            wb_stb_i    : in    std_logic;
34
            wb_cyc_i    : in    std_logic;
35
            wb_ack_o    : out   std_logic;
36
            --wb_adr_i    : in    std_logic_vector(3 downto 0);
37
                        wb_adr_i    : in    std_logic_vector(1 downto 0); --assumes 32 bit alignment
38
            wb_dat_o    : out   std_logic_vector(31 downto 0);
39
            wb_dat_i    : in    std_logic_vector(31 downto 0);
40
            wb_we_i     : in    std_logic;
41
            --Quadrature inputs
42
            quad_cha_i  : in    std_logic;  --Qudrature channel A
43
            quad_chb_i  : in    std_logic;  --Quadrature channel B
44
            quad_idx_i  : in    std_logic;  --Quadrature index
45
            quad_lat_i  : in    std_logic;  --Quadrature latch cnt input
46
            quad_irq_o  : out   std_logic   --Quadrature IRQ out
47
    );
48
end quad_decoder;
49
 
50
architecture quad_decoder_rtl of quad_decoder is
51
 
52
    --Register and bit definitions
53
   -----------------------------------------------------------------------------
54
   --   Quadrature Control Register, QCR, offset 0x00
55
   --
56
   --   Bit 0:  Enable Counting, ENCT
57
   --       0 -> Quadrature counting disabled
58
   --       1 -> Quadrature counting enabled
59
   --   Bit 1:  Set Count Direction, CTDR
60
   --       0 -> Counts positive when A leads B
61
   --       1 -> Counts negative when A leads B
62
   --   Bit 2:  Index Enable Bit, INEN
63
   --       0 -> Index input disabled
64
   --       1 -> Index input enabled
65
   --   Bit 3:  Index Function Bit, INFC
66
   --       0 -> Internal count not affected.
67
   --       1 -> Load count from pre load register
68
   --   Bit 4:  Index Interrupt Enable, INIE
69
   --       0 -> Index interrupt request disabled
70
   --       1 -> Index interrupt request enabled
71
   --   Bit 5:  Pre Load Count register, PLCT
72
   --       0 -> No action.
73
   --       1 -> Load value currently in pre load reg into count reg, auto clear
74
   --   Bit 6:  Underflow Interrupt Enable, UNIE
75
   --       0 -> Underflow event will not trigger an interrupt.
76
   --       1 -> Underflow event will trigger an interrupt
77
   --   Bit 7:  Overflow Interrupt Enable, OVIE
78
   --       0 -> Overflow event will not trigger an interrupt
79
   --       1 -> Overflow event will trigger an interrupt
80
   --   Bit 8:  Quadrature Count Latch, QLAT
81
   --       0 -> No action.
82
   --       1 -> Latch and store quad count in QRW register, auto cleared
83
   --   Bit 9:  Index Channel A configuration, ICHA
84
   --       0 -> Index asserted when quadrature channel A logic low
85
   --       1 -> Index asserted when quadrature channel A logic high
86
   --   Bit 10: Index Channel B configuration, ICHB
87
   --       0 -> Index asserted when quadrature channel B logic low
88
   --       1 -> Index asserted when quadrature channel B logic high
89
   --   Bit 11: Index Level configuration, IDXL
90
   --       0 -> Index asserted when quadature index is logic low
91
   --       1 -> Index asserted when quadrature index is logic high
92
   --   Bit 12: Quadrature Error Interrupt enable, QEIE
93
   --        0 -> Quadrature Error Interrupt disabled
94
   --        1 -> Quadrature Error Interrupt enabled
95
   --   Bits 31:13 -> Reserved, must always be written to 0
96
   --
97
   -----------------------------------------------------------------------------
98
    constant    QCR_ECNT    : integer := 0; --test ok
99
    constant    QCR_CTDR    : integer := 1; --test ok
100
    constant    QCR_INEN    : integer := 2; --test ok
101
    constant    QCR_INFC    : integer := 3; --test ok
102
    constant    QCR_INIE    : integer := 4; --test ok
103
    constant    QCR_PLCT    : integer := 5; --test ok
104
    constant    QCR_UNIE    : integer := 6; --test ok
105
    constant    QCR_OVIE    : integer := 7; --test ok
106
    constant    QCR_QLAT    : integer := 8; --test ok
107
    constant    QCR_ICHA    : integer := 9;     --test ok
108
    constant    QCR_ICHB    : integer := 10;--test ok
109
    constant    QCR_IDXL    : integer := 11;--test ok
110
    constant    QCR_QEIE    : integer := 12;--test ok
111
    constant    QCR_BITS    : integer := 13;    --Number of bits used in QCR register
112
    signal      qcr_reg     : std_logic_vector(QCR_BITS-1 downto 0);     --QCR register
113
 
114
    ----------------------------------------------------------------------------
115
    --  Quadrature Status Register, QSR, offset 0x04
116
    --  Note:  User clears set bits by writing a 1 to the correspoding register
117
    --         bit.
118
    --  Bit 0:  Quadrature decoder error status, QERR, auto set, user cleared
119
    --      0 -> No error
120
    --      1 -> Illegal state transition detected
121
    --  Bit 1:  Counter Overflow, CTOV, auto set, user cleared
122
    --      0 -> No overflow detected
123
    --      1 -> Counter overflow from 0xFFFF to 0x0000
124
    --  Bit 2:  Counter Underflow, CTUN, auto set, user cleared
125
    --      0 -> No underflow detected
126
    --      1 -> Counter underflow from 0x0000 to 0xFFFF
127
    --  Bit 3:  Index event, INEV, auto set, user cleared
128
    --      0 -> Index event has not occurred
129
    --      1 -> Index event occured, interrupt requested if INIE set
130
    --  Bits 31:4   -> Reserved, will always read 0
131
    ----------------------------------------------------------------------------
132
    constant    QSR_QERR    : integer := 0; --test ok
133
    constant    QSR_CTOV    : integer := 1; --test ok
134
    constant    QSR_CTUN    : integer := 2; --test ok
135
    constant    QSR_INEV    : integer := 3; --test ok
136
    constant    QSR_BITS    : integer := 4;                     -- Num bits in QSR reg
137
    signal      qsr_reg     : std_logic_vector(QSR_BITS-1 downto 0);     --QSR register
138
 
139
    --Signals indicating status information for the QSR process
140
    signal      quad_error  : std_logic;
141
    signal      quad_ovflw  : std_logic;
142
    signal      quad_unflw  : std_logic;
143
    signal      quad_index  : std_logic;
144
 
145
    ----------------------------------------------------------------------------
146
    --  Quadrature Count Read / Write Register, QRW, offset 0x08
147
    --  Note:   The actual quadrature count value must be latched prior to
148
    --          reading from this register.  This may be triggered two ways:
149
    --          1) Writing a '1' to the QCR, bit 9 quadrature count latch
150
    --              (QLAT), -or-
151
    --          2) Asserting the external syncronous input quad_lat_i.
152
    --          Once either event occurs, the quadrature count value will be
153
    --          copied to the QCT register.
154
    --
155
    --          This register is also used to hold the pre-load count value.
156
    --          After writing to this register, the pre-load value is
157
    --          transferred to the quadrature count register by writing a '1'
158
    --          to bit location 6, quadrature pre-load count (QPLCT) of the
159
    --          quadrature control register (QCR) offset 0x00.
160
    ----------------------------------------------------------------------------
161
    signal      qrw_reg     : std_logic_vector(QUAD_COUNT_WIDTH-1 downto 0);
162
 
163
    --Actual quadrature counter register, extra bit for over/underflow detect
164
    signal      quad_count  : std_logic_vector(QUAD_COUNT_WIDTH downto 0);
165
 
166
    --Input buffers / filters for quadrature signals
167
    signal      quad_cha_buf: std_logic_vector(3 downto 0);
168
    signal      quad_chb_buf: std_logic_vector(3 downto 0);
169
    signal      quad_idx_buf: std_logic_vector(3 downto 0);
170
    signal      quad_cha_flt: std_logic;
171
    signal      quad_chb_flt: std_logic;
172
    signal      quad_idx_flt: std_logic;
173
    signal      quad_cha_j  : std_logic;
174
    signal      quad_cha_k  : std_logic;
175
    signal      quad_chb_j  : std_logic;
176
    signal      quad_chb_k  : std_logic;
177
    signal      quad_idx_j  : std_logic;
178
    signal      quad_idx_k  : std_logic;
179
 
180
 
181
    signal quad_lat_flt : std_logic;
182
        signal quad_lat_q       : std_logic;
183
        signal quad_lat_m       : std_logic;
184
 
185
    --Quadrature 4X decoding state machine signals
186
    signal      quad_st_new : std_logic_vector(1 downto 0);
187
    signal      quad_st_old : std_logic_vector(1 downto 0);
188
    signal      quad_trans  : std_logic;
189
    signal      quad_dir    : std_logic;
190
    -- State constants for 4x quad decoding, CH B is MSB, CH A is LSB
191
    constant    QUAD_STATE_0: std_logic_vector(1 downto 0) := "00";
192
    constant    QUAD_STATE_1: std_logic_vector(1 downto 0) := "01";
193
    constant    QUAD_STATE_2: std_logic_vector(1 downto 0) := "11";
194
    constant    QUAD_STATE_3: std_logic_vector(1 downto 0) := "10";
195
 
196
        --Wishbone internal signals
197
    signal  wb_request  : std_logic;
198
    signal  wb_write    : std_logic;
199
 
200
    --Signal for single clock delay of ack out
201
    signal ack_dly : std_logic;
202
 
203
    --Internal irq signal
204
    signal      quad_irq_int: std_logic;
205
 
206
 
207
 
208
    ----------------------------------------------------------------------------
209
    --Start of RTL
210
    ----------------------------------------------------------------------------
211
    begin
212
 
213
        quad_irq_o  <= quad_irq_int;
214
 
215
        -- Handle wishbone ack generation / internal write signals
216
        wb_request  <= wb_stb_i and wb_cyc_i;
217
        wb_write    <= wb_request and wb_we_i;
218
        wb_ack_o        <= ack_dly;
219
 
220
                -----------------------------------------------------------------------
221
                --      Process:        qck_dly_proc( wb_clk_i )
222
                --      Desc:           Generates the wishbone ack signal after a single clock
223
                --                              delay.  This insures that the internal read / write
224
                --                              operations have completed before acknowledging the 
225
                --                              master device.
226
                --      Signals:        wb_clk_i
227
                --                              ack_dly
228
                --                              wb_rst_i
229
                --      Notes:          
230
                -----------------------------------------------------------------------
231
        ack_dly_proc: process( wb_clk_i ) begin
232
            if rising_edge( wb_clk_i ) then
233
                if wb_rst_i = '1' then
234
                    ack_dly <= '0';
235
                elsif wb_request = '1' then
236
                    ack_dly <= '1';
237
                end if;
238
                if ack_dly = '1' then
239
                    ack_dly <= '0';
240
                end if;
241
            end if;
242
        end process ack_dly_proc;
243
 
244
        -----------------------------------------------------------------------
245
        --  Process:    qcr_reg_wr_proc( wb_clk_i )
246
        --  Desc:       Handles writing of the Quadrature Control Regsiter
247
        --              signal, address offset 0x00.
248
        --  Signals:    qcr_reg, quadrature control register
249
        --              wb_rst_i, external reset input
250
        --              wb_write, internal write enable signal
251
        --              wb_adr_i, wishbone address inputs
252
        --              wb_dat_i, wishbone data inputs
253
        --  Notes:      See comments above for more info re the qcr_reg
254
        -----------------------------------------------------------------------
255
        qcr_reg_wr_proc: process( wb_clk_i ) begin
256
            if rising_edge( wb_clk_i ) then
257
                if wb_rst_i = '1' then
258
                    qcr_reg <= (others => '0');
259
                elsif wb_write = '1' and wb_adr_i ="00" then
260
                    qcr_reg <= wb_dat_i(QCR_BITS-1 downto 0);
261
                end if;
262
                --See if PLCT asserted, should be auto-cleared
263
                if qcr_reg(QCR_PLCT) = '1' then
264
                    qcr_reg(QCR_PLCT) <= '0';
265
                end if;
266
                --See if QLAT asserted, should be auto-cleared
267
                if qcr_reg(QCR_QLAT) = '1' then
268
                    qcr_reg(QCR_QLAT) <= '0';
269
                end if;
270
            end if;
271
        end process qcr_reg_wr_proc;
272
 
273
        -----------------------------------------------------------------------
274
        --  Process:    qsr_reg_wr_proc( wb_clk_i )
275
        --  Desc:       Handles writing of the Quadrature Status Register, QSR, 
276
        --              offset 0x04.
277
        --  Signals:    quad_error, internal error status signal
278
        --              quad_ovflw, internal counter overflow signal
279
        --              quad_unflw, internal counter underflow signal
280
        --              quad_index, internl index event signal
281
        --              wb_rst_i, external reset input
282
        --              wb_write, internal write enable signal
283
        --              wb_adr_i, wishbone address inputs
284
        --              wb_dat_i, wishbone data inputs
285
        --  Notes:      All of these bits are set automatically based on the
286
        --              states of the internal signals.  Once set, the user must
287
        --              write a '1' to the corresponding bit location to clear it.
288
        --              See the comments above for more information.
289
        -----------------------------------------------------------------------
290
        qsr_reg_wr_proc: process( wb_clk_i ) begin
291
            if rising_edge( wb_clk_i ) then
292
                if wb_rst_i = '1' then
293
                    qsr_reg     <= (others => '0');
294
                else
295
                    --Set qsr_reg bit from signal quad_error
296
                    if quad_error = '1' and qcr_reg( QCR_ECNT) = '1' then
297
                        qsr_reg(QSR_QERR) <= '1';
298
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_QERR) = '1' and wb_dat_i(QSR_QERR) = '1' then
299
                        qsr_reg(QSR_QERR) <= '0';
300
                    end if;
301
                    --Set qsr_reg bit rom signal quad_ovflw
302
                    if quad_ovflw = '1'and qcr_reg( QCR_ECNT) = '1' then
303
                        qsr_reg(QSR_CTOV) <= '1';
304
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_CTOV) = '1' and wb_dat_i(QSR_CTOV) = '1' then
305
                        qsr_reg(QSR_CTOV) <= '0';
306
                    end if;
307
                    --Set qsr_reg bit from signal quad_unflw
308
                    if quad_unflw = '1' and qcr_reg( QCR_ECNT) = '1' then
309
                        qsr_reg(QSR_CTUN) <= '1';
310
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_CTUN) = '1' and wb_dat_i(QSR_CTUN) = '1' then
311
                        qsr_reg(QSR_CTUN) <= '0';
312
                    end if;
313
                    --Set qsr_reg bit from signal quad_index
314
                    if quad_index = '1' and qcr_reg( QCR_ECNT) = '1' then
315
                        qsr_reg(QSR_INEV) <= '1';
316
                    elsif wb_write = '1' and wb_adr_i = "01" and qsr_reg(QSR_INEV) = '1' and wb_dat_i(QSR_INEV) = '1' then
317
                        qsr_reg(QSR_INEV) <= '0';
318
                    end if;
319
                end if;
320
            end if;
321
        end process qsr_reg_wr_proc;
322
 
323
        -----------------------------------------------------------------------
324
        --  Process:    qrw_reg_wr_proc( wb_clk_i )
325
        --  Desc:       Handles writing to the Quadrature Read / Write Register,
326
        --              offset 0x08.
327
        --  Signals:    
328
        -----------------------------------------------------------------------
329
        qrw_reg_wr_proc: process( wb_clk_i ) begin
330
            if rising_edge( wb_clk_i ) then
331
                if wb_rst_i = '1' then
332
                    qrw_reg <= (others =>'0');
333
                elsif wb_write = '1' and wb_adr_i = "10" then
334
                    qrw_reg <= wb_dat_i;
335
                elsif qcr_reg(QCR_QLAT) = '1' or quad_lat_flt = '1' then
336
                    qrw_reg <= quad_count(QUAD_COUNT_WIDTH-1 downto 0);
337
                end if;
338
            end if;
339
        end process qrw_reg_wr_proc;
340
 
341
        -----------------------------------------------------------------------
342
        --  Process:    quad_regs_rd_proc( wb_clk_i )
343
        --  Desc:       Handles reading of all of the registers.
344
        --  Signals:
345
        -----------------------------------------------------------------------
346
        quad_regs_rd_proc: process( wb_rst_i, wb_adr_i, qcr_reg, qsr_reg, qrw_reg ) begin
347
                        case wb_adr_i is
348
                                when "00"   =>
349
                                        wb_dat_o(QCR_BITS-1 downto 0) <= qcr_reg;
350
                                        wb_dat_o(31 downto QCR_BITS) <= (others => '0');
351
                                when "01"   =>
352
                                        wb_dat_o(QSR_BITS-1 downto 0) <= qsr_reg;
353
                                        wb_dat_o(31 downto QSR_BITS) <= (others => '0');
354
                                when "10"   =>
355
                                        wb_dat_o(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
356
                                when others =>
357
                                        wb_dat_o    <= (others => '0' );
358
                        end case;
359
        end process quad_regs_rd_proc;
360
 
361
                -----------------------------------------------------------------------
362
                --      Process:        quad_lat_m_proc( wb_clk_i )
363
                --      Desc:           Rising edge detect for input quad_lat_i
364
                --
365
                -----------------------------------------------------------------------
366
                quad_lat_m_proc : process( quad_lat_i ) begin
367
                        if rising_edge( quad_lat_i ) then
368
                                if wb_rst_i = '1' then
369
                                        quad_lat_m <= '0';
370
                                else
371
                                        quad_lat_m <= '1';
372
                                end if;
373
 
374
                                if quad_lat_m = '1' then
375
                                        quad_lat_m      <= '0';
376
                                end if;
377
                        end if;
378
                end process;
379
 
380
                -----------------------------------------------------------------------
381
                --      Process:        quad_lat_proc
382
                --      Desc:           Metastable filter for quad_lat_i, sets internal signal
383
                --
384
                -----------------------------------------------------------------------
385
        quad_lat_proc: process( wb_clk_i) begin
386
 
387
            if rising_edge( wb_clk_i ) then
388
 
389
                if wb_rst_i = '1' then
390
 
391
                    quad_lat_flt    <= '0';
392
                                        quad_lat_q              <= '0';
393
 
394
                else
395
                                        if quad_lat_m = '1' then
396
                                                quad_lat_q      <= '1';
397
                                        end if;
398
                                        if quad_lat_q = '1' then
399
                                                quad_lat_q              <= '0';
400
                                                quad_lat_flt    <= '1';
401
                                        end if;
402
 
403
                    if quad_lat_flt = '1' then
404
                        quad_lat_flt <= '0';
405
                    end if;
406
                end if;
407
            end if;
408
        end process quad_lat_proc;
409
 
410
        --Combinatorial logic for JK flip flop filters
411
        quad_cha_j  <= quad_cha_buf(3) and quad_cha_buf(2) and quad_cha_buf(1);
412
        quad_cha_k  <= not( quad_cha_buf(3) or quad_cha_buf(2) or quad_cha_buf(1) );
413
        quad_chb_j  <= quad_chb_buf(3) and quad_chb_buf(2) and quad_chb_buf(1);
414
        quad_chb_k  <= not( quad_chb_buf(3) or quad_chb_buf(2) or quad_chb_buf(1) );
415
        quad_idx_j  <= quad_idx_buf(3) and quad_idx_buf(2) and quad_idx_buf(1);
416
        quad_idx_k  <= not( quad_idx_buf(3) or quad_idx_buf(2) or quad_idx_buf(1) );
417
 
418
                -----------------------------------------------------------------------
419
                --      Process:        quad_filt_proc
420
                --      Desc:           Digital filters for the quadrature inputs
421
                --
422
                -----------------------------------------------------------------------
423
        quad_filt_proc: process( wb_clk_i ) begin
424
            if rising_edge( wb_clk_i ) then
425
                if wb_rst_i = '1' then
426
                    quad_cha_buf    <= ( quad_cha_i & quad_cha_i & quad_cha_i & quad_cha_i );
427
                    quad_chb_buf    <= ( quad_chb_i & quad_chb_i & quad_chb_i & quad_chb_i );
428
                    quad_idx_buf    <= ( quad_idx_i & quad_idx_i & quad_idx_i & quad_idx_i );
429
                    quad_cha_flt    <= quad_cha_i;
430
                    quad_chb_flt    <= quad_chb_i;
431
                    quad_idx_flt    <= quad_idx_i;
432
                else
433
                    --sample inputs, place into shift registers
434
                    quad_cha_buf    <= ( quad_cha_buf(2) & quad_cha_buf(1) & quad_cha_buf(0) & quad_cha_i );
435
                    quad_chb_buf    <= ( quad_chb_buf(2) & quad_chb_buf(1) & quad_chb_buf(0) & quad_chb_i );
436
                    quad_idx_buf    <= ( quad_idx_buf(2) & quad_idx_buf(1) & quad_idx_buf(0) & quad_idx_i );
437
 
438
                    -- JK flip flop filters
439
                    if quad_cha_j = '1' then
440
                        quad_cha_flt    <= '1';
441
                    end if;
442
                    if quad_cha_k = '1' then
443
                        quad_cha_flt    <= '0';
444
                    end if;
445
                    if quad_chb_j = '1' then
446
                        quad_chb_flt    <= '1';
447
                    end if;
448
                    if quad_chb_k = '1' then
449
                        quad_chb_flt    <= '0';
450
                    end if;
451
                    if quad_idx_j = '1' then
452
                        quad_idx_flt <= '1';
453
                    end if;
454
                    if quad_idx_k = '1' then
455
                        quad_idx_flt <= '0';
456
                    end if;
457
                end if;
458
            end if;
459
        end process quad_filt_proc;
460
 
461
        -----------------------------------------------------------------------
462
                --      Process:        quad_state_proc
463
                --      Desc:           Reads filtered values quad_cha_flt, quad_chb_flt and 
464
                --                              increments / decrements count based on prior state
465
                --
466
                -----------------------------------------------------------------------
467
        quad_state_proc: process( wb_clk_i ) begin
468
            if rising_edge( wb_clk_i ) then
469
                if wb_rst_i = '1' then
470
                    quad_st_old     <= (quad_chb_i & quad_cha_i);
471
                    quad_st_new     <= (quad_chb_i & quad_cha_i);
472
                    quad_trans      <= '0';
473
                    quad_dir        <= '0';
474
                    quad_error      <= '0';
475
                else
476
                    quad_st_new <= (quad_chb_flt & quad_cha_flt);
477
                    quad_st_old <= quad_st_new;
478
                    --state machine
479
                    case quad_st_new is
480
                        when QUAD_STATE_0 =>    --"00"
481
                            case quad_st_old is
482
                                when QUAD_STATE_0 =>
483
                                    quad_trans      <= '0';
484
                                when QUAD_STATE_3 => --"10" -- dflt positive direction
485
                                    if qcr_reg(QCR_CTDR) = '1' then
486
                                        quad_trans  <= '1';
487
                                        quad_dir    <= '0';
488
                                    else
489
                                        quad_trans  <= '1';
490
                                        quad_dir    <= '1';
491
                                    end if;
492
                                when QUAD_STATE_1 => --"01" -- dflt negative direction
493
                                    if qcr_reg(QCR_CTDR) = '1' then
494
                                        quad_trans  <= '1';
495
                                        quad_dir    <= '1';
496
                                    else
497
                                        quad_trans  <= '1';
498
                                        quad_dir    <= '0';
499
                                    end if;
500
                                when others =>
501
                                    quad_error  <= '1';
502
                                    quad_trans  <= '0';
503
                            end case; --quad_st_old
504
 
505
                        when QUAD_STATE_1 =>    --"01"
506
                            case quad_st_old is
507
                                when QUAD_STATE_1 =>
508
                                    quad_trans      <= '0';
509
                                when QUAD_STATE_0 => --"10" -- dflt positive direction
510
                                    if qcr_reg(QCR_CTDR) = '1' then
511
                                        quad_trans  <= '1';
512
                                        quad_dir    <= '0';
513
                                    else
514
                                        quad_trans  <= '1';
515
                                        quad_dir    <= '1';
516
                                    end if;
517
                                when QUAD_STATE_2 => --"01" -- dflt negative direction
518
                                    if qcr_reg(QCR_CTDR) = '1' then
519
                                        quad_trans  <= '1';
520
                                        quad_dir    <= '1';
521
                                    else
522
                                        quad_trans  <= '1';
523
                                        quad_dir    <= '0';
524
                                    end if;
525
                                when others =>
526
                                    quad_error  <= '1';
527
                                    quad_trans  <= '0';
528
                            end case; --quad_st_old
529
 
530
                        when QUAD_STATE_2 =>    --"11"
531
                            case quad_st_old is
532
                                when QUAD_STATE_2 =>
533
                                    quad_trans      <= '0';
534
                                when QUAD_STATE_1 => --"10" -- dflt positive direction
535
                                    if qcr_reg(QCR_CTDR) = '1' then
536
                                        quad_trans  <= '1';
537
                                        quad_dir    <= '0';
538
                                    else
539
                                        quad_trans  <= '1';
540
                                        quad_dir    <= '1';
541
                                    end if;
542
                                when QUAD_STATE_3 => --"01" -- dflt negative direction
543
                                    if qcr_reg(QCR_CTDR) = '1' then
544
                                        quad_trans  <= '1';
545
                                        quad_dir    <= '1';
546
                                    else
547
                                        quad_trans  <= '1';
548
                                        quad_dir    <= '0';
549
                                    end if;
550
                                when others =>
551
                                    quad_error  <= '1';
552
                                    quad_trans  <= '0';
553
                            end case; --quad_st_old
554
 
555
                        when QUAD_STATE_3 =>    --"10"
556
                            case quad_st_old is
557
                                when QUAD_STATE_3 =>
558
                                    quad_trans      <= '0';
559
                                when QUAD_STATE_2 => --"10" -- dflt positive direction
560
                                    if qcr_reg(QCR_CTDR) = '1' then
561
                                        quad_trans  <= '1';
562
                                        quad_dir    <= '0';
563
                                    else
564
                                        quad_trans  <= '1';
565
                                        quad_dir    <= '1';
566
                                    end if;
567
                                when QUAD_STATE_0 => --"01" -- dflt negative direction
568
                                    if qcr_reg(QCR_CTDR) = '1' then
569
                                        quad_trans  <= '1';
570
                                        quad_dir    <= '1';
571
                                    else
572
                                        quad_trans  <= '1';
573
                                        quad_dir    <= '0';
574
                                    end if;
575
                                when others =>
576
                                    quad_error  <= '1';
577
                                    quad_trans  <= '0';
578
                            end case; --quad_st_old
579
 
580
                        when others =>
581
                            quad_error  <= '1';
582
                            quad_trans  <= '0';
583
                    end case; --quad_st_new
584
 
585
                    if quad_trans = '1' then
586
                        quad_trans  <= '0';
587
                    end if;
588
 
589
                    if quad_dir = '1' then
590
                        quad_dir    <= '0';
591
                    end if;
592
 
593
                    if quad_error = '1' then
594
                        quad_error  <= '0';
595
                    end if;
596
                end if;
597
            end if;
598
        end process quad_state_proc;
599
 
600
        -----------------------------------------------------------------------
601
        --  Process:    quad_count_proc( wb_clk_i )
602
        --  Desc:       Handles writing to the quad_count register.  
603
        --              First, pre-load events are handled; this may be triggered
604
        --              by writing a '1' to the qcr_reg QCR_PLCT bit location, or
605
        --              by an index_event assertion. Next, count events may be
606
        --              triggered by an assertion of the 'quad_trans' signal, 
607
        --              which causes the quad_count value to increment or
608
        --              decrement by one, based on the quad_dir signal.
609
        --              With each change on the count value, the counter is 
610
        --              checked for over/underflow.  If either is detected, the 
611
        --              corresponding signal is asserted for one clock cycle.
612
        --  Signals:    quad_count, QUAD_COUNT_WIDTH+1 bit length, holds the actual
613
        --                  4x quadrature counts.  The extra bit (i.e., as compared
614
        --                  to the user register qrw_reg) is for over / underflow
615
        --                  detection.  2's complement integer.
616
        --              quad_ovflw, single bit signal indicating an overflow event
617
        --                  has occurred; asserted one clock cycle then cleared.
618
        --              quad_unflw, single bit signal indicating that an underflow
619
        --                  event occured; asserted one clock cycle then cleared.
620
        --  Note:       See the comments for the qcr_reg register for more info
621
        --              regarding the index event control bits.
622
        -----------------------------------------------------------------------
623
        quad_count_proc: process( wb_clk_i ) begin
624
            if rising_edge( wb_clk_i ) then
625
                --Reset event
626
                if wb_rst_i = '1' then
627
                    quad_count  <= (others =>'0');
628
                    quad_ovflw  <= '0';
629
                    quad_unflw  <= '0';
630
                --Pre-load count event; either from qcr_reg or index event
631
                elsif qcr_reg(QCR_PLCT) = '1' or (quad_index = '1' and qcr_reg(QCR_INFC) = '1') then
632
                    quad_count(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
633
                    quad_count(QUAD_COUNT_WIDTH)            <= '0';
634
                else
635
                    if quad_trans = '1' and qcr_reg(QCR_ECNT) = '1' then
636
                        if quad_dir = '1' then
637
                            quad_count  <= quad_count + 1;
638
                        else
639
                            quad_count  <= quad_count - 1;
640
                        end if;
641
                    end if;
642
                    --check for over/under flow
643
                    if quad_count(QUAD_COUNT_WIDTH) = '1' then
644
                        --reset overflow bit
645
                        quad_count(QUAD_COUNT_WIDTH)    <= '0';
646
                        --Check MSB-1 to see if it is under or over flow
647
                        if quad_count(QUAD_COUNT_WIDTH-1) = '1' then
648
                            quad_unflw  <= '1';
649
                        else
650
                            quad_ovflw  <= '1';
651
                        end if;
652
                    end if;
653
                    --reset signals
654
                    if quad_ovflw = '1' then
655
                        quad_ovflw  <= '0';
656
                    end if;
657
                    if quad_unflw = '1' then
658
                        quad_unflw  <= '0';
659
                    end if;
660
                end if;
661
            end if;
662
        end process quad_count_proc;
663
 
664
        -----------------------------------------------------------------------
665
        --  Process:    quad_index_proc( wb_clk_i )
666
        --  Desc:       Controled the internal quad_index signal.  This signal is
667
        --              asserted to indicated the occurance of an index event.
668
        --
669
        -----------------------------------------------------------------------
670
        quad_index_proc : process( wb_clk_i ) begin
671
            if rising_edge( wb_clk_i ) then
672
                if wb_rst_i = '1' then
673
                    quad_index <= '0';
674
                elsif qcr_reg(QCR_INEN) = '1' and qcr_reg(QCR_ICHA) = quad_cha_flt
675
                    and qcr_reg(QCR_ICHB) = quad_chb_flt and qcr_reg(QCR_IDXL) = quad_idx_flt then
676
                    quad_index  <= '1';
677
                end if;
678
                --If quad_index is asserted, clear signal
679
                if quad_index = '1' then
680
                    quad_index <= '0';
681
                end if;
682
            end if;
683
        end process quad_index_proc;
684
 
685
                -----------------------------------------------------------------------
686
                --      Process:        quad_irq_proc
687
                --      Desc:
688
                --      
689
                -----------------------------------------------------------------------
690
        quad_irq_proc: process( wb_clk_i ) begin
691
            if rising_edge( wb_clk_i ) then
692
                if wb_rst_i = '1' then
693
                    quad_irq_int  <= '0';
694
                elsif       ( quad_error = '1' and qcr_reg(QCR_QEIE) = '1' )
695
                        or  ( quad_ovflw = '1' and qcr_reg(QCR_OVIE) = '1' )
696
                        or  ( quad_unflw = '1' and qcr_reg(QCR_UNIE) = '1' )
697
                        or  ( quad_index = '1' and qcr_reg(QCR_INIE) = '1' ) then
698
                    quad_irq_int <= '1';
699
                elsif quad_irq_int = '1' and
700
                    not(    ( qsr_reg(QSR_QERR) = '1' and qcr_reg(QCR_QEIE) = '1' )
701
                        or  ( qsr_reg(QSR_CTOV) = '1' and qcr_reg(QCR_OVIE) = '1' )
702
                        or  ( qsr_reg(QSR_CTUN) = '1' and qcr_reg(QCR_UNIE) = '1' )
703
                        or  ( qsr_reg(QSR_INEV) = '1' and qcr_reg(QCR_INIE) = '1' ) ) then
704
                    quad_irq_int <= '0';
705
                end if;
706
            end if;
707
        end process quad_irq_proc;
708
 
709
 
710
end architecture quad_decoder_rtl;

powered by: WebSVN 2.1.0

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