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

Subversion Repositories timerocd

[/] [timerocd/] [trunk/] [src/] [TimerOCD.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dewhisna
--------------------------------------------------------------------------------
2
--      File name : TimerOCD.vhd
3
--------------------------------------------------------------------------------
4
--      Copyright (C) 2015 Donna Whisnant/Dewtronics.
5
--      Contact: http://www.dewtronics.com/
6
--
7
--      This file may be used under the terms of the GNU Lesser General Public License
8
--      version 3.0 as published by the Free Software Foundation and appearing
9
--      in the files lgpl-3.0.txt/gpl-3.0.txt included in the packaging of this file.
10
--      Please review the following information to ensure the GNU Lesser General
11
--      Public License version 3.0 requirements will be met:
12
--      https://www.gnu.org/licenses/lgpl-3.0.html
13
--      Attribution requested, but not required.
14
--
15
--      Target Device: Xilinx Spartan-6 XC6SLX9-2-TQG144
16
--              Using Numato Mimas Spartan 6 FPGA Development Board
17
--              http://numato.com/mimas-spartan-6-fpga-development-board.html
18
--
19
--
20
--      Timer Output Compare Driver
21
--
22
--      This FPGA/CPLD code serves as a SPI Device and functions as a multichannel
23
--      Timer Output Compare driver for use in the DRSSTC (Dual Resonance Solid-State
24
--      Tesla Coil) MIDI Interrupter.
25
--
26
--      My original DRSSTC MIDI Interrupter used a series of Arduino ProMini boards,
27
--      each with a built-in limit of six timer output compare channels, to drive
28
--      the many note signal timing generation.  But instead of cascading six to
29
--      eight of those processors per interrupter output, this is an attempt to do
30
--      it all in a single chip.
31
--
32
--      The SPI Interface functions as a slave device with the following stream:
33
--              Master must send MSbit First:
34
--
35
--              Input (9 bytes per data message transfer or 1 byte per command message transfer):
36
--                      * 8-bit Command/Address Byte:
37
--                              C7..C0 :
38
--
39
--                              C7..C0 : Timer Address for Read and Write operations
40
--                                      C7 C6 C5 C4 C3 C2 C1 C0
41
--                                      -- -- -- -- -- -- -- --
42
--                                      |  |  |  |  |  |  |  |
43
--                                      |  |  +--+--+--+--+--+----- Timer Address 0-63 0x00-0x3F (000000-111111) (For Data Mode)
44
--                                      |  |                                            Commands (for Command Mode):
45
--                                      |  |                                                    000000 = Reset (performs power-on reset equivalent) on Write (Read has no effect)
46
--                                      |  |                                                    000001 = RESERVED
47
--                                      |  |                                                    000010 = Switch to Note/Power/PitchBend Run mode (initial default) on Write (Read has no effect)
48
--                                      |  |                                                    000011 = Switch to Timer On/Off Compare Value Run mode on Write (Read has no effect)
49
--                                      |  |                                                    000100 = Bank Select 0 (Notes 0-63) for future transfers on Write (Read has no effect)
50
--                                      |  |                                                    000101 = Bank Select 1 (Notes 64-127) for future transfers on Write (Read has no effect)
51
--                                      |  |                                                    000110 = Bank Select 2 (Notes 128-191) for future transfers on Write (Read has no effect)
52
--                                      |  |                                                    000111 = Bank Select 3 (Notes 192-255) for future transfers on Write (Read has no effect)
53
--                                      |  |                                                    001xxx = TBD/RESERVED
54
--                                      |  |                              Note: on 00xxxx Commands (above) and with Timer Address in the Data Mode the Concurrent
55
--                                      |  |                                     Read Nybble with the command send will be as follows:
56
--                                      |  |                                  0 m b b
57
--                                      |  |                                  - - - -
58
--                                      |  |                                  | | | |
59
--                                      |  |                                  | | +-+-- Currently Selected Bank
60
--                                      |  |                                  | |           00 = Bank 0
61
--                                      |  |                                  | |           01 = Bank 1
62
--                                      |  |                                  | |           10 = Bank 2
63
--                                      |  |                                  | |           11 = Bank 3
64
--                                      |  |                                  | |
65
--                                      |  |                                  | +------ RunMode : 0 = Note/Power/PitchBend, 1 = Timer On/Off Compare Values
66
--                                      |  |                                  |
67
--                                      |  |                                  +-------- Reserved for 001xxx command, TBD, will be sent as 0
68
--                                      |  |
69
--                                      |  |                                                    01xxxx = Read Push Button Switch 0-3 Status (Read Nybble is concurrent with sending command byte, Write has no effect)
70
--                                      |  |                                                    10xxxx = Read/Set LEDs 0-3 (Read Nybble is concurrent with sending command byte)
71
--                                      |  |                                                    11xxxx = Read/Set LEDs 4-7 (Read Nybble is concurrent with sending command byte)
72
--                                      |  |
73
--                                      |  +----------------------- Command/Data Select (0=Data, 1=Command)
74
--                                      |
75
--                                      +-------------------------- R/W Mode Select
76
--                                                                                                      0 = Write new value to TimerOCD and concurrently Read present value from TimerOCD
77
--                                                                                                      1 = Read present value from TimerOCD (Data received during read operation is ignored)
78
--
79
--              Note/Power/PitchBend Run Mode
80
--              -----------------------------
81
--                      * 16-Bit : 7-Bit Note/Key and 7-Bit Power/Velocity for Left Channel:  (Data Mode Only)
82
--                              0,N6..N0,0,P6..P0 :
83
--
84
--                                      0  N6 N5 N4 N3 N2 N1 N0
85
--                                      -- -- -- -- -- -- -- --
86
--                                      |  |  |  |  |  |  |  |
87
--                                      |  +--+--+--+--+--+--+-- Note/Key 0-127 0x00-0x7F (0000000-1111111) - Left Channel
88
--                                      |
89
--                                      +----------------------- Unused
90
--
91
--                                      0  P6 P5 P4 P3 P2 P1 P0
92
--                                      -- -- -- -- -- -- -- --
93
--                                      |  |  |  |  |  |  |  |
94
--                                      |  +--+--+--+--+--+--+-- Power/Velocity 0-127 0x00-0x7F (0000000-1111111) - Left Channel
95
--                                      |
96
--                                      +----------------------- Unused
97
--
98
--                      * 16-Bit : 14-Bit Pitch Bend for Left Channel:  (Data Mode Only)
99
--                              0,0,B13..B0 :
100
--
101
--                                      0  0  B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0
102
--                                      -- -- --- --- --- --- -- -- -- -- -- -- -- -- -- --
103
--                                      |  |  |   |   |   |   |  |  |  |  |  |  |  |  |  |
104
--                                      |  |  +---+---+---+---+--+--+--+--+--+--+--+--+--+-- Pitch Bend 0000/2000(NoBend)/3FFF - Left Channel
105
--                                      |  |
106
--                                      +--+------------------------------------------------ Unused
107
--
108
--
109
--                      * 16-Bit : 7-Bit Note/Key and 7-Bit Power/Velocity for Right Channel:  (Data Mode Only)
110
--                              0,N6..N0,0,P6..P0 :
111
--
112
--                                      0  N6 N5 N4 N3 N2 N1 N0
113
--                                      -- -- -- -- -- -- -- --
114
--                                      |  |  |  |  |  |  |  |
115
--                                      |  +--+--+--+--+--+--+-- Note/Key 0-127 0x00-0x7F (0000000-1111111) - Right Channel
116
--                                      |
117
--                                      +----------------------- Unused
118
--
119
--                                      0  P6 P5 P4 P3 P2 P1 P0
120
--                                      -- -- -- -- -- -- -- --
121
--                                      |  |  |  |  |  |  |  |
122
--                                      |  +--+--+--+--+--+--+-- Power/Velocity 0-127 0x00-0x7F (0000000-1111111) - Right Channel
123
--                                      |
124
--                                      +----------------------- Unused
125
--
126
--                      * 16-Bit : 14-Bit Pitch Bend for Right Channel:  (Data Mode Only)
127
--                              0,0,B13..B0 :
128
--
129
--                                      0  0  B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 B0
130
--                                      -- -- --- --- --- --- -- -- -- -- -- -- -- -- -- --
131
--                                      |  |  |   |   |   |   |  |  |  |  |  |  |  |  |  |
132
--                                      |  |  +---+---+---+---+--+--+--+--+--+--+--+--+--+-- Pitch Bend 0000/2000(NoBend)/3FFF - Right Channel
133
--                                      |  |
134
--                                      +--+------------------------------------------------ Unused
135
--
136
--
137
--                      >> A Note Value of 0 or Power Level of 0 is considered "OFF" and will disable the timer compare channel
138
--
139
--
140
--              Timer On/Off Value Run Mode
141
--              ---------------------------
142
--                      * 16-Bit : Timer ON Value for Left Channel:             (Data Mode Only)
143
--                              T15..T0 :
144
--
145
--                                      T15 T14 T13 T12 T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0
146
--                                      --- --- --- --- --- --- -- -- -- -- -- -- -- -- -- --
147
--                                      |   |   |   |   |   |   |  |  |  |  |  |  |  |  |  |
148
--                                      +---+---+---+---+---+---+--+--+--+--+--+--+--+--+--+--  Timer ON Value 0x0000 - 0xFFFF - Left Channel
149
--
150
--
151
--                      * 16-Bit : Timer OFF Value for Left Channel:    (Data Mode Only)
152
--                              T15..T0 :
153
--
154
--                                      T15 T14 T13 T12 T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0
155
--                                      --- --- --- --- --- --- -- -- -- -- -- -- -- -- -- --
156
--                                      |   |   |   |   |   |   |  |  |  |  |  |  |  |  |  |
157
--                                      +---+---+---+---+---+---+--+--+--+--+--+--+--+--+--+--  Timer OFF Value 0x0000 - 0xFFFF - Left Channel
158
--
159
--
160
--                      * 16-Bit : Timer ON Value for Right Channel:    (Data Mode Only)
161
--                              T15..T0 :
162
--
163
--                                      T15 T14 T13 T12 T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0
164
--                                      --- --- --- --- --- --- -- -- -- -- -- -- -- -- -- --
165
--                                      |   |   |   |   |   |   |  |  |  |  |  |  |  |  |  |
166
--                                      +---+---+---+---+---+---+--+--+--+--+--+--+--+--+--+--  Timer ON Value 0x0000 - 0xFFFF - Right Channel
167
--
168
--
169
--                      * 16-Bit : Timer OFF Value for Right Channel:   (Data Mode Only)
170
--                              T15..T0 :
171
--
172
--                                      T15 T14 T13 T12 T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0
173
--                                      --- --- --- --- --- --- -- -- -- -- -- -- -- -- -- --
174
--                                      |   |   |   |   |   |   |  |  |  |  |  |  |  |  |  |
175
--                                      +---+---+---+---+---+---+--+--+--+--+--+--+--+--+--+--  Timer OFF Value 0x0000 - 0xFFFF - Right Channel
176
--
177
--                      >> Writing either Timer On or Timer Off to 0 is considered "OFF" and will disable the timer compare channel
178
--
179
--
180
--------------------------------------------------------------------------------
181
--
182
--      tmrMemBlkLeftXX/tmrMemBlkRightXX Memory Mapping:
183
--
184
--              Each Configured as 256 x 16-bit True Dual-Port RAM Memory
185
--                      Port A = All Read/Write processing (xferdataproc only)
186
--                      Port B = All Read-Only processing (tmrupdproc only)
187
--              (Address is 8-bits)
188
--
189
--              A7 A6 A5 A4 A3 A2 A1 A0
190
--              -- -- -- -- -- -- -- --
191
--              |  |  |  |  |  |  |  |
192
--              |  |  +--+--+--+--+--+------------      Subtimer Index (0-63) 0x00-0x3F
193
--              |  |
194
--              +--+--+---------------------------      Entry Selection:
195
--                                                                                              00 = Note and Power Data (as sent/received to/from SPI) (Read/Written on SPI side) (Note in MSB, Power in LSB)
196
--                                                                                              01 = Pitch Bend Value (as sent/received to/from SPI) (Read/Written on SPI side) (right-justified)
197
--                                                                                              10 = Timer ON Compare Value (Calculated during SPI receive and written then, Read on signal generation timer processing)
198
--                                                                                              11 = Timer OFF Compare Value (Calculated during SPI receive and written then, Read on signal generation timer processing)
199
--
200
--              Block Mapping:
201
--              --------------
202
--                      tmrMemBlkLeft00/tmrMemBlkRight00 - Holds notes 0-63
203
--                      tmrMemBlkLeft01/tmrMemBlkRight01 - Holds notes 64-127
204
--                      tmrMemBlkLeft02/tmrMemBlkRight02 - Holds notes 128-191
205
--                      tmrMemBlkLeft03/tmrMemBlkRight03 - Holds notes 192-255
206
--
207
--
208
--      tmrCTMemBlkLeftXX/tmrCTMemBlkRightXX Memory Mapping:
209
--
210
--              Each Configured as 64 x 16-bit Simple Dual-Port RAM Memory
211
--                      Port A = All Read/Write processing (used exclusively by tmrupdproc)
212
--              (Address is 6-bits)
213
--
214
--              A5 A4 A3 A2 A1 A0
215
--              -- -- -- -- -- --
216
--              |  |  |  |  |  |
217
--              +--+--+--+--+--+------- Subtimer Index (0-63) 0x00-0x3F
218
--
219
--
220
--                      tmrCTMemBlkLeft00/tmrCTMemBlkRight00 - Holds notes 0-63
221
--                      tmrCTMemBlkLeft01/tmrCTMemBlkRight01 - Holds notes 64-127
222
--                      tmrCTMemBlkLeft02/tmrCTMemBlkRight02 - Holds notes 128-191
223
--                      tmrCTMemBlkLeft03/tmrCTMemBlkRight03 - Holds notes 192-255
224
--
225
--------------------------------------------------------------------------------
226
--
227
--      cmpFreqMemBlk Memory Mapping:
228
--
229
--              Timer Output Compare FREQ Values
230
--                      (OFF Values) = (FREQ Value) - (ON Value)
231
--
232
--              Configured as 128 x 16-bit Dual Port ROM Memory
233
--              (Address is 7-bits)
234
--
235
--              A6 A5 A4 A3 A2 A1 A0
236
--              -- -- -- -- -- -- --
237
--              |  |  |  |  |  |  |
238
--              +--+--+--+--+--+--+------       Note Value 0-127 (0 is reserved for output disabled compare value of 0)
239
--
240
--
241
--------------------------------------------------------------------------------
242
--
243
--      cmpOnMemBlk Memory Mapping:
244
--
245
--              Timer Output Compare ON Values
246
--
247
--              Configured as 16384 x 16-bit Dual Port ROM Memory
248
--              (Address is 14-bits)
249
--
250
--              A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
251
--              --- --- --- --- -- -- -- -- -- -- -- -- -- --
252
--              |   |   |   |   |  |  |  |  |  |  |  |  |  |
253
--              |   |   |   |   |  |  |  +--+--+--+--+--+--+------      Note Value 0-127 (0 is reserved for output disabled compare value of 0)
254
--              |   |   |   |   |  |  |
255
--              +---+---+---+---+--+--+---------------------------      Power Value 0-127 (0 is reserved for output disabled compare value of 0)
256
--
257
--------------------------------------------------------------------------------
258
--
259
-- For PitchBend calculations, the top-two bits (bit B13 and B12) of the PitchBend determine which note
260
--              compare stores are used in the PitchBend calculation as follows:
261
--
262
--                      B13 B12
263
--                      --- ---
264
--                      0   0           -- Use Note-2 and Note-1
265
--                      0   1           -- Use Note-1 and Note
266
--                      1   0           -- Use Note and Note+1
267
--                      1   1           -- Use Note+1 and Note+2
268
--
269
--              Notes in the extremes of the Note values (i.e. outside of the meaningful
270
--                      88 note piano range where our compares wrap anyway) are excluded from
271
--                      the pitch bend calculations
272
--
273
--
274
--------------------------------------------------------------------------------
275
 
276
library IEEE;
277
use IEEE.std_logic_1164.all;
278
use IEEE.std_logic_arith.all;
279
use IEEE.std_logic_unsigned.all;
280
 
281
library UNISIM;
282
use UNISIM.VCOMPONENTS.all;
283
 
284
--------------------------------------------------------------------------------
285
-- ENTITY DECLARATION
286
--------------------------------------------------------------------------------
287
entity TimerOCD is
288
        port (
289
                reset_n: in STD_LOGIC;                                  -- Master reset (Active Low)
290
                SPI_SS_n_in: in STD_LOGIC;                              -- SPI Slave Select In (Active Low)
291
                SPI_CLK_in: in STD_LOGIC;                               -- SPI Clock In
292
                SPI_MOSI_in: in STD_LOGIC;                              -- SPI Master Out, Slave In
293
                SPI_MISO: out STD_LOGIC := 'Z';                 -- SPI Master In, Slave Out
294
                FiberOut: out STD_LOGIC_VECTOR(1 downto 0) := (OTHERS => '0');            -- Fiber Optic Output Drive Left/Right Channels
295
                ---
296
                ---                                                                             Numato Mimas Spartan6 Module I/O Mapping:
297
                GCLK_in: in STD_LOGIC;                                  -- Master System Clock (GCLK)
298
                SW0: in STD_LOGIC;                                              -- Push-Button Switch 0
299
                SW1: in STD_LOGIC;                                              -- Push-Button Switch 1
300
                SW2: in STD_LOGIC;                                              -- Push-Button Switch 2
301
                SW3: in STD_LOGIC;                                              -- Push-Button Switch 3
302
                LED: out STD_LOGIC_VECTOR(7 downto 0)    -- LEDs 0 - 7
303
        );
304
end TimerOCD;
305
 
306
--------------------------------------------------------------------------------
307
-- ARCHITECTURE DECLARATION
308
--------------------------------------------------------------------------------
309
architecture TimerOCD_arch of TimerOCD is
310
        constant tmrclkPrescaler : INTEGER := 64;       -- Output Timer Clock Prescaler (Based on incoming GCLK frequency) tmrclk = 1.5625MHz
311
        constant LEDpostPrescaler : INTEGER := 6250000;         -- 1/8th of a second pulse per LED with 100MHz GCLK
312
 
313
        constant numTimers : INTEGER := 256;            -- Number of Timers Supported
314
        constant numTimerBits : INTEGER := 8;           -- Number of Timer Address Bits
315
        constant numSubTimers : INTEGER := 64;          -- Number of Timers per Block
316
        constant numSubTimerBits : INTEGER := 6;        -- Number of SubTimer Address Bits
317
        constant numTimerBlocks : INTEGER := 4;         -- Number of Timer Blocks
318
        constant numTimerBlockBits : INTEGER := 2;      -- Number of Timer Block Address Bits
319
        constant numCommandXferBits : INTEGER := 6;     -- Number of Bit of Address Xfer is Command Bits
320
        constant numXferBits : INTEGER := 64;           -- Number of bits transmitted/received during SPI data exchange
321
        constant numOutputs : INTEGER := 2;                     -- Number of Outputs Supported
322
        constant LEFT_OUT_NDX : INTEGER := 0;            -- Left Output Index for array processing
323
        constant RIGHT_OUT_NDX : INTEGER := 1;          -- Right Output Index for array processing
324
        constant EVEN_NDX : STD_LOGIC := '0';            -- tmrupdproc Even-Half Index for array processing
325
        constant ODD_NDX : STD_LOGIC := '1';            -- tmrupdproc Odd-Half Index for array processing
326
 
327
        constant adrNotePower : STD_LOGIC_VECTOR := "00";       -- Note/Power address slots
328
        constant adrPitchBend : STD_LOGIC_VECTOR := "01";       -- PitchBend address slots
329
        constant adrTimeON : STD_LOGIC_VECTOR := "10";          -- Timer ON Compare address slots
330
        constant adrTimeOFF : STD_LOGIC_VECTOR := "11";         -- Timer OFF Compare address slots
331
 
332
        constant LOWERNOTE_INDEX : INTEGER := 21;       -- First "Piano" note index (i.e. lowest one considered in pitchbend)
333
        constant UPPERNOTE_INDEX : INTEGER := 108;      -- Last "Piano" note index (i.e. highest one considered in pitchbend)
334
 
335
        -- Conversion Functions:
336
        function TmrBlock(constant nAddrBlock : STD_LOGIC_VECTOR(numTimerBlockBits-1 downto 0)) return INTEGER is
337
        begin
338
                return CONV_INTEGER(nAddrBlock);
339
        end function TmrBlock;
340
 
341
        function Tmr(constant nSubTimer : STD_LOGIC_VECTOR(numSubTimerBits-1 downto 0)) return INTEGER is
342
        begin
343
                return CONV_INTEGER(nSubTimer);
344
        end function Tmr;
345
 
346
        function Tmr(constant nOddEven : STD_LOGIC; constant nSubTimerUpd : STD_LOGIC_VECTOR(numSubTimerBits-2 downto 0)) return INTEGER is
347
        begin
348
                return CONV_INTEGER(nOddEven & nSubTimerUpd);
349
        end function Tmr;
350
 
351
        component BUFG is
352
                port (
353
                        I : in STD_ULOGIC;
354
                        O : out STD_ULOGIC
355
                );
356
        end component;
357
 
358
        component timer_memblk
359
                port (
360
                        clka : in STD_LOGIC;
361
                        ena : in STD_LOGIC;
362
                        wea : in STD_LOGIC_VECTOR(0 downto 0);
363
                        addra : in STD_LOGIC_VECTOR(7 downto 0);
364
                        dina : in STD_LOGIC_VECTOR(15 downto 0);
365
                        douta : out STD_LOGIC_VECTOR(15 downto 0);
366
                        ----
367
                        clkb : in STD_LOGIC;
368
                        enb : in STD_LOGIC;
369
                        web : in STD_LOGIC_VECTOR(0 downto 0);
370
                        addrb : in STD_LOGIC_VECTOR(7 downto 0);
371
                        dinb : in STD_LOGIC_VECTOR(15 downto 0);
372
                        doutb : out STD_LOGIC_VECTOR(15 downto 0)
373
                );
374
        end component;
375
 
376
        component timerCT_memblk
377
                port (
378
                        clka : in STD_LOGIC;
379
                        ena : in STD_LOGIC;
380
                        wea : in STD_LOGIC_VECTOR(0 downto 0);
381
                        addra : in STD_LOGIC_VECTOR(5 downto 0);
382
                        dina : in STD_LOGIC_VECTOR(15 downto 0);
383
                        clkb : in STD_LOGIC;
384
                        enb : in STD_LOGIC;
385
                        addrb : in STD_LOGIC_VECTOR(5 downto 0);
386
                        doutb : out STD_LOGIC_VECTOR(15 downto 0)
387
                );
388
        end component;
389
 
390
        component cmpFreqData_memblk
391
                port (
392
                        clka : in STD_LOGIC;
393
                        addra : in STD_LOGIC_VECTOR(6 downto 0);
394
                        douta : out STD_LOGIC_VECTOR(15 downto 0);
395
                        clkb : IN STD_LOGIC;
396
                        addrb : IN STD_LOGIC_VECTOR(6 downto 0);
397
                        doutb : OUT STD_LOGIC_VECTOR(15 downto 0)
398
                );
399
        end component;
400
 
401
        component cmpOnData_memblk
402
                port (
403
                        clka : in STD_LOGIC;
404
                        addra : in STD_LOGIC_VECTOR(13 downto 0);
405
                        douta : out STD_LOGIC_VECTOR(15 downto 0);
406
                        clkb : IN STD_LOGIC;
407
                        addrb : IN STD_LOGIC_VECTOR(13 downto 0);
408
                        doutb : OUT STD_LOGIC_VECTOR(15 downto 0)
409
                );
410
        end component;
411
 
412
        component InterpolateMultAdd
413
                port (
414
                        a : in STD_LOGIC_VECTOR(15 downto 0);
415
                        b : in STD_LOGIC_VECTOR(11 downto 0);
416
                        c : in STD_LOGIC_VECTOR(27 downto 0);
417
                        subtract : in STD_LOGIC;
418
                        p : out STD_LOGIC_VECTOR(27 downto 12);
419
                        pcout : out STD_LOGIC_VECTOR(47 downto 0)
420
                );
421
        end component;
422
 
423
        -- Master Timer:
424
        signal theTimer : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');
425
 
426
        -- The Outputs:
427
        --              This is the value of all output signals and their corresponding "pseudo" outputs forming the combined output.
428
        --              Each output will be generated by the 'OR' of all values for the numTimers associated with that output:
429
        type TOutputBlockArray is array (0 to numTimerBlocks-1) of STD_LOGIC_VECTOR(numSubTimers-1 downto 0);
430
        type TOutputArray is array (0 to numOutputs-1) of TOutputBlockArray;
431
        signal outputLevels : TOutputArray;                     -- Toggles during On/Off transitions
432
        signal outputEnables : TOutputArray;            -- Set to '1' when timer loaded with valid compares and is enabled
433
        signal outputEnablesNext : TOutputArray;        -- Next state for outputEnables, set in xferdataproc and transferred to outputEnables in tmrupdproc when a timer compare occurs
434
        signal outputForceLoad : TOutputArray;          -- Toggled in the xferdataproc when receiving a timer value causing the tmrupdproc to force-load that timer during the next timer processing cycle
435
        signal outputForceLoad_done : TOutputArray;     -- Toggled when the tmrupdproc processes an OutputForceLoad flag
436
 
437
        signal LEDenable : STD_LOGIC_VECTOR(7 downto 0);                 -- LED Outputs, set in RxData Processing
438
        signal LEDSet : STD_LOGIC;                                                                      -- Set to '1' whenever any LED value is written via SPI, used to switch from LEDpost to LEDenable mode
439
        signal LEDpost : STD_LOGIC_VECTOR(7 downto 0);                           -- LED POST drive
440
        signal LEDpostScalerCount : STD_LOGIC_VECTOR(31 downto 0);       -- POST timer clock/counter
441
        signal LEDpostPulse : STD_LOGIC;                                                        -- LED POST Pulse generated on scaler counter rollover, used to strobe LEDpost to the next state
442
 
443
        signal runMode : STD_LOGIC := '0';                       -- Run Mode : 0 = Note/Power/PitchBend,  1 = Timer On/Off (via SPI command)
444
        constant rmodeNote : STD_LOGIC := '0';
445
        constant rmodeTime : STD_LOGIC := '1';
446
 
447
        -- SPI Connection:
448
        signal SPI_SS_n : STD_LOGIC;                                                                                            -- Preprocessed SPI_SS
449
        signal SPI_CLK : STD_LOGIC;                                                                                                     -- Preprocessed SPI_CLK
450
        signal SPI_MOSI : STD_LOGIC;                                                                                            -- Preprocessed SPI_MOSI
451
        signal SPI_addr : STD_LOGIC_VECTOR(7 downto 0) := (OTHERS => '0');                        -- Current Address for SPI Read/Write
452
        signal SPI_addr_latch : STD_LOGIC := '0';                                                                        -- Address Latch enable from SPI
453
        signal SPI_rx_data : STD_LOGIC_VECTOR(numXferBits-1 downto 0);                           -- Receive Data for On/Off Timer Values by Note/Velocity
454
        signal SPI_tx_data : STD_LOGIC_VECTOR(numXferBits-1 downto 0);                           -- Transmit Data for On/Off Timer Values by Note/Velocity
455
        signal SPI_rrdy : STD_LOGIC := '0';                                                                                      -- Receive Data Ready (when new command is available)
456
        signal SPI_cmd_addr : STD_LOGIC_VECTOR(2 downto 0) := (OTHERS => '0');            -- Command Address portion of Current Address for SPI Read/Write
457
        signal SPI_txcmd_data : STD_LOGIC_VECTOR(3 downto 0);                                            -- Transmit Command Data generated on SPI_cmd_data_latch synchronization logic in response to command byte
458
        signal SPI_busy : STD_LOGIC;                                                                                            -- Cooked and Buffered (i.e. clock synchronized) SPI busy
459
 
460
        -- Timer MemBlk Connections:
461
        type TTimerAddrBus is array (0 to numTimerBlocks-1) of STD_LOGIC_VECTOR(7 downto 0);
462
        type TTimerDataBus is array (0 to numTimerBlocks-1) of STD_LOGIC_VECTOR(15 downto 0);
463
        -----------------------------------
464
        signal tmrMemBlkLeft_CLKXfer : STD_LOGIC;                                                                       -- PORT A : xferdataproc Processing (All Synchronous R/W)
465
        signal tmrMemBlkLeft_ENXfer : STD_LOGIC;
466
        signal tmrMemBlkLeft_WEXfer : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);
467
        signal tmrMemBlkLeft_ADDRXfer : STD_LOGIC_VECTOR(7 downto 0);
468
        signal tmrMemBlkLeft_DINXfer : TTimerDataBus;
469
        signal tmrMemBlkLeft_DOUTXfer : TTimerDataBus;
470
 
471
        signal tmrMemBlkLeft_CLKTmr : STD_LOGIC;                                                                        -- PORT B : tmrupdproc Processing (All Synchronous Read-Only)
472
        signal tmrMemBlkLeft_ENTmr : STD_LOGIC;
473
        signal tmrMemBlkLeft_ADDRTmr : TTimerAddrBus;
474
        signal tmrMemBlkLeft_DOUTTmr : TTimerDataBus;
475
 
476
        signal tmrMemBlkLeft_WE_GATE : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);              -- Port Write Enable Gate for xferdataproc processing
477
        -----------------------------------
478
        signal tmrMemBlkRight_CLKXfer : STD_LOGIC;                                                                      -- PORT A : xferdataproc Processing (All Synchronous R/W)
479
        signal tmrMemBlkRight_ENXfer : STD_LOGIC;
480
        signal tmrMemBlkRight_WEXfer : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);
481
        signal tmrMemBlkRight_ADDRXfer : STD_LOGIC_VECTOR(7 downto 0);
482
        signal tmrMemBlkRight_DINXfer : TTimerDataBus;
483
        signal tmrMemBlkRight_DOUTXfer : TTimerDataBus;
484
 
485
        signal tmrMemBlkRight_CLKTmr : STD_LOGIC;                                                                       -- PORT B : tmrupdproc Processing (All Synchronous Read-Only)
486
        signal tmrMemBlkRight_ENTmr : STD_LOGIC;
487
        signal tmrMemBlkRight_ADDRTmr : TTimerAddrBus;
488
        signal tmrMemBlkRight_DOUTTmr : TTimerDataBus;
489
 
490
        signal tmrMemBlkRight_WE_GATE : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);     -- Port Write Enable Gate for xferdataproc processing
491
 
492
        -- TimerCT MemBlk Connections:
493
        signal tmrCTMemBlkLeft_CLKA : STD_LOGIC;
494
        signal tmrCTMemBlkLeft_ENA : STD_LOGIC;
495
        signal tmrCTMemBlkLeft_WEA : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);
496
        signal tmrCTMemBlkLeft_ADDRA : STD_LOGIC_VECTOR(5 downto 0);
497
        signal tmrCTMemBlkLeft_DINA : TTimerDataBus;
498
        signal tmrCTMemBlkLeft_CLKB : STD_LOGIC;
499
        signal tmrCTMemBlkLeft_ENB : STD_LOGIC;
500
        signal tmrCTMemBlkLeft_ADDRB : STD_LOGIC_VECTOR(5 downto 0);
501
        signal tmrCTMemBlkLeft_DOUTB : TTimerDataBus;
502
 
503
        signal tmrMemBlkLeft_DOUTBpTimer : TTimerDataBus;                                                               -- tmrMemBlkLeft_DOUTTmr Data plus timer from concurrent logic to load into tmrCTMemBlkLeft to reduce memory setup time in tmrupdproc
504
        signal tmrMemBlkLeft_DINAmuxODD : TTimerDataBus;                                                                -- Multiplexer for tmrMemBlk Left ODD Data In Port A
505
        signal tmrMemBlkLeft_DINAmuxEVEN : TTimerDataBus;                                                               -- Multiplexer for tmrMemBlk Left EVEN Data In Port A
506
        signal tmrCTMemBlkLeft_eqTimer : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);    -- Comparison result of tmrCTMemBlkLeft == theTimer, used to reduce memory setup time in tmrupdproc
507
 
508
        signal tmrCTMemBlkLeft_WE_GATE : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);    -- Port Write Enable Gate for tmrupdproc processing
509
        -----------------------------------
510
        signal tmrCTMemBlkRight_CLKA : STD_LOGIC;
511
        signal tmrCTMemBlkRight_ENA : STD_LOGIC;
512
        signal tmrCTMemBlkRight_WEA : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);
513
        signal tmrCTMemBlkRight_ADDRA : STD_LOGIC_VECTOR(5 downto 0);
514
        signal tmrCTMemBlkRight_DINA : TTimerDataBus;
515
        signal tmrCTMemBlkRight_CLKB : STD_LOGIC;
516
        signal tmrCTMemBlkRight_ENB : STD_LOGIC;
517
        signal tmrCTMemBlkRight_ADDRB : STD_LOGIC_VECTOR(5 downto 0);
518
        signal tmrCTMemBlkRight_DOUTB : TTimerDataBus;
519
 
520
        signal tmrMemBlkRight_DOUTBpTimer : TTimerDataBus;                                                              -- tmrMemBlkRight_DOUTTmr Data plus timer from concurrent logic to load into tmrCTMemBlkRight to reduce memory setup time in tmrupdproc
521
        signal tmrMemBlkRight_DINAmuxODD : TTimerDataBus;                                                               -- Multiplexer for tmrMemBlk Right ODD Data In Port A
522
        signal tmrMemBlkRight_DINAmuxEVEN : TTimerDataBus;                                                              -- Multiplexer for tmrMemBlk Right EVEN Data In Port A
523
        signal tmrCTMemBlkRight_eqTimer : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);   -- Comparison result of tmrCTMemBlkRight == theTimer, used to reduce memory setup time in tmrupdproc
524
 
525
        signal tmrCTMemBlkRight_WE_GATE : STD_LOGIC_VECTOR(numTimerBlocks-1 downto 0);   -- Port Write Enable Gate for tmrupdproc processing
526
 
527
        -- Compare Freq MemBlk Connection:
528
        signal cmpFreqLeftMemBlk_CLK : STD_LOGIC;                                                                       -- Port A used by Left Channel
529
        signal cmpFreqLeftMemBlk_ADDR : STD_LOGIC_VECTOR(6 downto 0);
530
        signal cmpFreqLeftMemBlk_DOUT : STD_LOGIC_VECTOR(15 downto 0);
531
        ----
532
        signal cmpFreqRightMemBlk_CLK : STD_LOGIC;                                                                      -- Port B used by Right Channel
533
        signal cmpFreqRightMemBlk_ADDR : STD_LOGIC_VECTOR(6 downto 0);
534
        signal cmpFreqRightMemBlk_DOUT : STD_LOGIC_VECTOR(15 downto 0);
535
 
536
        -- Compare On MemBlk Connection:
537
        signal cmpOnLeftMemBlk_CLK : STD_LOGIC;                                                                         -- Port A used by Left Channel
538
        signal cmpOnLeftMemBlk_ADDR : STD_LOGIC_VECTOR(13 downto 0);
539
        signal cmpOnLeftMemBlk_DOUT : STD_LOGIC_VECTOR(15 downto 0);
540
        -----
541
        signal cmpOnRightMemBlk_CLK : STD_LOGIC;                                                                        -- Port B used by Right Channel
542
        signal cmpOnRightMemBlk_ADDR : STD_LOGIC_VECTOR(13 downto 0);
543
        signal cmpOnRightMemBlk_DOUT : STD_LOGIC_VECTOR(15 downto 0);
544
 
545
        -- Calculations:
546
        signal pitchBendLeftNoteAIndex : STD_LOGIC_VECTOR(6 downto 0) := (OTHERS => '0');                 -- Lower note index for pitch bend (see comments at top)
547
        signal pitchBendLeftNoteBIndex : STD_LOGIC_VECTOR(6 downto 0) := (OTHERS => '0');                 -- Upper note index for pitch bend (see comments at top)
548
        signal pitchBendLeftMagnitude : STD_LOGIC_VECTOR(11 downto 0) := (OTHERS => '0');                 -- Absolute value of magnitude of pitch bend => DSP InterpolateMultAdd(B)
549
 
550
        signal pitchBendLeftCalcFREQAlpha : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');             -- NoteA Compare FREQ Value (lower) => DSP InterpolateMultAdd(C and delta)
551
        signal pitchBendLeftCalcFREQAlphaLeft : STD_LOGIC_VECTOR(27 downto 0) := (OTHERS => '0'); -- Left Justified NoteA Compare FREQ Value (lower) => DSP InterpolateMultAdd(C), Needed for addition to be "Multiplied" by 2^12
552
        signal pitchBendLeftCalcFreqBeta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');              -- NoteB Compare FREQ Value (upper) => DSP InterpolateMultAdd(delta)
553
        signal pitchBendLeftCalcFREQDelta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');             -- Compare FREQ (NoteB-NoteA) => DSP InterpolateMultAdd(A)
554
        signal pitchBendLeftCalcFREQResult : STD_LOGIC_VECTOR(15 downto 0);                                                      -- Compare FREQ Output from DSP InterpolateMultAdd
555
 
556
        signal pitchBendLeftCalcONAlpha : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');                       -- NoteA Compare ON Value (lower) => DSP InterpolateMultAdd(C and delta)
557
        signal pitchBendLeftCalcONAlphaLeft : STD_LOGIC_VECTOR(27 downto 0) := (OTHERS => '0');           -- Left Justified NoteA Compare ON Value (lower) => DSP InterpolateMultAdd(C), Needed for addition to be "Multiplied" by 2^12
558
        signal pitchBendLeftCalcONBeta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');                        -- NoteB Compare ON Value (upper) => DSP InterpolateMultAdd(delta)
559
        signal pitchBendLeftCalcONDelta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');                       -- Compare ON (NoteB-NoteA) => DSP InterpolateMultAdd(A)
560
        signal pitchBendLeftCalcONResult : STD_LOGIC_VECTOR(15 downto 0);                                                        -- Compare ON Output from DSP InterpolateMultAdd
561
        -----
562
        signal pitchBendRightNoteAIndex : STD_LOGIC_VECTOR(6 downto 0) := (OTHERS => '0');                        -- Lower note index for pitch bend (see comments at top)
563
        signal pitchBendRightNoteBIndex : STD_LOGIC_VECTOR(6 downto 0) := (OTHERS => '0');                        -- Upper note index for pitch bend (see comments at top)
564
        signal pitchBendRightMagnitude : STD_LOGIC_VECTOR(11 downto 0) := (OTHERS => '0');                        -- Absolute value of magnitude of pitch bend => DSP InterpolateMultAdd(B)
565
 
566
        signal pitchBendRightCalcFREQAlpha : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');            -- NoteA Compare FREQ Value (lower) => DSP InterpolateMultAdd(C and delta)
567
        signal pitchBendRightCalcFREQAlphaLeft : STD_LOGIC_VECTOR(27 downto 0) := (OTHERS => '0');        -- Left Justified NoteA Compare FREQ Value (lower) => DSP InterpolateMultAdd(C), Needed for addition to be "Multiplied" by 2^12
568
        signal pitchBendRightCalcFREQBeta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');             -- NoteB Compare FREQ Value (upper) => DSP InterpolateMultAdd(delta)
569
        signal pitchBendRightCalcFREQDelta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');            -- Compare FREQ (NoteB-NoteA) => DSP InterpolateMultAdd(A)
570
        signal pitchBendRightCalcFREQResult : STD_LOGIC_VECTOR(15 downto 0);                                             -- Compare FREQ Output from DSP InterpolateMultAdd
571
 
572
        signal pitchBendRightCalcONAlpha : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');              -- NoteA Compare ON Value (lower) => DSP InterpolateMultAdd(C and delta)
573
        signal pitchBendRightCalcONAlphaLeft : STD_LOGIC_VECTOR(27 downto 0) := (OTHERS => '0');  -- Left Justified NoteA Compare ON Value (lower) => DSP InterpolateMultAdd(C), Needed for addition to be "Multiplied" by 2^12
574
        signal pitchBendRightCalcONBeta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');                       -- NoteB Compare ON Value (upper) => DSP InterpolateMultAdd(delta)
575
        signal pitchBendRightCalcONDelta : STD_LOGIC_VECTOR(15 downto 0) := (OTHERS => '0');              -- Compare ON (NoteB-NoteA) => DSP InterpolateMultAdd(A)
576
        signal pitchBendRightCalcONResult : STD_LOGIC_VECTOR(15 downto 0);                                                       -- Compare ON Output from DSP InterpolateMultAdd
577
 
578
        -- Clocks
579
        signal GCLK : STD_LOGIC;                                -- Buffered GCLK input
580
        signal tmrclk : STD_LOGIC;                              -- Buffered Timer Clock (derived from GCLK based on timer prescaler)
581
        signal sysclk : STD_LOGIC;                              -- Buffered System processing clock (equivalent to GCLK with a separate name reserved for possible scaling)
582
        signal xferdataclk : STD_LOGIC;                 -- Buffered System Clock divided from sysclk for xferdataproc to slow it down enough to meet timing constraints for calculations
583
 
584
        signal tmrclk_in: STD_LOGIC;                    -- Timer Clock In (Derived from GCLK by dividing by prescaler)
585
        signal tmrclk_prescaler_count: STD_LOGIC_VECTOR(15 downto 0);            -- tmrclk generation prescaler counter
586
 
587
        signal xferdataclk_in: STD_LOGIC := '0'; -- XferData Clock in (Derived from GCLK/sysclk by dividing it to meet timing constraints, currently a divide by 2)
588
 
589
        -- Misc
590
        signal syn_rrdy : STD_LOGIC;                    -- Synchronous SPI_rrdy signal
591
        signal syn_rrdy_armed : STD_LOGIC;              -- Arming for Synchronous SPI_rrdy signal generation.  Used to extend the trigger period to at least one sysclk cycle
592
        signal syn_rrdy_clr_n : STD_LOGIC;              -- Synchronous rrdy clear signal (asserted when data has been read)
593
        signal syn_rxdata_trigger_n : STD_LOGIC := '1';         -- Synchronous rxdata processing trigger (asserted to start the rxdata receive process)
594
        signal syn_rxdata_processing_n : STD_LOGIC := '1';      -- Synchronous rxdata processing signal (asserted when we are processing incoming data)
595
        signal syn_cmd_processing_n : STD_LOGIC := '1';         -- Synchronous cmd processing signal (asserted hwen rxdataproc is processing the incoming SPI command)
596
        constant nRxSB : integer := 3;                                          -- Number of RxData State Bits (used for conversions)
597
        signal syn_rxdata_state : STD_LOGIC_VECTOR(nRxSB-1 downto 0) := (OTHERS => '0');  -- Synchronous rxdata processing state-machine state (See xferdataproc for details)
598
        signal syn_rxdata : STD_LOGIC_VECTOR(numXferBits-1 downto 0);            -- Synchronized received buffer to hold the SPI_rx_data before transferring to our internal logic
599
 
600
        signal txdata_trigger_n : STD_LOGIC := '1';                     -- txdata trigger, set upon the rising edge of SPI_addr_latch, meaning latch address is in progress, reset when txdata_processing_n becomes active or SPI_SS_n deasserts indicating xfer was aborted
601
        signal txdata_processing_n : STD_LOGIC := '1';          -- txdata processing, set when xferdataproc starts transmitting data (to the buffer) to be sent out over SPI
602
        constant nTxSB : integer := 2;                                          -- Number of TxData State Bits (used for conversions)
603
        signal txdata_state : STD_LOGIC_VECTOR(nTxSB-1 downto 0) := (OTHERS => '0');      -- Synchronous txdata processing state-machine state (See xferdataproc for details)
604
 
605
        signal local_rst_n : STD_LOGIC := '1';  -- Local reset to process the reset command from SPI
606
        signal reset_trigger_n : STD_LOGIC := '1';                      -- Reset trigger -- initiated by either reset_n or local_reset_n during sysclk processing of rxproc
607
        signal reset_in_progress_n : STD_LOGIC := '1';          -- Reset currently is progress -- initiated by reset_trigger_n, cleared when reset is complete
608
 
609
        signal tmrproc_trigger_n : STD_LOGIC := '1';            -- Timer Process Trigger - Set by tmrclk event in timerproc, acted on by tmrupdproc
610
        signal tmrproc_processing_n : STD_LOGIC := '1';         -- Timer Process Processing - Set in tmrupdproc in response to tmrclk to indicate tmrupdproc state-machine is running
611
        signal tmrproc_tmrndxEVEN : STD_LOGIC_VECTOR(numSubTimerBits-2 downto 0) := (OTHERS => '0');              -- Even Timer Index during the Timer Update Processing loop
612
        signal tmrproc_tmrndxODD : STD_LOGIC_VECTOR(numSubTimerBits-2 downto 0) := (OTHERS => '0');                       -- Odd Timer Index during the Timer Update Processing loop
613
        signal tmrproc_tmrndxEVENLock : STD_LOGIC_VECTOR(numSubTimerBits-2 downto 0) := (OTHERS => '0');  -- Even Timer Index Locked during the Timer Output Update Processing loop
614
        signal tmrproc_tmrndxODDLock : STD_LOGIC_VECTOR(numSubTimerBits-2 downto 0) := (OTHERS => '0');           -- Odd Timer Index Locked during the Timer Output Update Processing loop
615
        constant nTSB : integer := 1;                                           -- Number of Timer State Bits (used for conversions)
616
        signal tmrproc_state : STD_LOGIC_VECTOR(nTSB-1 downto 0) := (OTHERS => '0');                              -- Timer Update Processing state machine (See tmrupdproc for details)
617
 
618
        signal spi_xfer_mode : STD_LOGIC := '0';                 -- Command/Data mode from SPI address (0=Data, 1=Command)
619
        signal syn_xfer_mode : STD_LOGIC := '0';                 -- Latched version of spi_xfer_mode.  Latched at start of rxdata/xferdata proc in case new address starts transferring while we are still processing
620
        constant xmodeData : STD_LOGIC := '0';
621
        constant xmodeCmd : STD_LOGIC := '1';
622
        signal addr_subtimer : STD_LOGIC_VECTOR(numSubTimerBits-1 downto 0) := (OTHERS => '0');                   -- SubTimer portion of Address received from SPI
623
        signal syn_addr_subtimer : STD_LOGIC_VECTOR(numSubTimerBits-1 downto 0) := (OTHERS => '0');               -- Latched version of addr_subtimer.  Latched at start of rxdata/xferdata proc in case new address starts transferring while we are still processing
624
        signal addr_block : STD_LOGIC_VECTOR(numTimerBlockBits-1 downto 0) := (OTHERS => '0');                    -- Block address sent via Block Select Command
625
        signal spi_command : STD_LOGIC_VECTOR(numCommandXferBits-1 downto 0) := (OTHERS => '0');          -- Command received from SPI (when xfer_mode = 1)
626
        signal spi_rw : STD_LOGIC := '0';                                        -- SPI R/W Mode (0=Write, 1=Read)
627
        signal syn_rw : STD_LOGIC := '0';                                        -- Latched version of spi_rw.  Latched at start of rxdata/xferdata proc in case new address starts transferring while we are still processing
628
 
629
        -- Receive Data clarity mapping (Populated with data from syn_rxdata to make the code read better rather than dealing with arbitrary bit numbers everywhere):
630
        signal synrx_leftNote : STD_LOGIC_VECTOR(6 downto 0);
631
        signal synrx_leftPower : STD_LOGIC_VECTOR(6 downto 0);
632
        signal synrx_leftPitchBend : STD_LOGIC_VECTOR(13 downto 0);
633
        signal synrx_rightNote : STD_LOGIC_VECTOR(6 downto 0);
634
        signal synrx_rightPower : STD_LOGIC_VECTOR(6 downto 0);
635
        signal synrx_rightPitchBend : STD_LOGIC_VECTOR(13 downto 0);
636
        signal synrx_leftTimerON : STD_LOGIC_VECTOR(15 downto 0);
637
        signal synrx_leftTimerOFF : STD_LOGIC_VECTOR(15 downto 0);
638
        signal synrx_rightTimerON : STD_LOGIC_VECTOR(15 downto 0);
639
        signal synrx_rightTimerOFF : STD_LOGIC_VECTOR(15 downto 0);
640
 
641
begin
642
        -- Handle Clock Buffering:
643
        bufg_tmrclk : BUFG
644
                port map (
645
                        O => tmrclk,
646
                        I => tmrclk_in
647
                );
648
--      tmrclk <= tmrclk_in;
649
 
650
        bufg_xferdataclk : BUFG
651
                port map (
652
                        O => xferdataclk,
653
                        I => xferdataclk_in
654
                );
655
--      xferdataclk <= xferdataclk_in;
656
 
657
        bufg_GCLK : BUFG
658
                port map (
659
                        O => GCLK,
660
                        I => GCLK_in
661
                );
662
--      GCLK <= GCLK_in;
663
 
664
        -- System Clock doesn't use prescaler:
665
        sysclk <= GCLK;
666
 
667
        -- Incoming SPI Entity:
668
        iSPI : entity work.spi_slave
669
        generic map (
670
                cpol => '0',
671
                cpha => '0',
672
                d_width => numXferBits
673
        )
674
        port map (
675
                sync_clk => sysclk,
676
                reset_n => reset_n,
677
                ss_n => SPI_SS_n,
678
                sclk => SPI_CLK,
679
                mosi => SPI_MOSI,
680
                miso => SPI_MISO,
681
                rrdy => SPI_rrdy,
682
                rx_data => SPI_rx_data,
683
                tx_load_data => SPI_tx_data,
684
                addr => SPI_addr,
685
                addr_latch => SPI_addr_latch,
686
                cmd_load_data => SPI_txcmd_data,
687
                busy => SPI_busy
688
        );
689
 
690
        -- Timer MemBlk Entities:
691
        tmrMemBlkLeft00 : timer_memblk
692
                port map (
693
                        clka => tmrMemBlkLeft_CLKXfer,
694
                        ena => tmrMemBlkLeft_ENXfer,
695
                        wea => tmrMemBlkLeft_WEXfer(0 downto 0),
696
                        addra => tmrMemBlkLeft_ADDRXfer,
697
                        dina => tmrMemBlkLeft_DINXfer(0),
698
                        douta => tmrMemBlkLeft_DOUTXfer(0),
699
                        ----
700
                        clkb => tmrMemBlkLeft_CLKTmr,
701
                        enb => tmrMemBlkLeft_ENTmr,
702
                        web => "0",
703
                        addrb => tmrMemBlkLeft_ADDRTmr(0),
704
                        dinb => "0000000000000000",
705
                        doutb => tmrMemBlkLeft_DOUTTmr(0)
706
                );
707
 
708
        tmrMemBlkRight00 : timer_memblk
709
                port map (
710
                        clka => tmrMemBlkRight_CLKXfer,
711
                        ena => tmrMemBlkRight_ENXfer,
712
                        wea => tmrMemBlkRight_WEXfer(0 downto 0),
713
                        addra => tmrMemBlkRight_ADDRXfer,
714
                        dina => tmrMemBlkRight_DINXfer(0),
715
                        douta => tmrMemBlkRight_DOUTXfer(0),
716
                        ----
717
                        clkb => tmrMemBlkRight_CLKTmr,
718
                        enb => tmrMemBlkRight_ENTmr,
719
                        web => "0",
720
                        addrb => tmrMemBlkRight_ADDRTmr(0),
721
                        dinb => "0000000000000000",
722
                        doutb => tmrMemBlkRight_DOUTTmr(0)
723
                );
724
 
725
        tmrMemBlkLeft01 : timer_memblk
726
                port map (
727
                        clka => tmrMemBlkLeft_CLKXfer,
728
                        ena => tmrMemBlkLeft_ENXfer,
729
                        wea => tmrMemBlkLeft_WEXfer(1 downto 1),
730
                        addra => tmrMemBlkLeft_ADDRXfer,
731
                        dina => tmrMemBlkLeft_DINXfer(1),
732
                        douta => tmrMemBlkLeft_DOUTXfer(1),
733
                        ----
734
                        clkb => tmrMemBlkLeft_CLKTmr,
735
                        enb => tmrMemBlkLeft_ENTmr,
736
                        web => "0",
737
                        addrb => tmrMemBlkLeft_ADDRTmr(1),
738
                        dinb => "0000000000000000",
739
                        doutb => tmrMemBlkLeft_DOUTTmr(1)
740
                );
741
 
742
        tmrMemBlkRight01 : timer_memblk
743
                port map (
744
                        clka => tmrMemBlkRight_CLKXfer,
745
                        ena => tmrMemBlkRight_ENXfer,
746
                        wea => tmrMemBlkRight_WEXfer(1 downto 1),
747
                        addra => tmrMemBlkRight_ADDRXfer,
748
                        dina => tmrMemBlkRight_DINXfer(1),
749
                        douta => tmrMemBlkRight_DOUTXfer(1),
750
                        ----
751
                        clkb => tmrMemBlkRight_CLKTmr,
752
                        enb => tmrMemBlkRight_ENTmr,
753
                        web => "0",
754
                        addrb => tmrMemBlkRight_ADDRTmr(1),
755
                        dinb => "0000000000000000",
756
                        doutb => tmrMemBlkRight_DOUTTmr(1)
757
                );
758
 
759
        tmrMemBlkLeft02 : timer_memblk
760
                port map (
761
                        clka => tmrMemBlkLeft_CLKXfer,
762
                        ena => tmrMemBlkLeft_ENXfer,
763
                        wea => tmrMemBlkLeft_WEXfer(2 downto 2),
764
                        addra => tmrMemBlkLeft_ADDRXfer,
765
                        dina => tmrMemBlkLeft_DINXfer(2),
766
                        douta => tmrMemBlkLeft_DOUTXfer(2),
767
                        ----
768
                        clkb => tmrMemBlkLeft_CLKTmr,
769
                        enb => tmrMemBlkLeft_ENTmr,
770
                        web => "0",
771
                        addrb => tmrMemBlkLeft_ADDRTmr(2),
772
                        dinb => "0000000000000000",
773
                        doutb => tmrMemBlkLeft_DOUTTmr(2)
774
                );
775
 
776
        tmrMemBlkRight02 : timer_memblk
777
                port map (
778
                        clka => tmrMemBlkRight_CLKXfer,
779
                        ena => tmrMemBlkRight_ENXfer,
780
                        wea => tmrMemBlkRight_WEXfer(2 downto 2),
781
                        addra => tmrMemBlkRight_ADDRXfer,
782
                        dina => tmrMemBlkRight_DINXfer(2),
783
                        douta => tmrMemBlkRight_DOUTXfer(2),
784
                        ----
785
                        clkb => tmrMemBlkRight_CLKTmr,
786
                        enb => tmrMemBlkRight_ENTmr,
787
                        web => "0",
788
                        addrb => tmrMemBlkRight_ADDRTmr(2),
789
                        dinb => "0000000000000000",
790
                        doutb => tmrMemBlkRight_DOUTTmr(2)
791
                );
792
 
793
        tmrMemBlkLeft03 : timer_memblk
794
                port map (
795
                        clka => tmrMemBlkLeft_CLKXfer,
796
                        ena => tmrMemBlkLeft_ENXfer,
797
                        wea => tmrMemBlkLeft_WEXfer(3 downto 3),
798
                        addra => tmrMemBlkLeft_ADDRXfer,
799
                        dina => tmrMemBlkLeft_DINXfer(3),
800
                        douta => tmrMemBlkLeft_DOUTXfer(3),
801
                        ----
802
                        clkb => tmrMemBlkLeft_CLKTmr,
803
                        enb => tmrMemBlkLeft_ENTmr,
804
                        web => "0",
805
                        addrb => tmrMemBlkLeft_ADDRTmr(3),
806
                        dinb => "0000000000000000",
807
                        doutb => tmrMemBlkLeft_DOUTTmr(3)
808
                );
809
 
810
        tmrMemBlkRight03 : timer_memblk
811
                port map (
812
                        clka => tmrMemBlkRight_CLKXfer,
813
                        ena => tmrMemBlkRight_ENXfer,
814
                        wea => tmrMemBlkRight_WEXfer(3 downto 3),
815
                        addra => tmrMemBlkRight_ADDRXfer,
816
                        dina => tmrMemBlkRight_DINXfer(3),
817
                        douta => tmrMemBlkRight_DOUTXfer(3),
818
                        ----
819
                        clkb => tmrMemBlkRight_CLKTmr,
820
                        enb => tmrMemBlkRight_ENTmr,
821
                        web => "0",
822
                        addrb => tmrMemBlkRight_ADDRTmr(3),
823
                        dinb => "0000000000000000",
824
                        doutb => tmrMemBlkRight_DOUTTmr(3)
825
                );
826
 
827
        -- TimerCT MemBlk Entities:
828
        tmrCTMemBlkLeft00 : timerCT_memblk
829
                port map (
830
                        clka => tmrCTMemBlkLeft_CLKA,
831
                        ena => tmrCTMemBlkLeft_ENA,
832
                        wea => tmrCTMemBlkLeft_WEA(0 downto 0),
833
                        addra => tmrCTMemBlkLeft_ADDRA,
834
                        dina => tmrCTMemBlkLeft_DINA(0),
835
                        clkb => tmrCTMemBlkLeft_CLKB,
836
                        enb => tmrCTMemBlkLeft_ENB,
837
                        addrb => tmrCTMemBlkLeft_ADDRB,
838
                        doutb => tmrCTMemBlkLeft_DOUTB(0)
839
                );
840
 
841
        tmrCTMemBlkRight00 : timerCT_memblk
842
                port map (
843
                        clka => tmrCTMemBlkRight_CLKA,
844
                        ena => tmrCTMemBlkRight_ENA,
845
                        wea => tmrCTMemBlkRight_WEA(0 downto 0),
846
                        addra => tmrCTMemBlkRight_ADDRA,
847
                        dina => tmrCTMemBlkRight_DINA(0),
848
                        clkb => tmrCTMemBlkRight_CLKB,
849
                        enb => tmrCTMemBlkRight_ENB,
850
                        addrb => tmrCTMemBlkRight_ADDRB,
851
                        doutb => tmrCTMemBlkRight_DOUTB(0)
852
                );
853
 
854
        tmrCTMemBlkLeft01 : timerCT_memblk
855
                port map (
856
                        clka => tmrCTMemBlkLeft_CLKA,
857
                        ena => tmrCTMemBlkLeft_ENA,
858
                        wea => tmrCTMemBlkLeft_WEA(1 downto 1),
859
                        addra => tmrCTMemBlkLeft_ADDRA,
860
                        dina => tmrCTMemBlkLeft_DINA(1),
861
                        clkb => tmrCTMemBlkLeft_CLKB,
862
                        enb => tmrCTMemBlkLeft_ENB,
863
                        addrb => tmrCTMemBlkLeft_ADDRB,
864
                        doutb => tmrCTMemBlkLeft_DOUTB(1)
865
                );
866
 
867
        tmrCTMemBlkRight01 : timerCT_memblk
868
                port map (
869
                        clka => tmrCTMemBlkRight_CLKA,
870
                        ena => tmrCTMemBlkRight_ENA,
871
                        wea => tmrCTMemBlkRight_WEA(1 downto 1),
872
                        addra => tmrCTMemBlkRight_ADDRA,
873
                        dina => tmrCTMemBlkRight_DINA(1),
874
                        clkb => tmrCTMemBlkRight_CLKB,
875
                        enb => tmrCTMemBlkRight_ENB,
876
                        addrb => tmrCTMemBlkRight_ADDRB,
877
                        doutb => tmrCTMemBlkRight_DOUTB(1)
878
                );
879
 
880
        tmrCTMemBlkLeft02 : timerCT_memblk
881
                port map (
882
                        clka => tmrCTMemBlkLeft_CLKA,
883
                        ena => tmrCTMemBlkLeft_ENA,
884
                        wea => tmrCTMemBlkLeft_WEA(2 downto 2),
885
                        addra => tmrCTMemBlkLeft_ADDRA,
886
                        dina => tmrCTMemBlkLeft_DINA(2),
887
                        clkb => tmrCTMemBlkLeft_CLKB,
888
                        enb => tmrCTMemBlkLeft_ENB,
889
                        addrb => tmrCTMemBlkLeft_ADDRB,
890
                        doutb => tmrCTMemBlkLeft_DOUTB(2)
891
                );
892
 
893
        tmrCTMemBlkRight02 : timerCT_memblk
894
                port map (
895
                        clka => tmrCTMemBlkRight_CLKA,
896
                        ena => tmrCTMemBlkRight_ENA,
897
                        wea => tmrCTMemBlkRight_WEA(2 downto 2),
898
                        addra => tmrCTMemBlkRight_ADDRA,
899
                        dina => tmrCTMemBlkRight_DINA(2),
900
                        clkb => tmrCTMemBlkRight_CLKB,
901
                        enb => tmrCTMemBlkRight_ENB,
902
                        addrb => tmrCTMemBlkRight_ADDRB,
903
                        doutb => tmrCTMemBlkRight_DOUTB(2)
904
                );
905
 
906
        tmrCTMemBlkLeft03 : timerCT_memblk
907
                port map (
908
                        clka => tmrCTMemBlkLeft_CLKA,
909
                        ena => tmrCTMemBlkLeft_ENA,
910
                        wea => tmrCTMemBlkLeft_WEA(3 downto 3),
911
                        addra => tmrCTMemBlkLeft_ADDRA,
912
                        dina => tmrCTMemBlkLeft_DINA(3),
913
                        clkb => tmrCTMemBlkLeft_CLKB,
914
                        enb => tmrCTMemBlkLeft_ENB,
915
                        addrb => tmrCTMemBlkLeft_ADDRB,
916
                        doutb => tmrCTMemBlkLeft_DOUTB(3)
917
                );
918
 
919
        tmrCTMemBlkRight03 : timerCT_memblk
920
                port map (
921
                        clka => tmrCTMemBlkRight_CLKA,
922
                        ena => tmrCTMemBlkRight_ENA,
923
                        wea => tmrCTMemBlkRight_WEA(3 downto 3),
924
                        addra => tmrCTMemBlkRight_ADDRA,
925
                        dina => tmrCTMemBlkRight_DINA(3),
926
                        clkb => tmrCTMemBlkRight_CLKB,
927
                        enb => tmrCTMemBlkRight_ENB,
928
                        addrb => tmrCTMemBlkRight_ADDRB,
929
                        doutb => tmrCTMemBlkRight_DOUTB(3)
930
                );
931
 
932
        -- Compare Off MemBlk Entity:
933
        cmpFreqMemBlk : cmpFreqData_memblk
934
                port map (
935
                        clka => cmpFreqLeftMemBlk_CLK,
936
                        addra => cmpFreqLeftMemBlk_ADDR,
937
                        douta => cmpFreqLeftMemBlk_DOUT,
938
                        -----
939
                        clkb => cmpFreqRightMemBlk_CLK,
940
                        addrb => cmpFreqRightMemBlk_ADDR,
941
                        doutb => cmpFreqRightMemBlk_DOUT
942
                );
943
 
944
        -- Compare On MemBlk Entity:
945
        cmpOnMemBlk : cmpOnData_memblk
946
                port map (
947
                        clka => cmpOnLeftMemBlk_CLK,
948
                        addra => cmpOnLeftMemBlk_ADDR,
949
                        douta => cmpOnLeftMemBlk_DOUT,
950
                        ----
951
                        clkb => cmpOnRightMemBlk_CLK,
952
                        addrb => cmpOnRightMemBlk_ADDR,
953
                        doutb => cmpOnRightMemBlk_DOUT
954
                );
955
 
956
        -- DSP Interpolate MultAdd Entities:
957
        pitchBendFREQLeftDSPInterpolate : InterpolateMultAdd
958
                port map (
959
                        a => pitchBendLeftCalcFREQDelta,
960
                        b => pitchBendLeftMagnitude,
961
                        c => pitchBendLeftCalcFREQAlphaLeft,
962
                        subtract => '0',
963
                        p => pitchBendLeftCalcFREQResult,
964
                        pcout => open
965
                );
966
 
967
        pitchBendONLeftDSPInterpolate : InterpolateMultAdd
968
                port map (
969
                        a => pitchBendLeftCalcONDelta,
970
                        b => pitchBendLeftMagnitude,
971
                        c => pitchBendLeftCalcONAlphaLeft,
972
                        subtract => '0',
973
                        p => pitchBendLeftCalcONResult,
974
                        pcout => open
975
                );
976
        -----------------------------------
977
        pitchBendFREQRightDSPInterpolate : InterpolateMultAdd
978
                port map (
979
                        a => pitchBendRightCalcFREQDelta,
980
                        b => pitchBendRightMagnitude,
981
                        c => pitchBendRightCalcFREQAlphaLeft,
982
                        subtract => '0',
983
                        p => pitchBendRightCalcFREQResult,
984
                        pcout => open
985
                );
986
 
987
        pitchBendONRightDSPInterpolate : InterpolateMultAdd
988
                port map (
989
                        a => pitchBendRightCalcONDelta,
990
                        b => pitchBendRightMagnitude,
991
                        c => pitchBendRightCalcONAlphaLeft,
992
                        subtract => '0',
993
                        p => pitchBendRightCalcONResult,
994
                        pcout => open
995
                );
996
 
997
        -- Create Left Justified version of the pitchBendCalcOFFAlpha and pitchBendCalcONAlpha values.
998
        --              This will effectively multiply them by 2^12 since they get added before the divide by
999
        --              2^12 instead of after it.  This eliminates having additional math steps and hopefully
1000
        --              the synthesizer and fitter will optimize it:
1001
        pitchBendLeftCalcFREQAlphaLeft <= pitchBendLeftCalcFREQAlpha & "000000000000";
1002
        pitchBendLeftCalcONAlphaLeft <= pitchBendLeftCalcONAlpha & "000000000000";
1003
        ----
1004
        pitchBendRightCalcFREQAlphaLeft <= pitchBendRightCalcFREQAlpha & "000000000000";
1005
        pitchBendRightCalcONAlphaLeft <= pitchBendRightCalcONAlpha & "000000000000";
1006
 
1007
        -- DSP Delta Input Calculation as concurrent logic:
1008
        pitchBendLeftCalcONDelta <= pitchBendLeftCalcONBeta - pitchBendLeftCalcONAlpha;                         --   On: Delta = Beta-Alpha
1009
        pitchBendLeftCalcFREQDelta <= pitchBendLeftCalcFREQBeta - pitchBendLeftCalcFREQAlpha;           -- Freq: Delta = Beta-Alpha
1010
 
1011
        pitchBendRightCalcONDelta <= pitchBendRightCalcONBeta - pitchBendRightCalcONAlpha;                      --   On: Delta = Beta-Alpha
1012
        pitchBendRightCalcFREQDelta <= pitchBendRightCalcFREQBeta - pitchBendRightCalcFREQAlpha;        -- Freq: Delta = Beta-Alpha
1013
 
1014
        -- Receive Data clarity mapping (Populated with data from syn_rxdata to make the code read better rather than dealing with arbitrary bit numbers everywhere):
1015
        synrx_leftNote <= syn_rxdata(62 downto 56);
1016
        synrx_leftPower <= syn_rxdata(54 downto 48);
1017
        synrx_leftPitchBend <= syn_rxdata(45 downto 32);
1018
        synrx_rightNote <= syn_rxdata(30 downto 24);
1019
        synrx_rightPower <= syn_rxdata(22 downto 16);
1020
        synrx_rightPitchBend <= syn_rxdata(13 downto 0);
1021
        synrx_leftTimerON <= syn_rxdata(63 downto 48);
1022
        synrx_leftTimerOFF <= syn_rxdata(47 downto 32);
1023
        synrx_rightTimerON <= syn_rxdata(31 downto 16);
1024
        synrx_rightTimerOFF <= syn_rxdata(15 downto 0);
1025
 
1026
        -- Memory Block Clocking/Enable Logic:
1027
        tmrMemBlkLeft_ENXfer <= reset_n;                                                                        -- Enable Port A (R/W) accesses during xferdataproc
1028
        tmrMemBlkLeft_CLKXfer <= xferdataclk;
1029
        tmrMemBlkLeft_WEXfer <= tmrMemBlkLeft_WE_GATE;
1030
        tmrMemBlkLeft_ENTmr <= reset_n;                                                                         -- Enable Port B (R) accesses during tmrproc
1031
        tmrMemBlkLeft_CLKTmr <= sysclk;
1032
        -----
1033
        tmrMemBlkRight_ENXfer <= reset_n;                                                                       -- Enable Port A (R/W) accesses during xferdataproc
1034
        tmrMemBlkRight_CLKXfer <= xferdataclk;
1035
        tmrMemBlkRight_WEXfer <= tmrMemBlkRight_WE_GATE;
1036
        tmrMemBlkRight_ENTmr <= reset_n;                                                                        -- Enable Port B (R) accesses during tmrproc
1037
        tmrMemBlkRight_CLKTmr <= sysclk;
1038
        -----
1039
        tmrCTMemBlkLeft_ENA <= reset_n and NOT tmrproc_processing_n;            -- Enable Port A (R/W) accesses during tmrproc
1040
        tmrCTMemBlkLeft_ENB <= reset_n and NOT tmrproc_processing_n;
1041
        tmrCTMemBlkLeft_CLKA <= sysclk;
1042
        tmrCTMemBlkLeft_CLKB <= sysclk;
1043
        tmrCTMemBlkLeft_WEA <= tmrCTMemBlkLeft_WE_GATE;
1044
        -----
1045
        tmrCTMemBlkRight_ENA <= reset_n and NOT tmrproc_processing_n;           -- Enable Port A (R/W) accesses during tmrproc
1046
        tmrCTMemBlkRight_ENB <= reset_n and NOT tmrproc_processing_n;
1047
        tmrCTMemBlkRight_CLKA <= sysclk;
1048
        tmrCTMemBlkRight_CLKB <= sysclk;
1049
        tmrCTMemBlkRight_WEA <= tmrCTMemBlkRight_WE_GATE;
1050
        -----
1051
        cmpOnLeftMemBlk_CLK <= sysclk;
1052
        cmpFreqLeftMemBlk_CLK <= sysclk;
1053
        cmpOnRightMemBlk_CLK <= sysclk;
1054
        cmpFreqRightMemBlk_CLK <= sysclk;
1055
 
1056
        -- tmrCTMemBlk Precalc code:
1057
        --      The tmrCTMemBlkPreCalc code asynchronously takes the Timer On/Off
1058
        --              counts being outputted on the tmrMemBlk and adds it to theTimer
1059
        --              to find the time of the next event, making it available to the
1060
        --              tmrCTMemBlkxxx_DOUTBpTimer register which can be loaded if a
1061
        --              compare event for the current timer cycle is detected.  It also
1062
        --              compares the current tmrCTMemBlk memory output (i.e. the last
1063
        --              event calculation) against theTimer to see if this cycle is an
1064
        --              occurrence match.  Done asynchronously from the tmrupdproc
1065
        --              state-machine logic in order to meet setup timing conditions
1066
        --              for the RAM, etc, with the propagation delay of the logic:
1067
        tmrCTMemBlkPreCalc:for i in 0 to numTimerBlocks-1 generate
1068
        begin
1069
                tmrMemBlkLeft_DOUTBpTimer(i) <= tmrMemBlkLeft_DOUTTmr(i) + theTimer;
1070
                with (tmrCTMemBlkLeft_DOUTB(i) = theTimer) select
1071
                        tmrCTMemBlkLeft_eqTimer(i) <= '1' when true, '0' when OTHERS;
1072
                tmrMemBlkRight_DOUTBpTimer(i) <= tmrMemBlkRight_DOUTTmr(i) + theTimer;
1073
                with (tmrCTMemBlkRight_DOUTB(i) = theTimer) select
1074
                        tmrCTMemBlkRight_eqTimer(i) <= '1' when true, '0' when OTHERS;
1075
        end generate tmrCTMemBlkPreCalc;
1076
 
1077
        -- tmrCTMemBlk Data Multiplexer code:
1078
        --      The Odd/Even multiplexer code blocks asynchronously determine if the
1079
        --              particular timer needs to get updated on the current timer cycle
1080
        --              or not and loads either the next computed event time or the current
1081
        --              event time accordingly.
1082
        --      The final multiplexer code stage selects either the Odd or the Even
1083
        --              data to send to the memory data input depending on which half-cycle
1084
        --              of the state-machine logic we're on, making it available prior to
1085
        --              the rising-edge of the clock which will clock it into the RAM:
1086
        tmrCTMemBlkMuxODD:for i in 0 to numTimerBlocks-1 generate
1087
        begin
1088
                with (((outputEnables(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) = '0') AND
1089
                           (outputForceLoad(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) /= outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)))) OR
1090
                           (tmrCTMemBlkLeft_eqTimer(i) = '1')) select
1091
                        tmrMemBlkLeft_DINAmuxODD(i) <= tmrMemBlkLeft_DOUTBpTimer(i) when true, tmrCTMemBlkLeft_DOUTB(i) when OTHERS;
1092
                with (((outputEnables(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) = '0') AND
1093
                           (outputForceLoad(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) /= outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)))) OR
1094
                           (tmrCTMemBlkRight_eqTimer(i) = '1')) select
1095
                        tmrMemBlkRight_DINAmuxODD(i) <= tmrMemBlkRight_DOUTBpTimer(i) when true, tmrCTMemBlkRight_DOUTB(i) when OTHERS;
1096
        end generate tmrCTMemBlkMuxODD;
1097
 
1098
        tmrCTMemBlkMuxEVEN:for i in 0 to numTimerBlocks-1 generate
1099
        begin
1100
                with (((outputEnables(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) = '0') AND
1101
                           (outputForceLoad(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) /= outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)))) OR
1102
                           (tmrCTMemBlkLeft_eqTimer(i) = '1')) select
1103
                        tmrMemBlkLeft_DINAmuxEVEN(i) <= tmrMemBlkLeft_DOUTBpTimer(i) when true, tmrCTMemBlkLeft_DOUTB(i) when OTHERS;
1104
                with (((outputEnables(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) = '0') AND
1105
                           (outputForceLoad(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) /= outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)))) OR
1106
                           (tmrCTMemBlkRight_eqTimer(i) = '1')) select
1107
                        tmrMemBlkRight_DINAmuxEVEN(i) <= tmrMemBlkRight_DOUTBpTimer(i) when true, tmrCTMemBlkRight_DOUTB(i) when OTHERS;
1108
        end generate tmrCTMemBlkMuxEVEN;
1109
 
1110
        tmrCTMemBlkMux:for i in 0 to numTimerBlocks-1 generate
1111
        begin
1112
                -- NOTE: tmrproc_state values here are backwards from tmrupdproc state-machine because these
1113
                --              calculations are AFTER the state transistion has happened and the rest of the state
1114
                --              processing is occurring:
1115
                with (CONV_INTEGER(tmrproc_state)) select
1116
                        tmrCTMemBlkLeft_DINA(i) <= tmrMemBlkLeft_DINAmuxODD(i) when 1, tmrMemBlkLeft_DINAmuxEVEN(i) when OTHERS;
1117
                with (CONV_INTEGER(tmrproc_state)) select
1118
                        tmrCTMemBlkRight_DINA(i) <= tmrMemBlkRight_DINAmuxODD(i) when 1, tmrMemBlkRight_DINAmuxEVEN(i) when OTHERS;
1119
        end generate tmrCTMemBlkMux;
1120
 
1121
        -- LED Outputs
1122
        with (LEDSet) select
1123
                LED <= LEDenable when '1', LEDpost when OTHERS;
1124
 
1125
-- --------------------------------------------------------------------
1126
-- xferdataclkproc:
1127
--      This process handles prescaling of xferdataclk (simple divide by two):
1128
-- --------------------------------------------------------------------
1129
xferdataclkproc:process(sysclk)
1130
begin
1131
        if (rising_edge(sysclk)) then
1132
                xferdataclk_in <= not xferdataclk_in;
1133
        end if;
1134
end process xferdataclkproc;
1135
-- --------------------------------------------------------------------
1136
 
1137
 
1138
-- These provide a hook into the incoming SPI signals for an easy connection
1139
--              point for testing and experimenting without code changes to alter
1140
--              their naming:
1141
SPI_CLK <= SPI_CLK_in;
1142
SPI_MOSI <= SPI_MOSI_in;
1143
SPI_SS_n <= SPI_SS_n_in;
1144
 
1145
 
1146
-- --------------------------------------------------------------------
1147
-- tmrclkproc:
1148
--      This process handles prescaling of tmrclk
1149
--      Counts and toggles tmrclk when prescaler value is reached:
1150
-- --------------------------------------------------------------------
1151
tmrclkproc:process(GCLK, reset_n)
1152
begin
1153
        if (reset_n = '0') then
1154
                tmrclk_prescaler_count <= (OTHERS => '0');
1155
                tmrclk_in <= '0';
1156
        elsif (rising_edge(GCLK)) then
1157
                tmrclk_prescaler_count <= tmrclk_prescaler_count + 1;
1158
                if (CONV_INTEGER(tmrclk_prescaler_count) = (tmrclkPrescaler/2-1)) then
1159
                        tmrclk_prescaler_count <= (OTHERS => '0');
1160
                        tmrclk_in <= not tmrclk_in;
1161
                end if;
1162
        end if;
1163
end process tmrclkproc;
1164
-- --------------------------------------------------------------------
1165
 
1166
 
1167
-- --------------------------------------------------------------------
1168
-- LEDpostclkproc:
1169
--      This process handles prescaling of the LEDpostPulse used to
1170
--              drive the LEDpost output pattern:
1171
-- --------------------------------------------------------------------
1172
LEDpostclkproc:process(GCLK, reset_n)
1173
begin
1174
        if (reset_n = '0') then
1175
                LEDpostScalerCount <= (OTHERS => '0');
1176
                LEDpostPulse <= '0';
1177
        elsif (rising_edge(GCLK)) then
1178
                LEDpostScalerCount <= LEDpostScalerCount + 1;
1179
                if (CONV_INTEGER(LEDpostScalerCount) = LEDpostPrescaler) then
1180
                        LEDpostScalerCount <= (OTHERS => '0');
1181
                        LEDpostPulse <= not LEDpostPulse;
1182
                end if;
1183
        end if;
1184
end process LEDpostclkproc;
1185
-- --------------------------------------------------------------------
1186
 
1187
 
1188
-- --------------------------------------------------------------------
1189
-- LEDpostproc:
1190
--      This process handles outputting the LEDpost pattern:
1191
-- --------------------------------------------------------------------
1192
LEDpostproc:process(LEDpostPulse, reset_n)
1193
begin
1194
        if (reset_n = '0') then
1195
                LEDpost <= (OTHERS => '0');
1196
        elsif (rising_edge(LEDpostPulse)) then
1197
                LEDpost <= LEDpost(LEDpost'HIGH-1 downto LEDpost'LOW) & not LEDpost(LEDpost'HIGH);
1198
        end if;
1199
end process LEDpostproc;
1200
-- --------------------------------------------------------------------
1201
 
1202
 
1203
-- --------------------------------------------------------------------
1204
-- txcmddata:
1205
--      This combinatorial logic handles Command Nybble transfer data:
1206
-- --------------------------------------------------------------------
1207
with SPI_cmd_addr select SPI_txcmd_data <=
1208
        "0" & runMode & addr_block when "100" | "000" | "001" | "010" | "011",
1209
                -- Send the Bank/Mode data on either Command Mode 00 or Data Xfer
1210
                -- Set SPI_txcmd_data to:
1211
                --      0 m b b
1212
                --      - - - -
1213
                --      | | | |
1214
                --      | | +-+-- Currently Selected Bank
1215
                --      | |
1216
                --      | +------ RunMode : 0 = Note/Power/PitchBend, 1 = Timer On/Off Compare Values
1217
                --      |
1218
                --      +-------- Reserved for 001xxx command, TBD, will be sent as 0
1219
 
1220
        SW3 & SW2 & SW1 & SW0 when "101",
1221
                -- Switches are on Command Mode 01
1222
                -- Set SPI_txcmd_data to Switch Status
1223
 
1224
        LEDenable(3 downto 0) when "110",
1225
                -- Low LEDs are on Command Mode 10
1226
                -- Set SPI_txcmd_data to LEDs 0-3
1227
 
1228
        LEDenable(7 downto 4) when "111",
1229
                -- High LEDs are on Command Mode 11
1230
                -- Set SPI_txcmd_data to LEDs 4-7
1231
 
1232
        "0000" when OTHERS;             -- Not needed except to keep ghdl compiler happy
1233
-- --------------------------------------------------------------------
1234
 
1235
 
1236
-- --------------------------------------------------------------------
1237
-- txdataproc:
1238
--      This process handles the coordinating of sending our transmit data
1239
--              and latching of the transfer address logic for ALL modes.
1240
--              It triggers txdata_trigger_n on the rising edge of SPI_addr_latch.
1241
--              It resets when txdata_processing_n has begun or SPI_SS_n goes
1242
--              high indicating the transfer was aborted.
1243
-- --------------------------------------------------------------------
1244
txdataproc:process(reset_n, txdata_processing_n, SPI_addr_latch)
1245
begin
1246
        if ((reset_n = '0') OR (txdata_processing_n = '0')) then
1247
                txdata_trigger_n <= '1';
1248
        elsif (rising_edge(SPI_addr_latch)) then
1249
                txdata_trigger_n <= '0';
1250
        end if;
1251
end process txdataproc;
1252
-- --------------------------------------------------------------------
1253
 
1254
 
1255
-- Handle SPI Addr Processing, mapping to our local signals:
1256
spi_rw <= SPI_addr(7);
1257
spi_xfer_mode <= SPI_addr(6);
1258
addr_subtimer <= SPI_addr(numSubTimerBits-1 downto 0);
1259
spi_command <= SPI_addr(numCommandXferBits-1 downto 0);
1260
SPI_cmd_addr <= SPI_addr(6 downto 4);
1261
 
1262
 
1263
-- --------------------------------------------------------------------
1264
-- rrdysynproc:
1265
--      This process synchronizes the rrdy signal:
1266
-- --------------------------------------------------------------------
1267
rrdysynproc:process(reset_n, syn_rrdy_clr_n, sysclk)
1268
begin
1269
        if ((reset_n = '0') or (syn_rrdy_clr_n = '0')) then
1270
                syn_rrdy <= '0';
1271
                syn_rrdy_armed <= '0';
1272
        elsif (rising_edge(sysclk)) then
1273
                -- Capture the data as soon as it's available and arm the trigger to get ready for processing it:
1274
                if ((syn_rrdy_armed = '0') AND (SPI_rrdy = '1')) then
1275
                        syn_rrdy_armed <= '1';
1276
                        syn_rw <= spi_rw;
1277
                        syn_xfer_mode <= spi_xfer_mode;
1278
                        syn_rxdata <= SPI_rx_data;
1279
                        syn_addr_subtimer <= addr_subtimer;
1280
                elsif ((syn_rrdy_armed = '1') AND (txdata_processing_n = '1') AND (txdata_trigger_n = '1') AND (SPI_busy = '0')) then
1281
                        -- Keep it armed, but not running, until we have a rising sysclk after finishing any current txdata processing
1282
                        --              and the SPI is finished:
1283
                        syn_rrdy <= '1';
1284
                end if;
1285
        end if;
1286
end process rrdysynproc;
1287
-- --------------------------------------------------------------------
1288
 
1289
 
1290
-- --------------------------------------------------------------------
1291
-- rxproc:
1292
--      This process handles initial synchronous receive from SPI.  It
1293
--              processes Command Bytes received and triggers rxdata and/or
1294
--              the reset state-machines of xferdataproc as appropriate:
1295
-- --------------------------------------------------------------------
1296
rxproc:process(sysclk, reset_n, local_rst_n)
1297
begin
1298
        if ((reset_n = '0') OR
1299
                (local_rst_n = '0')) then
1300
                syn_rrdy_clr_n <= '1';
1301
                syn_cmd_processing_n <= '1';
1302
                syn_rxdata_trigger_n <= '1';
1303
                runMode <= rmodeNote;
1304
                addr_block <= (OTHERS => '0');
1305
                LEDenable <= (OTHERS => '0');
1306
                LEDSet <= '0';
1307
                local_rst_n <= '1';
1308
                reset_trigger_n <= '0';                                  -- Trigger a reset process
1309
        elsif (falling_edge(sysclk)) then
1310
                if (reset_trigger_n = '0') then
1311
                        if (reset_in_progress_n = '0') then
1312
                                reset_trigger_n <= '1';                 -- Release trigger once xferdataproc starts reset
1313
                        end if;
1314
                elsif (reset_in_progress_n = '1') then  -- Don't process incoming data while xferdataproc is resetting
1315
                        if ((syn_rrdy = '1') AND (syn_cmd_processing_n = '1')) then
1316
                                if (syn_xfer_mode = xmodeCmd) then
1317
                                        if (syn_rw = '0') then
1318
                                                -- Start Command receive:xferdataproc
1319
                                                case spi_command(5 downto 4) is
1320
                                                        when "00" =>            -- Control Logic
1321
                                                                case spi_command(3 downto 0) is
1322
                                                                        when "0000" =>
1323
                                                                                local_rst_n <= '0';
1324
                                                                        when "0010" =>
1325
                                                                                runMode <= rmodeNote;
1326
                                                                        when "0011" =>
1327
                                                                                runMode <= rmodeTime;
1328
                                                                        when "0100" =>
1329
                                                                                addr_block <= "00";
1330
                                                                        when "0101" =>
1331
                                                                                addr_block <= "01";
1332
                                                                        when "0110" =>
1333
                                                                                addr_block <= "10";
1334
                                                                        when "0111" =>
1335
                                                                                addr_block <= "11";
1336
                                                                        when OTHERS =>
1337
                                                                end case;
1338
 
1339
                                                        when "01" =>            -- Switches (does nothing here on write)
1340
 
1341
                                                        when "10" =>            -- Set LEDs 0-3
1342
                                                                LEDenable(3 downto 0) <= spi_command(3 downto 0);
1343
                                                                LEDSet <= '1';
1344
 
1345
                                                        when "11" =>            -- Set LEDs 4-7
1346
                                                                LEDenable(7 downto 4) <= spi_command(3 downto 0);
1347
                                                                LEDSet <= '1';
1348
 
1349
                                                        when OTHERS =>          -- Can't happen but ghdl complains without it
1350
                                                end case;
1351
                                        end if; -- end syn_rw='0'
1352
 
1353
                                        syn_rxdata_trigger_n <= '1';
1354
                                else
1355
                                        -- Start Data receive:
1356
                                        syn_rxdata_trigger_n <= '0';
1357
                                end if; -- end syn_xfer_mode=xmodeCmd
1358
 
1359
                                syn_cmd_processing_n <= '0';
1360
                        elsif (syn_cmd_processing_n = '0') then
1361
                                if (syn_rrdy_clr_n = '0') then
1362
                                        if (syn_rrdy = '0') then
1363
                                                syn_rrdy_clr_n <= '1';
1364
                                                syn_cmd_processing_n <= '1';
1365
                                        end if;
1366
                                elsif (syn_rxdata_trigger_n = '1') then
1367
                                        -- If this was just a command recept, release syn_rrdy here, since
1368
                                        --              the command was processed above
1369
                                        syn_rrdy_clr_n <= '0';
1370
                                elsif (syn_rxdata_processing_n = '0') then
1371
                                        -- But, if this was a data recept, keep syn_rrdy active and
1372
                                        --              syn_rxdata_trigger_n enabled until xferdataproc gets around
1373
                                        --              to processing the received data, which should happen
1374
                                        --              just as soon as any in-process tmrupdproc processes finish:
1375
                                        syn_rxdata_trigger_n <= '1';
1376
                                        syn_rrdy_clr_n <= '0';
1377
                                end if;
1378
                        end if;
1379
                end if;
1380
        end if;
1381
end process rxproc;
1382
-- --------------------------------------------------------------------
1383
 
1384
 
1385
-- --------------------------------------------------------------------
1386
-- xferdataproc:
1387
--      This process handles synchronous data transfer of data to set
1388
--              the timer memory.  It also handles resetting of the timer
1389
--              data and queuing of Transmit data.  This process runs at
1390
--              the xferdataclk clock rate.
1391
-- --------------------------------------------------------------------
1392
xferdataproc:process(xferdataclk, reset_n, local_rst_n, reset_trigger_n)
1393
begin
1394
        if (reset_trigger_n = '0') then
1395
                SPI_tx_data <= (OTHERS => '0');
1396
                txdata_processing_n <= '1';
1397
                syn_rxdata_processing_n <= '1';
1398
                cmpOnLeftMemBlk_ADDR <= (OTHERS => '0');
1399
                cmpFreqLeftMemBlk_ADDR <= (OTHERS => '0');
1400
                ----
1401
                cmpOnRightMemBlk_ADDR <= (OTHERS => '0');
1402
                cmpFreqRightMemBlk_ADDR <= (OTHERS => '0');
1403
                ----
1404
                tmrMemBlkLeft_ADDRXfer <= (OTHERS => '0');
1405
                tmrMemBlkRight_ADDRXfer <= (OTHERS => '0');
1406
                ----
1407
                reset_in_progress_n <= '0';                      -- Set the reset in progress flag so other rxproc knows we're working on it, otherwise remain in reset state
1408
                -- For resetting, our "state" is the tmrMemBlk address and each cycle is a write of data to it, so enable write gate and set initial data and address:
1409
                for i in 0 to numTimerBlocks-1 loop
1410
                        tmrMemBlkLeft_DINXfer(i) <= (OTHERS => '0');
1411
                        tmrMemBlkRight_DINXfer(i) <= (OTHERS => '0');
1412
                end loop;
1413
                tmrMemBlkLeft_WE_GATE <= (OTHERS => '1');       -- Note: Enabling this here won't engage memory writes until reset_n is deasserted  and our reset_in_progress state machine starts (see the concurrent logic)
1414
                tmrMemBlkRight_WE_GATE <= (OTHERS => '1');
1415
                ----
1416
                for i in 0 to numOutputs-1 loop
1417
                        for j in 0 to numTimerBlocks-1 loop
1418
                                outputEnablesNext(i)(j) <= (OTHERS => '0');
1419
                                outputForceLoad(i)(j) <= (OTHERS => '0');
1420
                        end loop;
1421
                end loop;
1422
        else
1423
                if (falling_edge(xferdataclk)) then
1424
                        if (reset_in_progress_n = '0') then
1425
                                -- If we are resetting, run the Reset State-Machine to clear
1426
                                --              out the Timer Data:
1427
                                -- Note: The addresses here are current-state for setting up the "next" value:
1428
                                if (tmrMemBlkLeft_ADDRXfer = "11111111") then
1429
                                        -- When we are done, clear memory write and stop state-machine:
1430
                                        tmrMemBlkLeft_WE_GATE <= (OTHERS => '0');
1431
                                        tmrMemBlkRight_WE_GATE <= (OTHERS => '0');
1432
                                        reset_in_progress_n <= '1';
1433
                                elsif (tmrMemBlkLeft_ADDRXfer = "00111111") then
1434
                                        -- If entering into PitchBend memory, set the defaults to 0x2000 which is midi value for "no bend":
1435
                                        for i in 0 to numTimerBlocks-1 loop
1436
                                                tmrMemBlkLeft_DINXfer(i) <= "0010000000000000";
1437
                                                tmrMemBlkRight_DINXfer(i) <= "0010000000000000";
1438
                                        end loop;
1439
                                elsif (tmrMemBlkLeft_ADDRXfer = "01111111") then
1440
                                        -- If leaving PitchBend memory, return to zeroing everything:
1441
                                        for i in 0 to numTimerBlocks-1 loop
1442
                                                tmrMemBlkLeft_DINXfer(i) <= (OTHERS => '0');
1443
                                                tmrMemBlkRight_DINXfer(i) <= (OTHERS => '0');
1444
                                        end loop;
1445
                                end if;
1446
                                tmrMemBlkLeft_ADDRXfer <= tmrMemBlkLeft_ADDRXfer + 1;
1447
                                tmrMemBlkRight_ADDRXfer <= tmrMemBlkRight_ADDRXfer + 1;
1448
                        elsif ((txdata_trigger_n = '0') OR (txdata_processing_n = '0')) then
1449
                                if ((txdata_trigger_n = '0') AND (txdata_processing_n = '1')) then                               -- If we aren't in reset, do normal TxData processing
1450
                                        -- Start transmit state-machine:
1451
                                        txdata_processing_n <= '0';
1452
                                        txdata_state <= (OTHERS => '0');
1453
 
1454
                                        -- State -1:
1455
                                        --              Select Note/Power or Timer ON data
1456
                                        tmrMemBlkLeft_ADDRXfer <= runMode & "0" & addr_subtimer;                                 -- Select Note/Power or Timer ON data store for Left Channel
1457
                                        tmrMemBlkRight_ADDRXfer <= runMode & "0" & addr_subtimer;                                        -- Select Note/Power or Timer ON data store for Right Channel
1458
 
1459
                                elsif (txdata_processing_n = '0') then
1460
 
1461
                                        -- Handle transmit -- give it a higher priority that receive processing so we don't collide with memory accesses and this needs to be asynchronous when the SPI needs it
1462
                                        case CONV_INTEGER(txdata_state) is
1463
 
1464
                                                -- State 0:
1465
                                                --              Save Note/Power or Timer ON data
1466
                                                --              Select PitchBend or Timer OFF data
1467
                                                when 0 =>
1468
                                                        txdata_state <= CONV_STD_LOGIC_VECTOR(1, nTxSB);                                                -- Goto state 1
1469
 
1470
                                                        SPI_tx_data(63 downto 48) <= tmrMemBlkLeft_DOUTXfer(TmrBlock(addr_block));      -- Save Note/Power or Timer ON data for Left Channel
1471
                                                        SPI_tx_data(31 downto 16) <= tmrMemBlkRight_DOUTXfer(TmrBlock(addr_block));     -- Save Note/Power or Timer ON data for Right Channel
1472
                                                        tmrMemBlkLeft_ADDRXfer <= runMode & "1" & addr_subtimer;                                -- Select PitchBend or Timer OFF data store for Left Channel
1473
                                                        tmrMemBlkRight_ADDRXfer <= runMode & "1" & addr_subtimer;                               -- Select PitchBend or Timer OFF data store for Right Channel
1474
 
1475
 
1476
                                                -- State 1 :
1477
                                                --              Save PitchBend or Timer OFF data
1478
                                                when 1 =>
1479
                                                        txdata_state <= CONV_STD_LOGIC_VECTOR(3, nTxSB);                                                -- Goto state 3
1480
 
1481
                                                        SPI_tx_data(47 downto 32) <= tmrMemBlkLeft_DOUTXfer(TmrBlock(addr_block));      -- Save PitchBend or Timer OFF data for Left Channel
1482
                                                        SPI_tx_data(15 downto 0) <= tmrMemBlkRight_DOUTXfer(TmrBlock(addr_block));       -- Save PitchBend or Timer OFF data for Right Channel
1483
 
1484
 
1485
                                                -- State 3 :  (Gray-Code Numbered to minimize transition logic)
1486
                                                --              Transition to done
1487
                                                when 3 =>
1488
                                                        txdata_processing_n <= '1';                                                                                             -- Done
1489
 
1490
 
1491
                                                -- No other states should happen, but as safeguard, disable TX Processing:
1492
                                                when OTHERS =>
1493
                                                        txdata_processing_n <= '1';
1494
 
1495
                                        end case;
1496
                                end if;
1497
 
1498
                        elsif ((syn_rxdata_trigger_n = '0') AND (syn_rxdata_processing_n = '1')) then                    -- If not queuing transmit data, process queued receive data:
1499
                                -- Start receive state-machine:
1500
                                syn_rxdata_processing_n <= '0';
1501
                                syn_rxdata_state <= (OTHERS => '0');
1502
 
1503
                                if (runMode = rmodeNote) then
1504
 
1505
                                        -- Pre-Process receive state-machine for Note/Power/PitchBend Run Mode:
1506
                                        -- State -1 :
1507
                                        --              Calculate PitchBend Note Indexes
1508
                                        --              Set tmrMemBlk Address and DataIn to Store the Note/Power Data
1509
                                        --              Enable tmrMemBlk WEB Gate to write the Timer Memory Block on the next several states
1510
                                        if ((CONV_INTEGER(synrx_leftNote) < (LOWERNOTE_INDEX+2)) OR
1511
                                                (CONV_INTEGER(synrx_leftNote) > (UPPERNOTE_INDEX-2))) then
1512
                                                -- Here if we cannot do pitch bend, so interpolate on same value to keep the same calc paths:
1513
                                                pitchBendLeftNoteAIndex <= synrx_leftNote;
1514
                                                pitchBendLeftNoteBIndex <= synrx_leftNote;
1515
                                        else
1516
                                                -- Here if we can pitch bend
1517
                                                pitchBendLeftMagnitude <= synrx_leftPitchBend(11 downto 0);
1518
                                                case synrx_leftPitchBend(13 downto 12) is
1519
                                                        when "00" =>
1520
                                                                pitchBendLeftNoteAIndex <= synrx_leftNote - 2;
1521
                                                                pitchBendLeftNoteBIndex <= synrx_leftNote - 1;
1522
                                                        when "01" =>
1523
                                                                pitchBendLeftNoteAIndex <= synrx_leftNote - 1;
1524
                                                                pitchBendLeftNoteBIndex <= synrx_leftNote;
1525
                                                        when "10" =>
1526
                                                                pitchBendLeftNoteAIndex <= synrx_leftNote;
1527
                                                                pitchBendLeftNoteBIndex <= synrx_leftNote + 1;
1528
                                                        when "11" =>
1529
                                                                pitchBendLeftNoteAIndex <= synrx_leftNote + 1;
1530
                                                                pitchBendLeftNoteBIndex <= synrx_leftNote + 2;
1531
                                                        when OTHERS =>          -- Shouldn't be needed in real logic, but needs to account for 'U','X', etc in simulation as needed by ghdl compiler
1532
                                                end case;
1533
                                        end if;
1534
 
1535
                                        if ((CONV_INTEGER(synrx_rightNote) < (LOWERNOTE_INDEX+2)) OR
1536
                                                (CONV_INTEGER(synrx_rightNote) > (UPPERNOTE_INDEX-2))) then
1537
                                                -- Here if we cannot do pitch bend, so interpolate on same value to keep the same calc paths:
1538
                                                pitchBendRightNoteAIndex <= synrx_rightNote;
1539
                                                pitchBendRightNoteBIndex <= synrx_rightNote;
1540
                                        else
1541
                                                -- Here if we can pitch bend
1542
                                                pitchBendRightMagnitude <= synrx_rightPitchBend(11 downto 0);
1543
                                                case synrx_rightPitchBend(13 downto 12) is
1544
                                                        when "00" =>
1545
                                                                pitchBendRightNoteAIndex <= synrx_rightNote - 2;
1546
                                                                pitchBendRightNoteBIndex <= synrx_rightNote - 1;
1547
                                                        when "01" =>
1548
                                                                pitchBendRightNoteAIndex <= synrx_rightNote - 1;
1549
                                                                pitchBendRightNoteBIndex <= synrx_rightNote;
1550
                                                        when "10" =>
1551
                                                                pitchBendRightNoteAIndex <= synrx_rightNote;
1552
                                                                pitchBendRightNoteBIndex <= synrx_rightNote + 1;
1553
                                                        when "11" =>
1554
                                                                pitchBendRightNoteAIndex <= synrx_rightNote + 1;
1555
                                                                pitchBendRightNoteBIndex <= synrx_rightNote + 2;
1556
                                                        when OTHERS =>          -- Shouldn't be needed in real logic, but needs to account for 'U','X', etc in simulation as needed by ghdl compiler
1557
                                                end case;
1558
                                        end if;
1559
 
1560
                                        tmrMemBlkLeft_ADDRXfer <= adrNotePower & syn_addr_subtimer;                                                             -- Select Note/Power data store for Left Channel
1561
                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= "0" & synrx_leftNote & "0" & synrx_leftPower;              -- Save given Note (MSB) and Power (LSB)
1562
                                        tmrMemBlkLeft_WE_GATE(TmrBlock(addr_block)) <= '1';                                                                                             -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1563
 
1564
                                        tmrMemBlkRight_ADDRXfer <= adrNotePower & syn_addr_subtimer;                                                    -- Select Note/Power data store for Right Channel
1565
                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= "0" & synrx_rightNote & "0" & synrx_rightPower;           -- Save given Note (MSB) and Power (LSB)
1566
                                        tmrMemBlkRight_WE_GATE(TmrBlock(addr_block)) <= '1';                                                                                    -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1567
 
1568
                                else
1569
 
1570
                                        -- Pre-Process receive state-machine for Direct Timer On/Off Values Run Mode:
1571
                                        -- State -1 :
1572
                                        --              Set tmrMemBlk Address and DataIn to Store the Timer ON Value
1573
                                        --              Enable tmrMemBlk WEB Gate to write the Timer Memory Block on the next several states
1574
                                        tmrMemBlkLeft_ADDRXfer <= adrTimeON & syn_addr_subtimer;                                -- Select Timer ON data for Left Channel
1575
                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= synrx_leftTimerON;
1576
                                        tmrMemBlkLeft_WE_GATE(TmrBlock(addr_block)) <= '1';                                             -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1577
 
1578
                                        tmrMemBlkRight_ADDRXfer <= adrTimeON & syn_addr_subtimer;                               -- Select Timer ON data for Right Channel
1579
                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= synrx_RightTimerON;
1580
                                        tmrMemBlkRight_WE_GATE(TmrBlock(addr_block)) <= '1';                                    -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1581
 
1582
                                end if;
1583
 
1584
                        elsif (syn_rxdata_processing_n = '0') then
1585
                                if (runMode = rmodeNote) then
1586
                                        -- Process receive state-machine for Note/Power/PitchBend Run Mode:
1587
                                        case CONV_INTEGER(syn_rxdata_state) is
1588
 
1589
                                                -- State 0 :
1590
                                                --              Set Compare On and Freq addresses for Lower Note Read (This will cause their DOUT to be the compare values next time)
1591
                                                --              Set tmrMemBlk Address and DataIn to Store the PitchBend on next clock edge
1592
                                                when 0 =>
1593
                                                        cmpOnLeftMemBlk_ADDR <= synrx_leftPower & pitchBendLeftNoteAIndex;                      -- Power in upper 7-bits, Note in lower 7-bits of Address
1594
                                                        cmpFreqLeftMemBlk_ADDR <= pitchBendLeftNoteAIndex;
1595
                                                        tmrMemBlkLeft_ADDRXfer <= adrPitchBend & syn_addr_subtimer;                                     -- Select PitchBend data store for Left Channel
1596
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= "00" & synrx_leftPitchBend;      -- Save given Pitchbend
1597
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1598
 
1599
                                                        cmpOnRightMemBlk_ADDR <= synrx_rightPower & pitchBendRightNoteAIndex;           -- Power in upper 7-bits, Note in lower 7-bits of Address
1600
                                                        cmpFreqRightMemBlk_ADDR <= pitchBendRightNoteAIndex;
1601
                                                        tmrMemBlkRight_ADDRXfer <= adrPitchBend & syn_addr_subtimer;                                            -- Select PitchBend data store for Right Channel
1602
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= "00" & synrx_rightPitchBend;            -- Save given PitchBend
1603
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1604
 
1605
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(1, nRxSB);                                            -- Goto state 1
1606
 
1607
                                                -- State 1 :
1608
                                                --              Save Compare On and Freq Values for Lower Note (Alpha)
1609
                                                --              Set Compare On and Freq addresses for Upper Note Read (This will cause their DOUT to be the compare values next time)
1610
                                                --              Disable tmrMemBlk WEB Gate to write the Timer Memory Block on the next several states
1611
                                                --
1612
                                                --              Note: Since Off is Freq-On, subtracting the two during the pitchbend cancels out the "on" portion,
1613
                                                --                              meaning we only need to do that operation on the final interpolated "on" value.
1614
                                                when 1 =>
1615
                                                        pitchBendLeftCalcONAlpha <= cmpOnLeftMemBlk_DOUT;
1616
                                                        pitchBendLeftCalcFREQAlpha <= cmpFreqLeftMemBlk_DOUT;
1617
                                                        cmpOnLeftMemBlk_ADDR <= synrx_leftPower & pitchBendLeftNoteBIndex;                              -- Power in upper 7-bits, Note in lower 7-bits of Address
1618
                                                        cmpFreqLeftMemBlk_ADDR <= pitchBendLeftNoteBIndex;
1619
                                                        --tmrMemBlkLeft_WE_GATE(TmrBlock(addr_block)) <= '0';
1620
                                                        tmrMemBlkLeft_WE_GATE <= (OTHERS => '0');
1621
 
1622
                                                        pitchBendRightCalcONAlpha <= cmpOnRightMemBlk_DOUT;
1623
                                                        pitchBendRightCalcFREQAlpha <= cmpFreqRightMemBlk_DOUT;
1624
                                                        cmpOnRightMemBlk_ADDR <= synrx_rightPower & pitchBendRightNoteBIndex;                   -- Power in upper 7-bits, Note in lower 7-bits of Address
1625
                                                        cmpFreqRightMemBlk_ADDR <= pitchBendRightNoteBIndex;
1626
                                                        --tmrMemBlkRight_WE_GATE(TmrBlock(addr_block)) <= '0';
1627
                                                        tmrMemBlkRight_WE_GATE <= (OTHERS => '0');
1628
 
1629
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(3, nRxSB);                                                    -- Goto state 3
1630
 
1631
                                                -- State 3 :
1632
                                                --              Save Compare On and Freq Values for Upper Note (Beta)
1633
                                                --              Calculate Compare On and Freq Delta Values (done as part of concurrent logic)
1634
                                                when 3 =>
1635
                                                        pitchBendLeftCalcONBeta <= cmpOnLeftMemBlk_DOUT;
1636
                                                        pitchBendLeftCalcFREQBeta <= cmpFreqLeftMemBlk_DOUT;
1637
 
1638
                                                        pitchBendRightCalcONBeta <= cmpOnRightMemBlk_DOUT;
1639
                                                        pitchBendRightCalcFREQBeta <= cmpFreqRightMemBlk_DOUT;
1640
 
1641
                                                        -- Note: At this step, the following concurrent calculations will be evaluated
1642
                                                        --                      independently of this state-machine.  Results will be clocked after
1643
                                                        --                      NOP states below, allowing DSP operations to complete.
1644
                                                        --
1645
                                                        -- pitchBendLeftCalcONDelta <= pitchBendLeftCalcONBeta - pitchBendLeftCalcONAlpha;
1646
                                                        -- pitchBendLeftCalcFREQDelta <= pitchBendLeftCalcFREQBeta - pitchBendLeftCalcFREQAlpha;
1647
                                                        -- pitchBendRightCalcONDelta <= pitchBendRightCalcONBeta - pitchBendRightCalcONAlpha;
1648
                                                        -- pitchBendRightCalcFREQDelta <= pitchBendRightCalcFREQBeta - pitchBendRightCalcFREQAlpha;
1649
 
1650
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(2, nRxSB);                                                    -- Goto state 2
1651
 
1652
                                                -- State 2 :
1653
                                                --              NOP -- needed to allow DSP slices to finish calculations as the subtraction
1654
                                                --                              for the delta in the above step doesn't stabilize in time to satisfy
1655
                                                --                              the setup required for the DSP multiply to complete.  The result
1656
                                                --                              takes 13-21nS depending on path, according to the simulation models,
1657
                                                --                              and might cause us to miss the calculation.
1658
                                                --
1659
                                                when 2 =>
1660
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(6, nRxSB);                                                    -- Goto state 6
1661
 
1662
                                                -- State 6 :
1663
                                                --              NOP -- needed to allow DSP slices to finish calculations as the subtraction
1664
                                                --                              for the delta in the above step doesn't stabilize in time to satisfy
1665
                                                --                              the setup required for the DSP multiply to complete.  The result
1666
                                                --                              takes 13-21nS depending on path, according to the simulation models,
1667
                                                --                              and might cause us to miss the calculation.
1668
                                                when 6 =>
1669
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(7, nRxSB);                                                    -- Goto state 7
1670
 
1671
                                                -- State 7 :
1672
                                                --              Set tmrMemBlk Address and DataIn to Store the Compare ON Value (so we can save the DSP result)
1673
                                                --              Enable tmrMemBlk WEB Gate to write the Timer Memory Block on the next several states
1674
                                                when 7 =>
1675
                                                        tmrMemBlkLeft_ADDRXfer <= adrTimeON & syn_addr_subtimer;                                                -- Select Compare ON data store for Left Channel
1676
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= pitchBendLeftCalcONResult;               -- Save the Compare ON Result for Left Channel
1677
                                                        tmrMemBlkLeft_WE_GATE(TmrBlock(addr_block)) <= '1';                                                             -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1678
 
1679
                                                        tmrMemBlkRight_ADDRXfer <= adrTimeON & syn_addr_subtimer;                                               -- Select Compare ON data store for Right Channel
1680
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= pitchBendRightCalcONResult;             -- Save the Compare ON Result for Right Channel
1681
                                                        tmrMemBlkRight_WE_GATE(TmrBlock(addr_block)) <= '1';                                                    -- Enable writing to the Timer Memory Block during upcoming rising clock edges
1682
 
1683
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(5, nRxSB);                                                    -- Goto state 5
1684
 
1685
                                                -- State 5 :
1686
                                                --              Calculate the Compare OFF value by subtracting the ON value from the interpolated Freq value
1687
                                                --              Set tmrMemBlk Address and DataIn to Store the Compare OFF Value (so we can save the DSP result)
1688
                                                --              Enable/Disable Outputs based on results and force tmrproc reload if result wasn't 0
1689
                                                when 5 =>
1690
                                                        tmrMemBlkLeft_ADDRXfer <= adrTimeOFF & syn_addr_subtimer;                                               -- Select Compare OFF data store for Left Channel
1691
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= pitchBendLeftCalcFREQResult - pitchBendLeftCalcONResult;         -- Calculate and Save the Compare OFF Result for Left Channel
1692
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1693
 
1694
                                                        tmrMemBlkRight_ADDRXfer <= adrTimeOFF & syn_addr_subtimer;                                              -- Select Compare OFF data store for Right Channel
1695
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= pitchBendRightCalcFREQResult - pitchBendRightCalcONResult;      -- Calculate and Save the Compare OFF Result for Right Channel
1696
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1697
 
1698
                                                        if ((pitchBendLeftCalcONResult /= "0000000000000000") AND
1699
                                                                (pitchBendLeftCalcFREQResult /= "0000000000000000")) then
1700
                                                                outputEnablesNext(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '1';
1701
                                                        else
1702
                                                                outputEnablesNext(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '0';
1703
                                                        end if;
1704
                                                        outputForceLoad(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= NOT outputForceLoad(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer));
1705
 
1706
                                                        if ((pitchBendRightCalcONResult /= "0000000000000000") AND
1707
                                                                (pitchBendRightCalcFREQResult /= "0000000000000000")) then
1708
                                                                outputEnablesNext(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '1';
1709
                                                        else
1710
                                                                outputEnablesNext(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '0';
1711
                                                        end if;
1712
                                                        outputForceLoad(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= NOT outputForceLoad(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer));
1713
 
1714
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(4, nRxSB);                                                    -- Goto state 4
1715
 
1716
                                                -- State 4 :
1717
                                                --              Disable tmrMemBlk WEB Gate (we're done with it)
1718
                                                --              Done -- Disable RX Processing
1719
                                                when 4 =>
1720
                                                        tmrMemBlkLeft_WE_GATE <= (OTHERS => '0');                                                                                -- Disable writing to the Timer Memory Block (we're done)
1721
                                                        tmrMemBlkRight_WE_GATE <= (OTHERS => '0');                                                                               -- Disable writing to the Timer Memory Block (we're done)
1722
                                                        syn_rxdata_processing_n <= '1';
1723
 
1724
                                                -- No other states should happen, but as safeguard, disable RX Processing: (plus this is needed by ghdl compiler)
1725
                                                when OTHERS =>
1726
                                                        syn_rxdata_processing_n <= '1';
1727
                                        end case;
1728
                                else            -- End Note/Power/PitchBend RxData State-Machine
1729
                                        -- Process receive state-machine for Direct Timer On/Off Values Run Mode:
1730
                                        case CONV_INTEGER(syn_rxdata_state) is
1731
 
1732
                                                -- State 0 :
1733
                                                --              Set tmrMemBlk Address and DataIn to Store the Timer OFF Value
1734
                                                when 0 =>
1735
                                                        tmrMemBlkLeft_ADDRXfer <= adrTimeOFF & syn_addr_subtimer;                                               -- Select Timer OFF data for Left Channel
1736
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= synrx_leftTimerOFF;
1737
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1738
 
1739
                                                        tmrMemBlkRight_ADDRXfer <= adrTimeOFF & syn_addr_subtimer;                                              -- Select Timer OFF data for Right Channel
1740
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= synrx_rightTimerOFF;
1741
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1742
 
1743
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(1, nRxSB);                                                    -- Goto state 1
1744
 
1745
                                                -- State 1 :
1746
                                                --              Set tmrMemBlk Address and DataIn to clear Note/Power:
1747
                                                when 1 =>
1748
                                                        tmrMemBlkLeft_ADDRXfer <= adrNotePower & syn_addr_subtimer;                                             -- Select Note/Power for Left Channel
1749
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= (OTHERS => '0');                                  -- Clear it
1750
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1751
 
1752
                                                        tmrMemBlkRight_ADDRXfer <= adrNotePower & syn_addr_subtimer;                                    -- Select Note/Power for Right Channel
1753
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= (OTHERS => '0');                         -- Clear it
1754
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1755
 
1756
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(3, nRxSB);                                                    -- Goto state 3
1757
 
1758
                                                -- State 3 :
1759
                                                --              Set tmrMemBlk Address and DataIn to clear PitchBend:
1760
                                                when 3 =>
1761
                                                        tmrMemBlkLeft_ADDRXfer <= adrPitchBend & syn_addr_subtimer;                                             -- Select PitchBend for Left Channel
1762
                                                        tmrMemBlkLeft_DINXfer(TmrBlock(addr_block)) <= "0010000000000000";                              -- Clear it
1763
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1764
 
1765
                                                        tmrMemBlkRight_ADDRXfer <= adrPitchBend & syn_addr_subtimer;                                    -- Select PitchBend for Right Channel
1766
                                                        tmrMemBlkRight_DINXfer(TmrBlock(addr_block)) <= "0010000000000000";                             -- Clear it
1767
                                                        -- Note tmrMemBlk_WEB_GATE already '1' to enable storing
1768
 
1769
                                                        syn_rxdata_state <= CONV_STD_LOGIC_VECTOR(2, nRxSB);                                                    -- Goto state 2
1770
 
1771
                                                -- State 2 :
1772
                                                --              Enable Channel Outputs if corresponding On/Off wasn't 0
1773
                                                --              Disable tmrMemBlk WEB Gate (we're done with it)
1774
                                                --              Done -- Disable RX Processing
1775
                                                when 2 =>
1776
                                                        if ((synrx_leftTimerON /= "0000000000000000") AND
1777
                                                                (synrx_leftTimerOFF /= "0000000000000000")) then
1778
                                                                outputEnablesNext(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '1';
1779
                                                        else
1780
                                                                outputEnablesNext(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '0';
1781
                                                        end if;
1782
                                                        outputForceLoad(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= NOT outputForceLoad(LEFT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer));
1783
 
1784
                                                        if ((synrx_rightTimerON /= "0000000000000000") AND
1785
                                                                (synrx_rightTimerOFF /= "0000000000000000")) then
1786
                                                                outputEnablesNext(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '1';
1787
                                                        else
1788
                                                                outputEnablesNext(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= '0';
1789
                                                        end if;
1790
                                                        outputForceLoad(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer)) <= NOT outputForceLoad(RIGHT_OUT_NDX)(TmrBlock(addr_block))(Tmr(syn_addr_subtimer));
1791
 
1792
                                                        tmrMemBlkLeft_WE_GATE <= (OTHERS => '0');                                                                        -- Disable writing to the Timer Memory Block (we're done)
1793
                                                        tmrMemBlkRight_WE_GATE <= (OTHERS => '0');                                                                       -- Disable writing to the Timer Memory Block (we're done)
1794
                                                        syn_rxdata_processing_n <= '1';
1795
 
1796
                                                -- Note: State 6 would be next with this Gray-Code encoding
1797
 
1798
                                                -- No other states should happen, but as safeguard, disable RX Processing:
1799
                                                when OTHERS =>
1800
                                                        syn_rxdata_processing_n <= '1';
1801
                                        end case;
1802
 
1803
                                end if;         -- End Direct Timer On/Off RxData State-Machine
1804
                        end if;         -- syn_rxdata Processing
1805
                end if;         -- Clock Edge
1806
        end if;         -- Reset
1807
end process xferdataproc;
1808
-- --------------------------------------------------------------------
1809
 
1810
 
1811
-- --------------------------------------------------------------------
1812
-- outproc:
1813
--      This process generates the outputs:
1814
-- --------------------------------------------------------------------
1815
outproc:process(sysclk, reset_n)
1816
        variable outputs : STD_LOGIC_VECTOR(numSubTimers-1 downto 0);
1817
        variable out_val : STD_LOGIC;
1818
begin
1819
        if (reset_n = '0') then
1820
                for i in 0 to numOutputs-1 loop
1821
                        FiberOut(i) <= '0';
1822
                end loop;
1823
        elsif (rising_edge(sysclk)) then
1824
                for i in 0 to numOutputs-1 loop
1825
                        out_val := '0';
1826
                        for j in 0 to numTimerBlocks-1 loop
1827
                                outputs := (outputEnables(i)(j) AND outputLevels(i)(j));
1828
                                for k in 0 to numSubTimers-1 loop
1829
                                        out_val := out_val OR outputs(k);
1830
                                end loop;
1831
                        end loop;
1832
                        FiberOut(i) <= out_val;
1833
                end loop;
1834
        end if;
1835
end process outproc;
1836
-- --------------------------------------------------------------------
1837
 
1838
 
1839
-- --------------------------------------------------------------------
1840
-- tmroutproc:
1841
--      This process handles the second-half of doing a round-robin update
1842
--              of all of the timers checking timer data and toggling outputs
1843
--              accrodingly.  This process is triggered by the main timerproc
1844
--              (which runs at the tmrclk clock rate) and this process runs at
1845
--              the sysclk clock rate (processing speed).
1846
--
1847
--      This process handles the output driving/toggling instigated by
1848
--              tmrupdproc.  This process runs on the rising edge of sysclk,
1849
--              whereas tmrupdproc runs on the falling eddge of sysclk.  This
1850
--              allows us an extra 5nS for the output results and timer data
1851
--              (selected via concurrent logic) to get setup before the clock,
1852
--              otherwise we wouldn't have enough setup time.
1853
-- --------------------------------------------------------------------
1854
tmroutproc:process(sysclk, reset_n, local_rst_n, reset_in_progress_n)
1855
begin
1856
        if ((reset_n = '0') OR
1857
                (local_rst_n = '0') OR
1858
                (reset_in_progress_n = '0')) then
1859
                ----
1860
                for i in 0 to numOutputs-1 loop
1861
                        for j in 0 to numTimerBlocks-1 loop
1862
                                outputEnables(i)(j) <= (OTHERS => '0');
1863
                                outputLevels(i)(j) <= (OTHERS => '0');
1864
                                outputForceLoad_done(i)(j) <= (OTHERS => '0');
1865
                        end loop;
1866
                end loop;
1867
        elsif (rising_edge(sysclk)) then
1868
                if (tmrproc_processing_n = '0') then
1869
                        case CONV_INTEGER(tmrproc_state) is
1870
                                -- State 1:
1871
                                --              ODD-TRANSITION, EVEN-SETUP (Note state-numbers are flip-flopped because other state-machine already transitioned them at the falling edge)
1872
                                when 1 =>
1873
                                        for i in 0 to numTimerBlocks-1 loop
1874
                                                if (((outputEnables(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) = '0') AND
1875
                                                         (outputForceLoad(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) /= outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)))) OR
1876
                                                         (tmrCTMemBlkLeft_eqTimer(i) = '1')) then                               -- If this Timer Left Channel matches our timer or wasn't enabled and becoming enabled, process toggle
1877
                                                        outputLevels(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= NOT outputLevels(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));           -- Toggle
1878
                                                        outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= NOT outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));
1879
                                                        outputEnables(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= outputEnablesNext(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));
1880
                                                end if;
1881
 
1882
                                                if (((outputEnables(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) = '0') AND
1883
                                                         (outputForceLoad(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) /= outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)))) OR
1884
                                                         (tmrCTMemBlkRight_eqTimer(i) = '1')) then                              -- If this Timer Right Channel matches our timer or wasn't enabled and becoming enabled, process toggle
1885
                                                        outputLevels(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= NOT outputLevels(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));         -- Toggle
1886
                                                        outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= NOT outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));
1887
                                                        outputEnables(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock)) <= outputEnablesNext(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODDLock));
1888
                                                end if;
1889
                                        end loop;
1890
 
1891
                                        tmrproc_tmrndxEVENLock <= tmrproc_tmrndxEVEN;                                           -- Lock EVEN Timer Index for EVEN-Setup
1892
 
1893
                                -- State 0:
1894
                                --              EVEN-TRANSITION, ODD-SETUP (Note state-numbers are flip-flopped because other state-machine already transitioned them at the falling edge)
1895
                                when 0 =>
1896
                                        for i in 0 to numTimerBlocks-1 loop
1897
                                                if (((outputEnables(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) = '0') AND
1898
                                                         (outputForceLoad(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) /= outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)))) OR
1899
                                                         (tmrCTMemBlkLeft_eqTimer(i) = '1')) then                               -- If this Timer Left Channel matches our timer or wasn't enabled and becoming enabled, process toggle
1900
                                                        outputLevels(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= NOT outputLevels(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));               -- Toggle
1901
                                                        outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= NOT outputForceLoad_done(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));
1902
                                                        outputEnables(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= outputEnablesNext(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));
1903
                                                end if;
1904
 
1905
                                                if (((outputEnables(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) = '0') AND
1906
                                                         (outputForceLoad(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) /= outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)))) OR
1907
                                                         (tmrCTMemBlkRight_eqTimer(i) = '1')) then                              -- If this Timer Right Channel matches our timer or wasn't enabled and becoming enabled, process toggle
1908
                                                        outputLevels(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= NOT outputLevels(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));             -- Toggle
1909
                                                        outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= NOT outputForceLoad_done(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));
1910
                                                        outputEnables(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock)) <= outputEnablesNext(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVENLock));
1911
                                                end if;
1912
                                        end loop;
1913
 
1914
                                        tmrproc_tmrndxODDLock <= tmrproc_tmrndxODD;                                                     -- Lock ODD Timer Index for ODD-Setup
1915
 
1916
                                when OTHERS =>                          -- There are no other cases, but keep ghdl compiler happy...
1917
                        end case;
1918
                end if;
1919
        end if;
1920
end process tmroutproc;
1921
-- --------------------------------------------------------------------
1922
 
1923
 
1924
-- --------------------------------------------------------------------
1925
-- tmrupdproc:
1926
--      This process handles the primary-half of doing a round-robin update
1927
--              of all of the timers checking timer data and toggling outputs
1928
--              accrodingly.  This process is triggered by the main timerproc
1929
--              (which runs at the tmrclk clock rate) and this process runs at
1930
--              the sysclk clock rate (processing speed).
1931
--
1932
--      This process sets up the timer memory read addressing and handles
1933
--              the round-robin indexing logic and instigating what values
1934
--              come next, but doesn't handle the output driving/toggling,
1935
--              which is done by tmroutproc.
1936
-- --------------------------------------------------------------------
1937
tmrupdproc:process(sysclk, reset_n, local_rst_n, reset_in_progress_n)
1938
begin
1939
        if ((reset_n = '0') OR
1940
                (local_rst_n = '0') OR
1941
                (reset_in_progress_n = '0')) then
1942
                ----
1943
                tmrCTMemBlkLeft_ADDRA <= (OTHERS => '0');
1944
                tmrCTMemBlkLeft_ADDRB <= (OTHERS => '0');
1945
                tmrCTMemBlkLeft_WE_GATE <= (OTHERS => '0');
1946
                ----
1947
                tmrCTMemBlkRight_ADDRA <= (OTHERS => '0');
1948
                tmrCTMemBlkRight_ADDRB <= (OTHERS => '0');
1949
                tmrCTMemBlkRight_WE_GATE <= (OTHERS => '0');
1950
                ----
1951
                for i in 0 to numTimerBlocks-1 loop
1952
                        tmrMemBlkLeft_ADDRTmr(i) <= (OTHERS => '0');
1953
                        tmrMemBlkRight_ADDRTmr(i) <= (OTHERS => '0');
1954
                end loop;
1955
                ----
1956
                tmrproc_tmrndxEVEN <= "00000";
1957
                tmrproc_tmrndxODD <= "00000";
1958
                tmrproc_processing_n <= '1';
1959
        elsif (falling_edge(sysclk)) then
1960
                if ((tmrproc_trigger_n = '0') AND (tmrproc_processing_n = '1')) then                     -- Handle setup coming out of reset:
1961
                        -- Start timer processing state-machine:
1962
                        tmrproc_processing_n <= '0';
1963
                        ----
1964
                        -- Note : tmrCTMemBlkXXXX addresses set in reset to first state
1965
 
1966
                        ---- SETUP FOR EVEN TIMER ---
1967
 
1968
                        for i in 0 to numTimerBlocks-1 loop
1969
                                if (outputLevels(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, "00000")) = '1') then
1970
                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeOFF & EVEN_NDX & "00000";    -- Get amount of time to be off
1971
                                else
1972
                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeON & EVEN_NDX & "00000";             -- Get amount of time to be on
1973
                                end if;
1974
 
1975
                                if (outputLevels(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, "00000")) = '1') then
1976
                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeOFF & EVEN_NDX & "00000";   -- Get amount of time to be off
1977
                                else
1978
                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeON & EVEN_NDX & "00000";    -- Get amount of time to be on
1979
                                end if;
1980
                        end loop;
1981
 
1982
                        tmrproc_state <= CONV_STD_LOGIC_VECTOR(1, nTSB);        -- Goto State 1 to start
1983
                elsif (tmrproc_processing_n = '0') then
1984
                        -- Loop through timers processing compare logic:
1985
 
1986
                        case CONV_INTEGER(tmrproc_state) is
1987
                                -- State 0:
1988
                                --              ODD-TRANSITION, EVEN-SETUP
1989
                                when 0 =>
1990
                                        -- Enable ALL writes (for speed).  If a timer doesn't need updating, we'll
1991
                                        --              simply write it back with the same value.  We have to do this here
1992
                                        --              and on both paths so we don't accidentally write the first transition
1993
                                        --              coming into this state-machine.  Likewise for disabling it, it has
1994
                                        --              to be disabled in the exit/done state:
1995
                                        tmrCTMemBlkLeft_WE_GATE <= (OTHERS => '1');
1996
                                        tmrCTMemBlkRight_WE_GATE <= (OTHERS => '1');
1997
 
1998
                                        ---- TRANSITION FOR ODD TIMER ----
1999
 
2000
                                        tmrCTMemBlkLeft_ADDRA <= ODD_NDX & tmrproc_tmrndxODD;                           -- Setup to write the Timer Compare value for this timer Left Channel
2001
                                        tmrCTMemBlkRight_ADDRA <= ODD_NDX & tmrproc_tmrndxODD;                          -- Setup to write the Timer Compare value for this timer Right Channel
2002
 
2003
                                        tmrproc_state <= CONV_STD_LOGIC_VECTOR(1, nTSB);                                        -- Keep looping
2004
                                        tmrproc_tmrndxODD <= tmrproc_tmrndxODD + 1;
2005
 
2006
                                        -------------------------------------------------------------------------------
2007
 
2008
                                        ---- SETUP FOR EVEN TIMER ----
2009
 
2010
                                        tmrCTMemBlkLeft_ADDRB <= EVEN_NDX & tmrproc_tmrndxEVEN;                         -- Setup to read the Timer Compare value for this timer Left Channel
2011
                                        tmrCTMemBlkRight_ADDRB <= EVEN_NDX & tmrproc_tmrndxEVEN;                        -- Setup to read the Timer Compare value for this timer Right Channel
2012
 
2013
                                        for i in 0 to numTimerBlocks-1 loop
2014
                                                if (outputLevels(LEFT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVEN)) = '1') then
2015
                                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeOFF & EVEN_NDX & tmrproc_tmrndxEVEN;         -- Get amount of time to be off
2016
                                                else
2017
                                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeON & EVEN_NDX & tmrproc_tmrndxEVEN;          -- Get amount of time to be on
2018
                                                end if;
2019
 
2020
                                                if (outputLevels(RIGHT_OUT_NDX)(i)(Tmr(EVEN_NDX, tmrproc_tmrndxEVEN)) = '1') then
2021
                                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeOFF & EVEN_NDX & tmrproc_tmrndxEVEN;        -- Get amount of time to be off
2022
                                                else
2023
                                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeON & EVEN_NDX & tmrproc_tmrndxEVEN;         -- Get amount of time to be on
2024
                                                end if;
2025
                                        end loop;
2026
 
2027
                                -- State 1:
2028
                                --              EVEN-TRANSITION, ODD-SETUP
2029
                                when 1 =>
2030
                                        -- Enable ALL writes (for speed).  If a timer doesn't need updating, we'll
2031
                                        --              simply write it back with the same value.  We have to do this here
2032
                                        --              and on both paths so we don't accidentally write the first transition
2033
                                        --              coming into this state-machine.  Likewise for disabling it, it has
2034
                                        --              to be disabled in the exit/done state:
2035
                                        tmrCTMemBlkLeft_WE_GATE <= (OTHERS => '1');
2036
                                        tmrCTMemBlkRight_WE_GATE <= (OTHERS => '1');
2037
 
2038
                                        ---- TRANSITION FOR EVEN TIMER ----
2039
 
2040
                                        tmrCTMemBlkLeft_ADDRA <= EVEN_NDX & tmrproc_tmrndxEVEN;                         -- Setup to write the Timer Compare value for this timer Left Channel
2041
                                        tmrCTMemBlkRight_ADDRA <= EVEN_NDX & tmrproc_tmrndxEVEN;                        -- Setup to write the Timer Compare value for this timer Right Channel
2042
 
2043
                                        tmrproc_state <= CONV_STD_LOGIC_VECTOR(0, nTSB);                                 -- Keep looping
2044
                                        tmrproc_tmrndxEVEN <= tmrproc_tmrndxEVEN + 1;
2045
 
2046
                                        -------------------------------------------------------------------------------
2047
 
2048
                                        ---- SETUP FOR ODD TIMER ----
2049
 
2050
                                        tmrCTMemBlkLeft_ADDRB <= ODD_NDX & tmrproc_tmrndxODD;                           -- Setup to read the Timer Compare value for this timer Left Channel
2051
                                        tmrCTMemBlkRight_ADDRB <= ODD_NDX & tmrproc_tmrndxODD;                          -- Setup to read the Timer Compare value for this timer Right Channel
2052
 
2053
                                        for i in 0 to numTimerBlocks-1 loop
2054
                                                if (outputLevels(LEFT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODD)) = '1') then
2055
                                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeOFF & ODD_NDX & tmrproc_tmrndxODD;           -- Get amount of time to be off
2056
                                                else
2057
                                                        tmrMemBlkLeft_ADDRTmr(i) <= adrTimeON & ODD_NDX & tmrproc_tmrndxODD;            -- Get amount of time to be on
2058
                                                end if;
2059
 
2060
                                                if (outputLevels(RIGHT_OUT_NDX)(i)(Tmr(ODD_NDX, tmrproc_tmrndxODD)) = '1') then
2061
                                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeOFF & ODD_NDX & tmrproc_tmrndxODD;          -- Get amount of time to be off
2062
                                                else
2063
                                                        tmrMemBlkRight_ADDRTmr(i) <= adrTimeON & ODD_NDX & tmrproc_tmrndxODD;           -- Get amount of time to be on
2064
                                                end if;
2065
                                        end loop;
2066
 
2067
                                -- No other states should happen, but as safeguard, disable Timer Processing and make sure write gate is off as something bad happened:
2068
                                when OTHERS =>
2069
                                        tmrCTMemBlkLeft_WE_GATE <= (OTHERS => '0');
2070
                                        tmrCTMemBlkRight_WE_GATE <= (OTHERS => '0');
2071
                                        tmrproc_processing_n <= '1';
2072
                        end case;
2073
                end if;         -- End of Timer Processing
2074
        end if;
2075
end process tmrupdproc;
2076
-- --------------------------------------------------------------------
2077
 
2078
 
2079
-- --------------------------------------------------------------------
2080
-- timerproc:
2081
--      This process is the main Timer Tick processing.  It handles updating
2082
--              the main timer and triggering processing synchronous logic
2083
--              in tmrupdproc.
2084
-- --------------------------------------------------------------------
2085
timerproc:process(tmrclk, tmrproc_processing_n, reset_n, local_rst_n)
2086
begin
2087
        if ((reset_n='0') OR
2088
                (local_rst_n='0')) then
2089
                tmrproc_trigger_n <= '1';
2090
                theTimer <= (OTHERS => '0');
2091
        elsif (rising_edge(tmrclk)) then
2092
                if (reset_in_progress_n = '1') then
2093
                        theTimer <= theTimer + 1;
2094
                        tmrproc_trigger_n <= '0';                                -- Used to synchronize tmrupdproc to rising tmrclk edge
2095
                end if;
2096
        end if;
2097
end process timerproc;
2098
-- --------------------------------------------------------------------
2099
 
2100
end TimerOCD_arch;
2101
 

powered by: WebSVN 2.1.0

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