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 4

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 4 sinclairrf
      optionally specifies using a 32-bit RAM for the dual-port memory instantiation
50 3 sinclairrf
      Note:  This is required for Vivado 2013.3.\n
51
  Vivado Users:
52
    The peripheral creates a TCL script to facilitate turning the micro
53
    controller into an IP core.  Look for a file with the name
54
    "vivado_<basePortName>.tcl".\n
55 2 sinclairrf
  Example:  The code fragments
56
              <addr> .outport(O_address) .inport(I_read)
57
            and
58
              <addr> .outport(O_address) <value> .outport(O_write)
59
            will read from and write to the dual-port RAM.\n
60
  Example:  Function to read the byte at the specified address:
61
              ; ( u_addr - u_value)
62
              .function als_read
63
                .outport(O_address) .inport(I_read) .return
64
            or
65
              ; ( u_addr - u_value)
66
              .function als_read
67
                .outport(O_address) I_read .return(inport)
68
            To invoke the function:
69
              <addr> .call(als_read)
70
            or
71
              .call(als_read,<addr>)\n
72
  Example:  Function to write the byte at the specified address:
73
              ; ( u_value u_addr - )
74
              .function als_write
75
                .outport(O_address) O_write outport .return(drop)
76
            To invoke the function:
77
              <value> <addr> .call(als_write)
78
            or
79
              <value> .call(als_write,<addr>)\n
80
  Example:  Spin on an address, waiting for the host processor to write to the
81
            address, do something when the address is written to, and then
82
            clear its contents.
83
              0x00 .outport(O_address)
84
              :loop .inport(I_read) 0= .jumpc(loop)
85
              ; Avoid race conditions between the processor writes and the micro
86
              ; controller read.
87
              .inport(I_read)
88
              ...
89
              ; clear the value and start waiting again
90
              0x00 O_address outport O_write outport .jump(loop,drop)\n
91
  LEGAL NOTICE:  ARM has restrictions on what kinds of applications can use
92
  interfaces based on their AXI protocol.  Ensure your application is in
93
  compliance with their restrictions before using this peripheral for an AXI
94
  interface.
95
  """
96
 
97
  def __init__(self,peripheralFile,config,param_list,loc):
98
    # Use the externally provided file name for the peripheral
99
    self.peripheralFile = peripheralFile;
100
    # Get the parameters.
101
    def validateSize(x):
102
      if re.match(r'L_\w+$',x):
103
        if not config.IsParameter(x):
104
          raise SSBCCException('"size=%s" is not a parameter at %s' % (x,loc,));
105
        ix = [param[0] for param in config.parameters].index(x);
106
        y = config.parameters[ix][1];
107
        if not re.match(r'[1-9]\d*$', y):
108
          raise SSBCCException('localparam must be a numeric constant, not "%s", to be used in "size=%s" at %s' % (y,x,loc,));
109
        y = int(y);
110 4 sinclairrf
      elif re.match(r'C_\w+$',x):
111
        if not config.IsConstant(x):
112
          raise SSBCCException('"size=%s" is not a constant at %s' % (x,loc,));
113
        y = int(config.constants[x]);
114 2 sinclairrf
      elif re.match(r'[1-9]\d*$',x):
115
        y = int(x);
116
      else:
117
        raise SSBCCException('Malformed entry for "size=%s" at %s' % (x,loc,));
118
      if math.modf(math.log(y,2))[0] != 0:
119
        raise SSBCCException('size=%d must be a power of 2 at %s' % (y,loc,));
120
      if not (16 <= y <= 256):
121
        raise SSBCCException('size=%d must be between 16 and 256 inclusive at %s' % (y,loc,));
122
      return y;
123
    allowables = (
124
      ('address',       r'O_\w+$',      None,           ),
125
      ('basePortName',  r'\w+$',        None,           ),
126
      ('ram8',          None,           None,           ),
127
      ('ram32',         None,           None,           ),
128
      ('read',          r'I_\w+$',      None,           ),
129
      ('size',          r'\S+$',        validateSize,   ),
130
      ('write',         r'O_\w+$',      None,           ),
131
    );
132
    names = [a[0] for a in allowables];
133
    for param_tuple in param_list:
134
      param = param_tuple[0];
135
      if param not in names:
136
        raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
137
      param_test = allowables[names.index(param)];
138
      self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
139
    # Ensure the required parameters are provided.
140
    for paramname in (
141
      'address',
142
      'basePortName',
143
      'read',
144
      'write',
145
    ):
146
      if not hasattr(self,paramname):
147
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
148
    # Set optional parameters.
149
    for optionalpair in (
150
        ('size',        256,    ),
151
      ):
152
      if not hasattr(self,optionalpair[0]):
153
        setattr(self,optionalpair[0],optionalpair[1]);
154
    # Ensure exclusive pair configurations are set and consistent.
155
    for exclusivepair in (
156
        ('ram8','ram32','ram8',True,),
157
      ):
158
      if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
159
        raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
160
      if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]):
161
        setattr(self,exclusivepair[2],exclusivepair[3]);
162
    # Set the string used to identify signals associated with this peripheral.
163
    self.namestring = self.basePortName;
164
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
165 3 sinclairrf
    self.address_width = int(math.log(self.size,2));
166 2 sinclairrf
    for signal in (
167
      ( 'i_%s_aresetn',         1,                      'input',        ),
168
      ( 'i_%s_aclk',            1,                      'input',        ),
169
      ( 'i_%s_awvalid',         1,                      'input',        ),
170
      ( 'o_%s_awready',         1,                      'output',       ),
171 3 sinclairrf
      ( 'i_%s_awaddr',          self.address_width,     'input',        ),
172 2 sinclairrf
      ( 'i_%s_wvalid',          1,                      'input',        ),
173
      ( 'o_%s_wready',          1,                      'output',       ),
174
      ( 'i_%s_wdata',           32,                     'input',        ),
175
      ( 'i_%s_wstrb',           4,                      'input',        ),
176
      ( 'o_%s_bresp',           2,                      'output',       ),
177
      ( 'o_%s_bvalid',          1,                      'output',       ),
178
      ( 'i_%s_bready',          1,                      'input',        ),
179
      ( 'i_%s_arvalid',         1,                      'input',        ),
180
      ( 'o_%s_arready',         1,                      'output',       ),
181 3 sinclairrf
      ( 'i_%s_araddr',          self.address_width,     'input',        ),
182 2 sinclairrf
      ( 'o_%s_rvalid',          1,                      'output',       ),
183
      ( 'i_%s_rready',          1,                      'input',        ),
184
      ( 'o_%s_rdata',           32,                     'output',       ),
185
      ( 'o_%s_rresp',           2,                      'output',       ),
186
    ):
187
      thisName = signal[0] % self.basePortName;
188
      config.AddIO(thisName,signal[1],signal[2],loc);
189 3 sinclairrf
    config.AddSignal('s__%s__mc_addr'  % self.namestring, self.address_width, loc);
190 2 sinclairrf
    config.AddSignal('s__%s__mc_rdata' % self.namestring, 8, loc);
191
    config.AddOutport((self.address,False,
192 3 sinclairrf
                      ('s__%s__mc_addr' % self.namestring, self.address_width, 'data', ),
193 2 sinclairrf
                      ),loc);
194
    config.AddInport((self.read,
195
                      ('s__%s__mc_rdata' % self.namestring, 8, 'data', ),
196
                      ),loc);
197
    self.ix_write = config.NOutports();
198
    config.AddOutport((self.write,False,
199
                      # empty list
200
                      ),loc);
201
    # Add the 'clog2' function to the processor (if required).
202
    config.functions['clog2'] = True;
203
 
204
  def GenVerilog(self,fp,config):
205
    body = self.LoadCore(self.peripheralFile,'.v');
206
    for subpair in (
207
      (r'\bL__',        'L__@NAME@__',                  ),
208
      (r'\bgen__',      'gen__@NAME@__',                        ),
209
      (r'\bi_a',        'i_@NAME@_a',                           ),
210
      (r'\bi_b',        'i_@NAME@_b',                           ),
211
      (r'\bi_r',        'i_@NAME@_r',                           ),
212
      (r'\bi_w',        'i_@NAME@_w',                           ),
213
      (r'\bix__',       'ix__@NAME@__',                         ),
214
      (r'\bo_',         'o_@NAME@_',                            ),
215
      (r'\bs__',        's__@NAME@__',                          ),
216
      (r'@IX_WRITE@',   "8'h%02x" % self.ix_write,              ),
217
      (r'@NAME@',       self.namestring,                        ),
218
      (r'@SIZE@',       str(self.size),                         ),
219
      (r'@MEM8@',       '1' if hasattr(self,'mem8') else '0',   ),
220
    ):
221
      body = re.sub(subpair[0],subpair[1],body);
222
    body = self.GenVerilogFinal(config,body);
223
    fp.write(body);
224 3 sinclairrf
 
225
    # Write the TCL script to facilitate creating Vivado IP for the port.
226
    vivadoFile = os.path.join(os.path.dirname(self.peripheralFile),'vivado_AXI4_Lite_Bus.py');
227
    execfile(vivadoFile,globals());
228
    WriteTclScript('slave',self.basePortName,self.address_width);

powered by: WebSVN 2.1.0

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