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 287

Go to most recent revision | 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
--               they delay after triggering and pulse width to be set by
27
--               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 275 jshamlet
--   0x6   EDCBAA-- Timer Configuration                    (RW*)
39 244 jshamlet
--                  A: Interrupt Select
40
--                   00 - Disabled
41
--                   01 - Interrupt on trigger event
42
--                   10 - Interrupt on delay done
43
--                   11 - Interrupt on pulse done
44
--                  B: Trigger Edge
45
--                    0 - Trigger on falling edge
46
--                    1 - Trigger on rising edge
47
--                  C: Automatic Re-Arm (enabled if 1)
48
--                  D: Time base locked (okay if 1)     (read-only)
49
--                  E: Time base source
50
--                    0 - Use the internal uSec_Tick pulse
51
--                    1 - Use an external clock source
52
--   0x7   DCBA---- Timer Control                          (RW*)
53
--                  A: Current output level             (read-only)
54
--                  B: Clear/Re-Arm on '1'              (one-shot)
55
--                     Trigger event status on read
56
--                  C: Disable/Safe Trigger             (one-shot)
57
--                     Returns '0' on read
58
--                  D: Enable/Arm Trigger               (one-shot)
59
--                     Trigger armed status on read
60
--
61
-- Revision History
62
-- Author          Date     Change
63
------------------ -------- ---------------------------------------------------
64
-- Seth Henry      05/14/20 Design start
65
-- Seth Henry      05/18/20 Added write qualification input
66
 
67
library ieee;
68
use ieee.std_logic_1164.all;
69
  use ieee.std_logic_unsigned.all;
70
  use ieee.std_logic_arith.all;
71
  use ieee.std_logic_misc.all;
72
 
73
library work;
74
  use work.open8_pkg.all;
75
 
76
entity o8_trig_delay is
77
generic(
78
  Default_Delay              : std_logic_vector(23 downto 0) := x"000000";
79
  Default_Width              : std_logic_vector(23 downto 0) := x"000000";
80
  Default_Timebase           : std_logic := '0';
81
  Default_Auto_ReArm         : std_logic := '0';
82
  Default_Trigger_Edge       : std_logic := '1';
83
  Default_Int_Source         : std_logic_vector(1 downto 0) := "00";
84
  Address                    : ADDRESS_TYPE
85
);
86
port(
87
  Open8_Bus                  : in  OPEN8_BUS_TYPE;
88
  Write_Qual                 : in  std_logic := '1';
89
  Rd_Data                    : out DATA_TYPE;
90
  Interrupt                  : out std_logic;
91
  --
92
  Time_Base_Clock            : in  std_logic := '0';
93
  Time_Base_Locked           : in  std_logic := '1';
94
  --
95
  Ext_Trig                   : in  std_logic;
96
  Timer_Out                  : out std_logic
97
);
98
end entity;
99
 
100
architecture behave of o8_trig_delay is
101
 
102
  alias Clock                is Open8_Bus.Clock;
103
  alias Reset                is Open8_Bus.Reset;
104
  alias uSec_Tick            is Open8_Bus.uSec_Tick;
105
  alias Wr_Data_d            is Open8_Bus.Wr_Data;
106
 
107
  constant User_Addr         : std_logic_vector(15 downto 3) :=
108
                                Address(15 downto 3);
109
  alias  Comp_Addr           is Open8_Bus.Address(15 downto 3);
110
  alias  Reg_Sel_d           is Open8_Bus.Address(2 downto 0);
111
 
112
  signal Addr_Match          : std_logic := '0';
113
  signal Reg_Sel_q           : std_logic_vector(2 downto 0) := "000";
114
  signal Wr_En_d             : std_logic := '0';
115
  signal Wr_En_q             : std_logic := '0';
116
  signal Wr_Data_q           : DATA_TYPE := x"00";
117
  signal Rd_En_d             : std_logic := '0';
118
  signal Rd_En_q             : std_logic := '0';
119
 
120
  -- Configuration Registers
121
 
122
  signal Pulse_Delay         : std_logic_vector(23 downto 0) := x"000000";
123
  alias  Pulse_Delay_B0      is Pulse_Delay( 7 downto  0);
124
  alias  Pulse_Delay_B1      is Pulse_Delay(15 downto  8);
125
  alias  Pulse_Delay_B2      is Pulse_Delay(23 downto  16);
126
 
127
  signal Pulse_Width         : std_logic_vector(23 downto 0) := x"000000";
128
  alias  Pulse_Width_B0      is Pulse_Width( 7 downto  0);
129
  alias  Pulse_Width_B1      is Pulse_Width(15 downto  8);
130
  alias  Pulse_Width_B2      is Pulse_Width(23 downto  16);
131
 
132
  signal Time_Base_Source    : std_logic := '0';
133
  signal Time_Base_Status    : std_logic := '0';
134
  signal Auto_ReArm          : std_logic := '0';
135
  signal Trigger_Edge        : std_logic := '0';
136
  signal Interrupt_Select    : std_logic_vector(1 downto 0);
137
 
138
  signal Arm_Timer           : std_logic := '0';
139
  signal Safe_Timer          : std_logic := '0';
140
  signal Clear_Trigd         : std_logic := '0';
141
 
142
  -- Time Base signals
143
  signal Ext_TBC_SR          : std_logic_vector(3 downto 0) := "0000";
144
  signal Ext_TBL_SR          : std_logic_vector(3 downto 0) := "0000";
145
 
146
  signal Timer_Tick          : std_logic := '0';
147
 
148
  -- Trigger signals
149
  signal Ext_Trig_SR         : std_logic_vector(3 downto 0) := "0000";
150
  signal Trig_RE             : std_logic := '0';
151
  signal Trig_FE             : std_logic := '0';
152
  signal Delay_Trig          : std_logic := '0';
153
  signal Trigger_Armed       : std_logic := '0';
154
  signal Trigger_Event       : std_logic := '0';
155
 
156
  -- Delay Timer signals
157
  signal Delay_Pending       : std_logic := '0';
158
  signal Delay_Tmr           : std_logic_vector(23 downto 0) := x"000000";
159
  signal Delay_Tmr_SR        : std_logic_vector(1 downto 0);
160
  signal Width_Trig          : std_logic := '0';
161
 
162
  -- Pulse Timer signals
163
  signal Width_Tmr           : std_logic_vector(23 downto 0) := x"000000";
164
  signal Width_Tmr_SR        : std_logic_vector(1 downto 0);
165
  signal Pulse_Out           : std_logic := '0';
166
  signal Pulse_Done          : std_logic := '0';
167
 
168
begin
169
 
170
  Timer_Out                  <= Pulse_Out;
171
 
172
  Addr_Match                 <= '1' when Comp_Addr = User_Addr else '0';
173
  Wr_En_d                    <= Addr_Match and Open8_Bus.Wr_En;
174
  Rd_En_d                    <= Addr_Match and Open8_Bus.Rd_En;
175
 
176
  io_reg: process( Clock, Reset )
177
  begin
178
    if( Reset = Reset_Level )then
179
      Reg_Sel_q              <= (others => '0');
180
      Wr_En_q                <= '0';
181
      Wr_Data_q              <= (others => '0');
182
      Rd_En_q                <= '0';
183
      Rd_Data                <= OPEN8_NULLBUS;
184
      Pulse_Delay            <= Default_Delay;
185
      Pulse_Width            <= Default_Width;
186
      Time_Base_Source       <= Default_Timebase;
187
      Auto_ReArm             <= Default_Auto_ReArm;
188
      Trigger_Edge           <= Default_Trigger_Edge;
189
      Interrupt_Select       <= Default_Int_Source;
190
      Arm_Timer              <= '0';
191
      Safe_Timer             <= '0';
192
      Clear_Trigd            <= '0';
193
      Interrupt              <= '0';
194
    elsif( rising_edge( Clock ) )then
195
      Reg_Sel_q              <= Reg_Sel_d;
196
 
197
      Wr_En_q                <= Wr_En_d;
198
      Wr_Data_q              <= Wr_Data_d;
199
 
200
      Arm_Timer              <= '0';
201
      Safe_Timer             <= '0';
202
      Clear_Trigd            <= '0';
203
 
204
      if( Wr_En_q = '1' and Write_Qual = '1' )then
205
        case( Reg_Sel_q )is
206
          when "000" =>
207
            Pulse_Delay_B0   <= Wr_Data_q;
208
          when "001" =>
209
            Pulse_Delay_B1   <= Wr_Data_q;
210
          when "010" =>
211
            Pulse_Delay_B2   <= Wr_Data_q;
212
 
213
          when "011" =>
214
            Pulse_Width_B0   <= Wr_Data_q;
215
          when "100" =>
216
            Pulse_Width_B1   <= Wr_Data_q;
217
          when "101" =>
218
            Pulse_Width_B2   <= Wr_Data_q;
219
 
220
          when "110" =>
221
            Time_Base_Source <= Wr_Data_q(7);
222
            -- Reserved for status bit
223
            Auto_ReArm       <= Wr_Data_q(5);
224
            Trigger_Edge     <= Wr_Data_q(4);
225
            Interrupt_Select <= Wr_Data_q(3 downto 2);
226
 
227
          when "111" =>
228
            Arm_Timer        <= Wr_Data_q(7);
229
            Safe_Timer       <= Wr_Data_q(6);
230
            Clear_Trigd      <= Wr_Data_q(5);
231
          when others => null;
232
        end case;
233
      end if;
234
 
235
      Rd_Data                <= OPEN8_NULLBUS;
236
      Rd_En_q                <= Rd_En_d;
237
      if( Rd_En_q = '1' )then
238
        case( Reg_Sel_q )is
239
          when "000" =>
240
            Rd_Data          <= Pulse_Delay_B0;
241
          when "001" =>
242
            Rd_Data          <= Pulse_Delay_B1;
243
          when "010" =>
244
            Rd_Data          <= Pulse_Delay_B2;
245
 
246
          when "011" =>
247
            Rd_Data          <= Pulse_Width_B0;
248
          when "100" =>
249
            Rd_Data          <= Pulse_Width_B1;
250
          when "101" =>
251
            Rd_Data          <= Pulse_Width_B2;
252
 
253
          when "110" =>
254
            Rd_Data          <= Time_Base_Source & -- Bit 7
255
                                Time_Base_Status & -- Bit 6
256
                                Auto_ReArm &       -- Bit 5
257
                                Trigger_Edge &     -- Bit 4
258
                                Interrupt_Select & -- Bits 3:2
259
                                "00";              -- Bits 1:0
260
          when "111" =>
261
            Rd_Data          <= Trigger_Armed &    -- Bit 7
262
                                '0' &              -- Bit 6
263
                                Trigger_Event &    -- Bit 5
264
                                Pulse_Out &        -- Bit 4
265
                                "0000";            -- Bits 3:0
266
          when others => null;
267
        end case;
268
      end if;
269
 
270
      case( Interrupt_Select )is
271
        when "00" =>
272
          Interrupt          <= '0';
273
        when "01" =>
274
          Interrupt          <= Delay_Trig;
275
        when "10" =>
276
          Interrupt          <= Width_Trig;
277
        when "11" =>
278
          Interrupt          <= Pulse_Done;
279
        when others =>
280
          null;
281
      end case;
282
 
283
    end if;
284
  end process;
285
 
286
  Time_Base_proc: process( Clock, Reset )
287
  begin
288
    if( Reset = Reset_Level )then
289
      Ext_TBC_SR             <= (others => '0');
290
      Ext_TBL_SR             <= (others => '0');
291
      Time_Base_Status       <= '0';
292
      Timer_Tick             <= '0';
293
    elsif( rising_edge(Clock) )then
294
      Ext_TBC_SR             <= Ext_TBC_SR(2 downto 0) & Time_Base_Clock;
295
      Ext_TBL_SR             <= Ext_TBL_SR(2 downto 0) & Time_Base_Locked;
296
 
297
      Time_Base_Status       <= '1';
298
      Timer_Tick             <= uSec_Tick;
299
      if( Time_Base_Source = '1' )then
300
        Time_Base_Status     <= Ext_TBL_SR(3);
301
        Timer_Tick           <= Ext_TBC_SR(2) and not Ext_TBC_SR(3);
302
      end if;
303
 
304
    end if;
305
  end process;
306
 
307
  Trigger_proc: process( Clock, Reset )
308
  begin
309
    if( Reset = Reset_Level )then
310
      Ext_Trig_SR            <= (others => '0');
311
      Trig_RE                <= '0';
312
      Trig_FE                <= '0';
313
      Delay_Trig             <= '0';
314
      Trigger_Armed          <= '0';
315
      Trigger_Event          <= '0';
316
    elsif( rising_edge(Clock) )then
317
      Ext_Trig_SR            <= Ext_Trig_SR(2 downto 0) & Ext_Trig;
318
 
319
      Trig_RE                <= Ext_Trig_SR(2) and not Ext_Trig_SR(3);
320
      Trig_FE                <= Ext_Trig_SR(3) and not Ext_Trig_SR(2);
321
 
322
      Delay_Trig             <= ((Trig_FE and not Trigger_Edge) or
323
                                 (Trig_RE and Trigger_Edge)) and
324
                                Trigger_Armed and (not Trigger_Event);
325
 
326
      if( Arm_Timer = '1' )then
327
        Trigger_Armed        <= '1';
328
      elsif( Safe_Timer = '1' )then
329
        Trigger_Armed        <= '0';
330
      end if;
331
 
332
      if( Delay_Trig = '1' )then
333
        Trigger_Event        <= '1';
334
      elsif( Clear_Trigd = '1' or Auto_ReArm = '1' )then
335
        Trigger_Event        <= '0';
336
      end if;
337
 
338
    end if;
339
  end process;
340
 
341
  Delay_proc: process( Clock, Reset )
342
  begin
343
    if( Reset = Reset_Level )then
344
      Delay_Pending          <= '0';
345
      Delay_Tmr              <= (others => '0');
346
      Delay_Tmr_SR           <= (others => '0');
347
      Width_Trig             <= '0';
348
    elsif( rising_edge(Clock) )then
349
 
350
      if( Delay_Trig = '1' )then
351
        Delay_Pending        <= '1';
352
      elsif( Timer_Tick = '1' and Delay_Pending = '1' )then
353
        Delay_Pending        <= '0';
354
      end if;
355
 
356
      Delay_Tmr              <= Delay_Tmr - Timer_Tick;
357
      if( Timer_Tick = '1' and Delay_Pending = '1' )then
358
        Delay_Tmr            <= Pulse_Delay;
359
      elsif( Delay_Tmr = 0 )then
360
        Delay_Tmr            <= (others => '0');
361
      end if;
362
 
363
      Delay_Tmr_SR           <= Delay_Tmr_SR(0) & nor_reduce(Delay_Tmr);
364
 
365
      -- If the pulse delay is set to zero, trigger the pulse output
366
      --  immediately (overriding the timer logic) otherwise, trigger when
367
      --  the delay timer crosses from 1 to 0
368
      Width_Trig             <= (Delay_Trig and nor_reduce(Pulse_Delay)) or
369
                                (Delay_Tmr_SR(0) and not Delay_Tmr_SR(1));
370
 
371
    end if;
372
  end process;
373
 
374
  Timer_proc: process( Clock, Reset )
375
  begin
376
    if( Reset = Reset_Level )then
377
      Width_Tmr              <= (others => '0');
378
      Pulse_Done             <= '0';
379
      Pulse_Out              <= '0';
380
    elsif( rising_edge(Clock) )then
381
      Width_Tmr              <= Width_Tmr - Timer_Tick;
382
      if( Width_Trig = '1' )then
383
        Width_Tmr            <= Pulse_Width;
384
      elsif( Width_Tmr = 0 )then
385
        Width_Tmr            <= (others => '0');
386
      end if;
387
 
388
      Width_Tmr_SR           <= Width_Tmr_SR(0) & nor_reduce(Width_Tmr);
389
 
390
      Pulse_Done             <= (Width_Trig and nor_reduce(Pulse_Width)) or
391
                                (Width_Tmr_SR(0) and not Width_Tmr_SR(1));
392
 
393
      if( Width_Trig = '1' )then
394
        Pulse_Out            <= '1';
395
      elsif( Pulse_Done = '1' )then
396
        Pulse_Out            <= '0';
397
      end if;
398
 
399
    end if;
400
  end process;
401
 
402
end architecture;

powered by: WebSVN 2.1.0

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