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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [doc/] [interrupt.html] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 sinclairrf
<!-- Copyright 2015, Sinclair R.F., Inc. -->
2
<html>
3
<title>
4
macros
5
</title>
6
<body>
7
<h1>Interrupt handlers for the 9x8 micro controller</h1><br/>
8
Copyright 2012, Sinclair R.F., Inc.<br/><br/>
9
This document describes how to implement interrupt handlers for the 9x8 micro
10
  controller.<br/><br/>
11
There is a single interrupt in the controller, although this interrupt can be
12
  triggered by more than one signal.  Implementing interrupts consists of two
13
  actions:  adding a single interrupt peripheral to the processor architecture
14
  and adding a ".interrupt" body to the assembly source.<br/><br/>
15
The interrupt test bench illustrates how to add an interrupt for a single
16
  external event and the design in <tt>example/interrupt</tt> illustrates how to
17
  add an interrupt for two events, one external to the processor and one
18
  internal to the processor.<br/><br/>
19
<h2>Theory of Operation</h2>
20
  The interrupt peripheral creates two signals, <tt>s_interrupt</tt> and
21
  <tt>s_interrupted</tt>, for the interrupt event and to disable normal
22
  processor operation until the interrupt handler is running.<br/><br/>
23
  Specifically, <tt>s_interrupt</tt> is a non-registered signal that is high
24
  when (1)&nbsp;interrupts are enabled, (2)&nbsp;an interrupt edge has occurred
25
  (and not be precluded by the interrupt mask, if any), and (3)&nbsp;the
26
  processor is not in the middle of executing a jump, call, or return.<br/><br/>
27
  When <tt>s_interrupt</tt> goes high, the processor pushes the PC address for
28
  the current instruction onto the return stack, sets the next PC address to be
29
  the interrupt handler start address (so that the interrupt handler will start
30
  executing in 2&nbsp;instruction cycles), and otherwise performs a "nop."
31
  Because of the piplined PC/opcode architecture, a delay register is required
32
  for the current opcode PC address to be available.<br/><br/>
33
  The instruction cycle after <tt>s_interrupt</tt> is high must perform a "nop."
34
  This is done by using <tt>s_interrupted</tt> as a registered, delayed, version
35
  of <tt>s_interrupt</tt>.  When <tt>s_interrupted</tt> is high, the processor
36
  core is coerced to perform a "nop" and the instruction pipeline architecture
37
  starts fetching the second instruction in the interrupt handler.<br/><br/>
38
  When the "return" opcode is performed by the interrupt handler, execution will
39
  resume at the instruction that would have been performed when
40
  <tt>s_interrupt</tt> was high.  This instruction cannot be one immediately
41
  after a <tt>jump</tt>, <tt>call</tt>, or <tt>return</tt> or one after a
42
  <tt>jumpc</tt> or <tt>callc</tt> if the conditional was true, otherwise the
43
  processor will not perform the desired jump, call, or return and will simply
44
  start executing the code following the instruction after the jump, call, or
45
  return.<br/><br/>
46
  On&nbsp;return from the interrupt handler, the interrupts are enabled in a way
47
  that precludes the interrupt handler from being interrupted again.  This is
48
  done with the three instruction sequence "<tt>O_INTERRUPT_ENA return
49
  outport</tt>."  The outport, as the instruction performed immediately after
50
  the return, enables interrupts on the following instruction cycle, which will
51
  be the first instruction cycle resuming the previous execution
52
  sequence.<br/><br/>
53
  The interrupt peripheral needs to generate the <tt>s_interrupt</tt> and
54
  <tt>s_interrupted</tt> signals and the <tt>O_INTERRUPT_DIS</tt> and
55
  <tt>O_INTERRUPT_ENA</tt> outport strobes; create signals for any interrupt
56
  signals external to the processor; and instantiate the HDL for the
57
  interrupt.  Using the base class <tt>SSBCCinterruptPeripheral</tt> from
58
  <tt>ssbccPeripheral</tt> ensures the <tt>s_interrupt</tt> and
59
  <tt>s_interrupted</tt> signals are declared, although the code to generate
60
  their values is not created, and it ensures the two outport strobes are
61
  created.<br/><br/>
62
<h2>Example Implementation</h2>
63
  The interrupt peripheral provided with the core provides an interface for one
64
  to eight edge triggered interrupts.  These interrupt sources can be external
65
  to the processor or they can be signals from other peripherals.  They are
66
  normally rising edge triggered, but they can also be falling edge triggered.
67
  The peripheral also provides an optional mask for the interrupt sources,
68
  allowing it to be set, read, and initialized to a particular value.
69
  Constants for bit maps for the interrupt signals can be defined as part of
70
  selecting the signal for each of the one to eight interrupt signal
71
  sources.<br/><br/>
72
  The test bench for this interrupt peripheral illustrates a single, external,
73
  rising-edge interrupt signal.  The timing of the external interrupt was varied
74
  to validate correct generation of the <tt>s_interrupt</tt> signal and return
75
  from the interrupt handler (this was done by manually verifying the
76
  displayed instruction sequences).<br/><br/>
77
  An example interrupt controller for two interrupt signals, one external and
78
  one internal, and one rising edge and one falled edge, along with a mask for
79
  the interrupt signals, is also provided in
80
  <tt>example/interrupt</tt>.<br/><br/>
81
<h2>Construction of Interrupt Peripherals</h2>
82
  This discussion is based on the interrupt peripheral provided with the 9x8
83
  processor core.  It&nbsp;describes the HDL required to implement the interrupt
84
  hardware.<br/><br/>
85
  The processor core sets <tt>s_bus_pc</tt> to <tt>C_BUS_PC_JUMP</tt> when a
86
  jump or call is performed and it sets it to <tt>C_BUS_PC_RETURN</tt> when a
87
  return is being performed.  When <tt>s_bus_pc</tt> is either one of these
88
  values at the end of a processor clock cycle, then the instruction pipeline
89
  will be in the middle of performing a jump, call, or return during the
90
  following interval.  During this subsequent interval, interrupts must be
91
  disabled.  This is done by capturing the status of <tt>s_bus_pc</tt> in the
92
  register <tt>s_in_jump</tt> and prohibiting interrupts if <tt>s_in_jump</tt>
93
  is high.<br/><br/>
94
  The status of candidate interrupt signals is captured in
95
  <tt>s_interrupt_raw</tt>.  I.e., signal inversion is performed as required by
96
  the peripheral architecture statement and masking is performed where the mask
97
  is high if the signal is to be included as a candidate interrupt.  The "raw"
98
  interrupt triggers are then generated by looking for rising edges in this
99
  signal as compared to the value(s) for the previous clock cycle.<br/><br/>
100
  Two signals are then used to capture the trigger.  The first,
101
  <tt>s_interrupt_trigger</tt> records which enabled signals had a rising edge.
102
  In&nbsp;order to reduced the depth of subsequent logic for the interrupt
103
  signal itself, the single-bit signal <tt>s_interrupt_trigger_any</tt> records
104
  whether or not any enabled signal had a rising edge.  The history of both of
105
  these signals is cleared if the processor reads the input port for
106
  <tt>s_interrupt_trigger</tt>.<br/><br/>
107
  The non-registered interrupt signal is then generated if (1)&nbsp;interrupts
108
  are enabled, (2)&nbsp;a rising edge has occured, and (3)&nbsp;interrupts are
109
  not disabled because the instruction pipeline is in the middle of a jump,
110
  call, or return.<br/><br/>
111
  A&nbsp;delayed version of <tt>s_interrupt</tt> is registed as
112
  <tt>s_interrupted</tt> for generation of the interrupt-induced "nop"
113
  instruction that must follow the interrupt.<br/><br/>
114
  Finally, the interrupt enable signal is generated.  Interrupts are initially
115
  disabled (so that the processor can perform its initialization without
116
  spurious stated induced by premature interrupts).  Interrupts are then
117
  disabled when an interrupt occurs or when the <tt>O_INTERRUPT_DIS</tt> strobe
118
  is received.  Interrupts are only enabled when the <tt>O_INTERRUPT_ENA</tt>
119
  strobe is received.<br/><br/>
120
<h2>Construction of Interrupt Handlers</h2>
121
  If&nbsp;there is only one signal that can produce an interrupt (as set in the
122
  peripheral architecture statement), then the interrupt handler simply
123
  processed the interrupt and exits using the <tt>.returni</tt> macro.  For
124
  example, the following code simply counts the number of interrupts received
125
  (provided that they don't occur so fast that the interrupt handler isn't
126
  called as fast as the interrupts occur):<br/><br/>
127
  <tt>&nbsp;&nbsp;.interrupt<br/></tt>
128
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;.fetchvalue(interruptCount) 1+ .storevalue(interruptCount)<br/></tt>
129
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;.returni<br/></tt><br/>
130
  If&nbsp;there is more than one signal that can produce an interrupt, then the
131
  construction of the interrupt handler is slightly more complicated.  Suppose
132
  the interrupt peripheral architecture statement is:<br/><br/>
133
  <tt>&nbsp;&nbsp;PERIPHERAL&nbsp;interrupt&nbsp;insignal0=i_int0,C_INT0&nbsp;\<br/></tt>
134
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insignal1=i_int1,C_INT1&nbsp;\<br/></tt>
135
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inport=I_INTERRUPT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br/></tt>
136
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/></tt><br/>
137
  The interrupt handler then reads the interrupt trigger, conditionally calls
138
  subroutines for the appropriate interrupt, clears the trigger from the data
139
  stack, and returns as follows:<br/><br/>
140
  <tt>&nbsp;&nbsp;.interrupt<br/></tt>
141
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;.inport(I_INTERRUPT)<br/></tt>
142
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;dup C_INT0 &amp; .callc(int0)<br/></tt>
143
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;dup C_INT1 &amp; .callc(int1)<br/></tt>
144
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;drop<br/></tt>
145
  <tt>&nbsp;&nbsp;&nbsp;&nbsp;.returni<br/></tt><br/>
146
</body>
147
</html>

powered by: WebSVN 2.1.0

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