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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [o8_trig_delay.vhd] - Blame information for rev 292

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 244 jshamlet
-- Copyright (c)2020 Jeremy Seth Henry
2
-- All rights reserved.
3
--
4
-- Redistribution and use in source and binary forms, with or without
5
-- modification, are permitted provided that the following conditions are met:
6
--     * Redistributions of source code must retain the above copyright
7
--       notice, this list of conditions and the following disclaimer.
8
--     * Redistributions in binary form must reproduce the above copyright
9
--       notice, this list of conditions and the following disclaimer in the
10
--       documentation and/or other materials provided with the distribution,
11
--       where applicable (as part of a user interface, debugging port, etc.)
12
--
13
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
--
24
-- VHDL Entity: o8_trig_delay
25 274 jshamlet
-- Description: Programmable delay timer with time-base selection. Allows both
26 292 jshamlet
--               the delay after triggering and pulse width to be set by
27 274 jshamlet
--               software. Output may either be routed to a pin or used to
28
--               trigger an interrupt.
29 244 jshamlet
--
30
-- Register Map:
31
-- Offset  Bitfield Description                        Read/Write
32
--   0x0   AAAAAAAA Delay Time  Byte 0                     (RW)
33
--   0x1   AAAAAAAA Delay Time  Byte 1                     (RW)
34
--   0x2   AAAAAAAA Delay Time  Byte 2                     (RW)
35
--   0x3   AAAAAAAA Pulse Width Byte 0                     (RW)
36
--   0x4   AAAAAAAA Pulse Width Byte 1                     (RW)
37
--   0x5   AAAAAAAA Pulse Width Byte 2                     (RW)
38 292 jshamlet
--   0x6   FEDCBBA- Timer Configuration                    (RW*)
39
--                  A: Global Interrupt Enable
40
--                  B: Interrupt Select
41
--                   00 - Interrupt on trigger input (pre-arm check)
42
--                   01 - Interrupt on trigger event (post-arm check)
43 244 jshamlet
--                   10 - Interrupt on delay done
44
--                   11 - Interrupt on pulse done
45 292 jshamlet
--                  C: Trigger Edge
46 244 jshamlet
--                    0 - Trigger on falling edge
47
--                    1 - Trigger on rising edge
48 292 jshamlet
--                  D: Automatic Re-Arm (enabled if 1)
49
--                  E: Time base locked (okay if 1)     (read-only)
50
--                  F: Time base source
51 244 jshamlet
--                    0 - Use the internal uSec_Tick pulse
52
--                    1 - Use an external clock source
53 292 jshamlet
--   0x7   FEDCB--A Timer Control                          (RW*)
54
--                  A: External Trigger Input State     (read-only)
55
--                  B: Issue Internal Trigger           (one-shot)
56
--                     Returns '0' on read
57
--                  C: Current output level             (read-only)
58
--                  D: Clear/Re-Arm on '1'              (one-shot)
59 244 jshamlet
--                     Trigger event status on read
60 292 jshamlet
--                  E: Disable/Safe Trigger             (one-shot)
61 244 jshamlet
--                     Returns '0' on read
62 292 jshamlet
--                  F: Enable/Arm Trigger               (one-shot)
63 244 jshamlet
--                     Trigger armed status on read
64
--
65
-- Revision History
66
-- Author          Date     Change
67
------------------ -------- ---------------------------------------------------
68
-- Seth Henry      05/14/20 Design start
69
-- Seth Henry      05/18/20 Added write qualification input
70 292 jshamlet
-- Seth Henry      05/27/21 Added internal trigger function
71
-- Seth Henry      05/27/21 Moved the arming logic to later in the trigger to
72
--                           allow premature trigger detection
73
-- Seth Henry      06/15/21 Added a global interrupt enable and modified the
74
--                           interrupt to use either the pre- or post-arm
75
--                           trigger input
76 244 jshamlet
 
77
library ieee;
78
use ieee.std_logic_1164.all;
79
  use ieee.std_logic_unsigned.all;
80
  use ieee.std_logic_arith.all;
81
  use ieee.std_logic_misc.all;
82
 
83
library work;
84
  use work.open8_pkg.all;
85
 
86
entity o8_trig_delay is
87
generic(
88
  Default_Delay              : std_logic_vector(23 downto 0) := x"000000";
89
  Default_Width              : std_logic_vector(23 downto 0) := x"000000";
90
  Default_Timebase           : std_logic := '0';
91
  Default_Auto_ReArm         : std_logic := '0';
92
  Default_Trigger_Edge       : std_logic := '1';
93
  Default_Int_Source         : std_logic_vector(1 downto 0) := "00";
94 292 jshamlet
  Default_Int_Enable         : std_logic := '0';
95 244 jshamlet
  Address                    : ADDRESS_TYPE
96
);
97
port(
98
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
99
  Write_Qual                 : in  std_logic := '1';
100
  Rd_Data                    : out DATA_TYPE;
101
  Interrupt                  : out std_logic;
102
  --
103
  Time_Base_Clock            : in  std_logic := '0';
104
  Time_Base_Locked           : in  std_logic := '1';
105
  --
106
  Ext_Trig                   : in  std_logic;
107
  Timer_Out                  : out std_logic
108
);
109
end entity;
110
 
111
architecture behave of o8_trig_delay is
112
 
113
  alias Clock                is Open8_Bus.Clock;
114
  alias Reset                is Open8_Bus.Reset;
115
  alias uSec_Tick            is Open8_Bus.uSec_Tick;
116
  alias Wr_Data_d            is Open8_Bus.Wr_Data;
117
 
118
  constant User_Addr         : std_logic_vector(15 downto 3) :=
119
                                Address(15 downto 3);
120
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 3);
121
  alias  Reg_Sel_d           is Open8_Bus.Address(2 downto 0);
122
 
123
  signal Addr_Match          : std_logic := '0';
124
  signal Reg_Sel_q           : std_logic_vector(2 downto 0) := "000";
125
  signal Wr_En_d             : std_logic := '0';
126
  signal Wr_En_q             : std_logic := '0';
127
  signal Wr_Data_q           : DATA_TYPE := x"00";
128
  signal Rd_En_d             : std_logic := '0';
129
  signal Rd_En_q             : std_logic := '0';
130
 
131
  -- Configuration Registers
132
 
133
  signal Pulse_Delay         : std_logic_vector(23 downto 0) := x"000000";
134
  alias  Pulse_Delay_B0      is Pulse_Delay( 7 downto  0);
135
  alias  Pulse_Delay_B1      is Pulse_Delay(15 downto  8);
136
  alias  Pulse_Delay_B2      is Pulse_Delay(23 downto  16);
137
 
138
  signal Pulse_Width         : std_logic_vector(23 downto 0) := x"000000";
139
  alias  Pulse_Width_B0      is Pulse_Width( 7 downto  0);
140
  alias  Pulse_Width_B1      is Pulse_Width(15 downto  8);
141
  alias  Pulse_Width_B2      is Pulse_Width(23 downto  16);
142
 
143
  signal Time_Base_Source    : std_logic := '0';
144
  signal Time_Base_Status    : std_logic := '0';
145
  signal Auto_ReArm          : std_logic := '0';
146
  signal Trigger_Edge        : std_logic := '0';
147
  signal Interrupt_Select    : std_logic_vector(1 downto 0);
148 292 jshamlet
  signal Interrupt_Enable    : std_logic := '0';
149 244 jshamlet
 
150 292 jshamlet
  signal Interrupt_Src       : std_logic := '0';
151
 
152
  signal Int_Trig            : std_logic := '0';
153 244 jshamlet
  signal Arm_Timer           : std_logic := '0';
154
  signal Safe_Timer          : std_logic := '0';
155
  signal Clear_Trigd         : std_logic := '0';
156
 
157
  -- Time Base signals
158
  signal Ext_TBC_SR          : std_logic_vector(3 downto 0) := "0000";
159
  signal Ext_TBL_SR          : std_logic_vector(3 downto 0) := "0000";
160
 
161
  signal Timer_Tick          : std_logic := '0';
162
 
163
  -- Trigger signals
164
  signal Ext_Trig_SR         : std_logic_vector(3 downto 0) := "0000";
165
  signal Trig_RE             : std_logic := '0';
166
  signal Trig_FE             : std_logic := '0';
167 292 jshamlet
  signal Trigger_In          : std_logic := '0';
168 244 jshamlet
  signal Trigger_Armed       : std_logic := '0';
169
  signal Trigger_Event       : std_logic := '0';
170 292 jshamlet
  signal Trigger_Event_q     : std_logic := '0';
171
  signal Delay_Trig          : std_logic := '0';
172 244 jshamlet
 
173
  -- Delay Timer signals
174
  signal Delay_Pending       : std_logic := '0';
175
  signal Delay_Tmr           : std_logic_vector(23 downto 0) := x"000000";
176
  signal Delay_Tmr_SR        : std_logic_vector(1 downto 0);
177
  signal Width_Trig          : std_logic := '0';
178
 
179
  -- Pulse Timer signals
180
  signal Width_Tmr           : std_logic_vector(23 downto 0) := x"000000";
181
  signal Width_Tmr_SR        : std_logic_vector(1 downto 0);
182
  signal Pulse_Out           : std_logic := '0';
183
  signal Pulse_Done          : std_logic := '0';
184
 
185
begin
186
 
187
  Timer_Out                  <= Pulse_Out;
188
 
189
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
190
  Wr_En_d                    <= Addr_Match and Open8_Bus.Wr_En;
191
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
192
 
193
  io_reg: process( Clock, Reset )
194
  begin
195
    if( Reset = Reset_Level )then
196
      Reg_Sel_q              <= (others => '0');
197
      Wr_En_q                <= '0';
198
      Wr_Data_q              <= (others => '0');
199
      Rd_En_q                <= '0';
200
      Rd_Data                <= OPEN8_NULLBUS;
201
      Pulse_Delay            <= Default_Delay;
202
      Pulse_Width            <= Default_Width;
203
      Time_Base_Source       <= Default_Timebase;
204
      Auto_ReArm             <= Default_Auto_ReArm;
205
      Trigger_Edge           <= Default_Trigger_Edge;
206
      Interrupt_Select       <= Default_Int_Source;
207 292 jshamlet
      Interrupt_Enable       <= Default_Int_Enable;
208
      Int_Trig               <= '0';
209 244 jshamlet
      Arm_Timer              <= '0';
210
      Safe_Timer             <= '0';
211
      Clear_Trigd            <= '0';
212
      Interrupt              <= '0';
213
    elsif( rising_edge( Clock ) )then
214
      Reg_Sel_q              <= Reg_Sel_d;
215
 
216
      Wr_En_q                <= Wr_En_d;
217
      Wr_Data_q              <= Wr_Data_d;
218
 
219 292 jshamlet
      Int_Trig               <= '0';
220 244 jshamlet
      Arm_Timer              <= '0';
221
      Safe_Timer             <= '0';
222
      Clear_Trigd            <= '0';
223
 
224
      if( Wr_En_q = '1' and Write_Qual = '1' )then
225
        case( Reg_Sel_q )is
226
          when "000" =>
227
            Pulse_Delay_B0   <= Wr_Data_q;
228
          when "001" =>
229
            Pulse_Delay_B1   <= Wr_Data_q;
230
          when "010" =>
231
            Pulse_Delay_B2   <= Wr_Data_q;
232
 
233
          when "011" =>
234
            Pulse_Width_B0   <= Wr_Data_q;
235
          when "100" =>
236
            Pulse_Width_B1   <= Wr_Data_q;
237
          when "101" =>
238
            Pulse_Width_B2   <= Wr_Data_q;
239
 
240
          when "110" =>
241
            Time_Base_Source <= Wr_Data_q(7);
242
            -- Reserved for status bit
243
            Auto_ReArm       <= Wr_Data_q(5);
244
            Trigger_Edge     <= Wr_Data_q(4);
245
            Interrupt_Select <= Wr_Data_q(3 downto 2);
246 292 jshamlet
            Interrupt_Enable <= Wr_Data_q(1);
247 244 jshamlet
 
248
          when "111" =>
249
            Arm_Timer        <= Wr_Data_q(7);
250
            Safe_Timer       <= Wr_Data_q(6);
251
            Clear_Trigd      <= Wr_Data_q(5);
252 292 jshamlet
            Int_Trig         <= Wr_Data_q(3);
253 244 jshamlet
          when others => null;
254
        end case;
255
      end if;
256
 
257
      Rd_Data                <= OPEN8_NULLBUS;
258
      Rd_En_q                <= Rd_En_d;
259
      if( Rd_En_q = '1' )then
260
        case( Reg_Sel_q )is
261
          when "000" =>
262
            Rd_Data          <= Pulse_Delay_B0;
263
          when "001" =>
264
            Rd_Data          <= Pulse_Delay_B1;
265
          when "010" =>
266
            Rd_Data          <= Pulse_Delay_B2;
267
 
268
          when "011" =>
269
            Rd_Data          <= Pulse_Width_B0;
270
          when "100" =>
271
            Rd_Data          <= Pulse_Width_B1;
272
          when "101" =>
273
            Rd_Data          <= Pulse_Width_B2;
274
 
275
          when "110" =>
276
            Rd_Data          <= Time_Base_Source & -- Bit 7
277
                                Time_Base_Status & -- Bit 6
278
                                Auto_ReArm &       -- Bit 5
279
                                Trigger_Edge &     -- Bit 4
280
                                Interrupt_Select & -- Bits 3:2
281
                                "00";              -- Bits 1:0
282
          when "111" =>
283
            Rd_Data          <= Trigger_Armed &    -- Bit 7
284
                                '0' &              -- Bit 6
285
                                Trigger_Event &    -- Bit 5
286
                                Pulse_Out &        -- Bit 4
287 292 jshamlet
                                "000" &            -- Bits 3:1
288
                                Ext_Trig_SR(3);    -- Bit 0
289 244 jshamlet
          when others => null;
290
        end case;
291
      end if;
292
 
293
      case( Interrupt_Select )is
294
        when "00" =>
295 292 jshamlet
          Interrupt_Src      <= Trigger_In;
296 244 jshamlet
        when "01" =>
297 292 jshamlet
          Interrupt_Src      <= Delay_Trig;
298 244 jshamlet
        when "10" =>
299 292 jshamlet
          Interrupt_Src      <= Width_Trig;
300 244 jshamlet
        when "11" =>
301 292 jshamlet
          Interrupt_Src      <= Pulse_Done;
302 244 jshamlet
        when others =>
303
          null;
304
      end case;
305
 
306 292 jshamlet
      Interrupt              <= Interrupt_Src and Interrupt_Enable;
307
 
308 244 jshamlet
    end if;
309
  end process;
310
 
311
  Time_Base_proc: process( Clock, Reset )
312
  begin
313
    if( Reset = Reset_Level )then
314
      Ext_TBC_SR             <= (others => '0');
315
      Ext_TBL_SR             <= (others => '0');
316
      Time_Base_Status       <= '0';
317
      Timer_Tick             <= '0';
318
    elsif( rising_edge(Clock) )then
319
      Ext_TBC_SR             <= Ext_TBC_SR(2 downto 0) & Time_Base_Clock;
320
      Ext_TBL_SR             <= Ext_TBL_SR(2 downto 0) & Time_Base_Locked;
321
 
322
      Time_Base_Status       <= '1';
323
      Timer_Tick             <= uSec_Tick;
324
      if( Time_Base_Source = '1' )then
325
        Time_Base_Status     <= Ext_TBL_SR(3);
326
        Timer_Tick           <= Ext_TBC_SR(2) and not Ext_TBC_SR(3);
327
      end if;
328
 
329
    end if;
330
  end process;
331
 
332
  Trigger_proc: process( Clock, Reset )
333
  begin
334
    if( Reset = Reset_Level )then
335
      Ext_Trig_SR            <= (others => '0');
336
      Trig_RE                <= '0';
337
      Trig_FE                <= '0';
338 292 jshamlet
      Trigger_In             <= '0';
339 244 jshamlet
      Trigger_Armed          <= '0';
340
      Trigger_Event          <= '0';
341 292 jshamlet
      Trigger_Event_q        <= '0';
342
      Delay_Trig             <= '0';
343 244 jshamlet
    elsif( rising_edge(Clock) )then
344
      Ext_Trig_SR            <= Ext_Trig_SR(2 downto 0) & Ext_Trig;
345
 
346
      Trig_RE                <= Ext_Trig_SR(2) and not Ext_Trig_SR(3);
347
      Trig_FE                <= Ext_Trig_SR(3) and not Ext_Trig_SR(2);
348
 
349 292 jshamlet
      Trigger_In             <= ((Trig_FE and not Trigger_Edge) or
350
                                 (Trig_RE and Trigger_Edge) or
351
                                  Int_Trig
352
                                );
353 244 jshamlet
 
354
      if( Arm_Timer = '1' )then
355
        Trigger_Armed        <= '1';
356
      elsif( Safe_Timer = '1' )then
357
        Trigger_Armed        <= '0';
358
      end if;
359
 
360 292 jshamlet
      if( Trigger_In = '1' )then
361
        Trigger_Event        <= Trigger_Armed;
362 244 jshamlet
      elsif( Clear_Trigd = '1' or Auto_ReArm = '1' )then
363
        Trigger_Event        <= '0';
364
      end if;
365
 
366 292 jshamlet
      -- Trigger on rising edge only
367
      Trigger_Event_q        <= Trigger_Event;
368
      Delay_Trig             <= Trigger_Event and (not Trigger_Event_q);
369 244 jshamlet
    end if;
370
  end process;
371
 
372
  Delay_proc: process( Clock, Reset )
373
  begin
374
    if( Reset = Reset_Level )then
375
      Delay_Pending          <= '0';
376
      Delay_Tmr              <= (others => '0');
377
      Delay_Tmr_SR           <= (others => '0');
378
      Width_Trig             <= '0';
379
    elsif( rising_edge(Clock) )then
380
 
381
      if( Delay_Trig = '1' )then
382
        Delay_Pending        <= '1';
383
      elsif( Timer_Tick = '1' and Delay_Pending = '1' )then
384
        Delay_Pending        <= '0';
385
      end if;
386
 
387
      Delay_Tmr              <= Delay_Tmr - Timer_Tick;
388
      if( Timer_Tick = '1' and Delay_Pending = '1' )then
389
        Delay_Tmr            <= Pulse_Delay;
390
      elsif( Delay_Tmr = 0 )then
391
        Delay_Tmr            <= (others => '0');
392
      end if;
393
 
394
      Delay_Tmr_SR           <= Delay_Tmr_SR(0) & nor_reduce(Delay_Tmr);
395
 
396
      -- If the pulse delay is set to zero, trigger the pulse output
397
      --  immediately (overriding the timer logic) otherwise, trigger when
398
      --  the delay timer crosses from 1 to 0
399
      Width_Trig             <= (Delay_Trig and nor_reduce(Pulse_Delay)) or
400
                                (Delay_Tmr_SR(0) and not Delay_Tmr_SR(1));
401
 
402
    end if;
403
  end process;
404
 
405
  Timer_proc: process( Clock, Reset )
406
  begin
407
    if( Reset = Reset_Level )then
408
      Width_Tmr              <= (others => '0');
409
      Pulse_Done             <= '0';
410
      Pulse_Out              <= '0';
411
    elsif( rising_edge(Clock) )then
412
      Width_Tmr              <= Width_Tmr - Timer_Tick;
413
      if( Width_Trig = '1' )then
414
        Width_Tmr            <= Pulse_Width;
415
      elsif( Width_Tmr = 0 )then
416
        Width_Tmr            <= (others => '0');
417
      end if;
418
 
419
      Width_Tmr_SR           <= Width_Tmr_SR(0) & nor_reduce(Width_Tmr);
420
 
421
      Pulse_Done             <= (Width_Trig and nor_reduce(Pulse_Width)) or
422
                                (Width_Tmr_SR(0) and not Width_Tmr_SR(1));
423
 
424
      if( Width_Trig = '1' )then
425
        Pulse_Out            <= '1';
426
      elsif( Pulse_Done = '1' )then
427
        Pulse_Out            <= '0';
428
      end if;
429
 
430
    end if;
431
  end process;
432
 
433
end architecture;

powered by: WebSVN 2.1.0

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