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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [peripherals/] [AXI4_Lite_Slave_DualPortRAM.py] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
################################################################################
2
#
3
# Copyright 2013, Sinclair R.F., Inc.
4
#
5
################################################################################
6
 
7
import math
8
import re;
9
 
10
from ssbccPeripheral import SSBCCperipheral
11
from ssbccUtil import SSBCCException;
12
 
13
class AXI4_Lite_Slave_DualPortRAM(SSBCCperipheral):
14
  """
15
  AXI-Lite slave implemented as a dual-port RAM.  The dual-port RAM has at most
16
  256 bytes addressable by a single 8-bit value.  The data is stored in little
17
  endian format (i.e., the LSB of the 32-bit word is stored in the lowest
18
  numbered address).\n
19
  Usage:
20
    PERIPHERAL AXI4_Lite_Slave_DualPortRAM              \\
21
                                basePortName=<name>     \\
22
                                address=<O_address>     \\
23
                                read=<I_read>           \\
24
                                write=<O_write>         \\
25
                                [size=<N>]              \\
26
                                [ram8|ram32]\n
27
  Where:
28
    basePortName=<name>
29
      specifies the name used to construct the multiple AXI4-Lite signals
30
    address=<O_address>
31
      specifies the symbol used to set the address used for read and write
32
      operations from and to the dual-port memory
33
    read=<I_read>
34
      specifies the symbol used to read from the dual-port memory
35
    write=<O_write>
36
      specifies the symbol used to write to the dual-port memory
37
    size=<N>
38
      optionally specify the size of the dual-port memory.
39
      Note:  N must be either a power of 2 in the range from 16 to 256 inclusive
40
             or it must be a local param with the same restrictions on its
41
             value.
42
      Note:  N=256, i.e., the largest memory possible, is the default.
43
      Note:  Using a localparam for the memory size provides a convenient way
44
             to use the size of the dual port RAM in the micro controller code.\n
45
    ram8
46
      optionally specifies using an 8-bit RAM for the dual-port memory instantiation
47
      Note:  This is the default
48
    ram32
49
      optionally specifies using a 32-bit RAM for the dual-port memrory instantiation
50
      Note:  This is required for Vivado 2013.3.
51
  Example:  The code fragments
52
              <addr> .outport(O_address) .inport(I_read)
53
            and
54
              <addr> .outport(O_address) <value> .outport(O_write)
55
            will read from and write to the dual-port RAM.\n
56
  Example:  Function to read the byte at the specified address:
57
              ; ( u_addr - u_value)
58
              .function als_read
59
                .outport(O_address) .inport(I_read) .return
60
            or
61
              ; ( u_addr - u_value)
62
              .function als_read
63
                .outport(O_address) I_read .return(inport)
64
            To invoke the function:
65
              <addr> .call(als_read)
66
            or
67
              .call(als_read,<addr>)\n
68
  Example:  Function to write the byte at the specified address:
69
              ; ( u_value u_addr - )
70
              .function als_write
71
                .outport(O_address) O_write outport .return(drop)
72
            To invoke the function:
73
              <value> <addr> .call(als_write)
74
            or
75
              <value> .call(als_write,<addr>)\n
76
  Example:  Spin on an address, waiting for the host processor to write to the
77
            address, do something when the address is written to, and then
78
            clear its contents.
79
              0x00 .outport(O_address)
80
              :loop .inport(I_read) 0= .jumpc(loop)
81
              ; Avoid race conditions between the processor writes and the micro
82
              ; controller read.
83
              .inport(I_read)
84
              ...
85
              ; clear the value and start waiting again
86
              0x00 O_address outport O_write outport .jump(loop,drop)\n
87
  LEGAL NOTICE:  ARM has restrictions on what kinds of applications can use
88
  interfaces based on their AXI protocol.  Ensure your application is in
89
  compliance with their restrictions before using this peripheral for an AXI
90
  interface.
91
  """
92
 
93
  def __init__(self,peripheralFile,config,param_list,loc):
94
    # Use the externally provided file name for the peripheral
95
    self.peripheralFile = peripheralFile;
96
    # Get the parameters.
97
    def validateSize(x):
98
      if re.match(r'L_\w+$',x):
99
        if not config.IsParameter(x):
100
          raise SSBCCException('"size=%s" is not a parameter at %s' % (x,loc,));
101
        ix = [param[0] for param in config.parameters].index(x);
102
        y = config.parameters[ix][1];
103
        if not re.match(r'[1-9]\d*$', y):
104
          raise SSBCCException('localparam must be a numeric constant, not "%s", to be used in "size=%s" at %s' % (y,x,loc,));
105
        y = int(y);
106
      elif re.match(r'[1-9]\d*$',x):
107
        y = int(x);
108
      else:
109
        raise SSBCCException('Malformed entry for "size=%s" at %s' % (x,loc,));
110
      if math.modf(math.log(y,2))[0] != 0:
111
        raise SSBCCException('size=%d must be a power of 2 at %s' % (y,loc,));
112
      if not (16 <= y <= 256):
113
        raise SSBCCException('size=%d must be between 16 and 256 inclusive at %s' % (y,loc,));
114
      return y;
115
    allowables = (
116
      ('address',       r'O_\w+$',      None,           ),
117
      ('basePortName',  r'\w+$',        None,           ),
118
      ('ram8',          None,           None,           ),
119
      ('ram32',         None,           None,           ),
120
      ('read',          r'I_\w+$',      None,           ),
121
      ('size',          r'\S+$',        validateSize,   ),
122
      ('write',         r'O_\w+$',      None,           ),
123
    );
124
    names = [a[0] for a in allowables];
125
    for param_tuple in param_list:
126
      param = param_tuple[0];
127
      if param not in names:
128
        raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
129
      param_test = allowables[names.index(param)];
130
      self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
131
    # Ensure the required parameters are provided.
132
    for paramname in (
133
      'address',
134
      'basePortName',
135
      'read',
136
      'write',
137
    ):
138
      if not hasattr(self,paramname):
139
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
140
    # Set optional parameters.
141
    for optionalpair in (
142
        ('size',        256,    ),
143
      ):
144
      if not hasattr(self,optionalpair[0]):
145
        setattr(self,optionalpair[0],optionalpair[1]);
146
    # Ensure exclusive pair configurations are set and consistent.
147
    for exclusivepair in (
148
        ('ram8','ram32','ram8',True,),
149
      ):
150
      if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
151
        raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
152
      if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]):
153
        setattr(self,exclusivepair[2],exclusivepair[3]);
154
    # Set the string used to identify signals associated with this peripheral.
155
    self.namestring = self.basePortName;
156
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
157
    for signal in (
158
      ( 'i_%s_aresetn',         1,                      'input',        ),
159
      ( 'i_%s_aclk',            1,                      'input',        ),
160
      ( 'i_%s_awvalid',         1,                      'input',        ),
161
      ( 'o_%s_awready',         1,                      'output',       ),
162
      ( 'i_%s_awaddr',          math.log(self.size,2),  'input',        ),
163
      ( 'i_%s_wvalid',          1,                      'input',        ),
164
      ( 'o_%s_wready',          1,                      'output',       ),
165
      ( 'i_%s_wdata',           32,                     'input',        ),
166
      ( 'i_%s_wstrb',           4,                      'input',        ),
167
      ( 'o_%s_bresp',           2,                      'output',       ),
168
      ( 'o_%s_bvalid',          1,                      'output',       ),
169
      ( 'i_%s_bready',          1,                      'input',        ),
170
      ( 'i_%s_arvalid',         1,                      'input',        ),
171
      ( 'o_%s_arready',         1,                      'output',       ),
172
      ( 'i_%s_araddr',          math.log(self.size,2),  'input',        ),
173
      ( 'o_%s_rvalid',          1,                      'output',       ),
174
      ( 'i_%s_rready',          1,                      'input',        ),
175
      ( 'o_%s_rdata',           32,                     'output',       ),
176
      ( 'o_%s_rresp',           2,                      'output',       ),
177
    ):
178
      thisName = signal[0] % self.basePortName;
179
      config.AddIO(thisName,signal[1],signal[2],loc);
180
    config.AddSignal('s__%s__mc_addr'  % self.namestring, int(math.log(self.size,2)), loc);
181
    config.AddSignal('s__%s__mc_rdata' % self.namestring, 8, loc);
182
    config.AddOutport((self.address,False,
183
                      ('s__%s__mc_addr' % self.namestring, int(math.log(self.size,2)), 'data', ),
184
                      ),loc);
185
    config.AddInport((self.read,
186
                      ('s__%s__mc_rdata' % self.namestring, 8, 'data', ),
187
                      ),loc);
188
    self.ix_write = config.NOutports();
189
    config.AddOutport((self.write,False,
190
                      # empty list
191
                      ),loc);
192
    # Add the 'clog2' function to the processor (if required).
193
    config.functions['clog2'] = True;
194
 
195
  def GenVerilog(self,fp,config):
196
    body = self.LoadCore(self.peripheralFile,'.v');
197
    for subpair in (
198
      (r'\bL__',        'L__@NAME@__',                  ),
199
      (r'\bgen__',      'gen__@NAME@__',                        ),
200
      (r'\bi_a',        'i_@NAME@_a',                           ),
201
      (r'\bi_b',        'i_@NAME@_b',                           ),
202
      (r'\bi_r',        'i_@NAME@_r',                           ),
203
      (r'\bi_w',        'i_@NAME@_w',                           ),
204
      (r'\bix__',       'ix__@NAME@__',                         ),
205
      (r'\bo_',         'o_@NAME@_',                            ),
206
      (r'\bs__',        's__@NAME@__',                          ),
207
      (r'@IX_WRITE@',   "8'h%02x" % self.ix_write,              ),
208
      (r'@NAME@',       self.namestring,                        ),
209
      (r'@SIZE@',       str(self.size),                         ),
210
      (r'@MEM8@',       '1' if hasattr(self,'mem8') else '0',   ),
211
    ):
212
      body = re.sub(subpair[0],subpair[1],body);
213
    body = self.GenVerilogFinal(config,body);
214
    fp.write(body);

powered by: WebSVN 2.1.0

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