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 244

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

powered by: WebSVN 2.1.0

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