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 3

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 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
      elif re.match(r'[1-9]\d*$',x):
111
        y = int(x);
112
      else:
113
        raise SSBCCException('Malformed entry for "size=%s" at %s' % (x,loc,));
114
      if math.modf(math.log(y,2))[0] != 0:
115
        raise SSBCCException('size=%d must be a power of 2 at %s' % (y,loc,));
116
      if not (16 <= y <= 256):
117
        raise SSBCCException('size=%d must be between 16 and 256 inclusive at %s' % (y,loc,));
118
      return y;
119
    allowables = (
120
      ('address',       r'O_\w+$',      None,           ),
121
      ('basePortName',  r'\w+$',        None,           ),
122
      ('ram8',          None,           None,           ),
123
      ('ram32',         None,           None,           ),
124
      ('read',          r'I_\w+$',      None,           ),
125
      ('size',          r'\S+$',        validateSize,   ),
126
      ('write',         r'O_\w+$',      None,           ),
127
    );
128
    names = [a[0] for a in allowables];
129
    for param_tuple in param_list:
130
      param = param_tuple[0];
131
      if param not in names:
132
        raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
133
      param_test = allowables[names.index(param)];
134
      self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
135
    # Ensure the required parameters are provided.
136
    for paramname in (
137
      'address',
138
      'basePortName',
139
      'read',
140
      'write',
141
    ):
142
      if not hasattr(self,paramname):
143
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
144
    # Set optional parameters.
145
    for optionalpair in (
146
        ('size',        256,    ),
147
      ):
148
      if not hasattr(self,optionalpair[0]):
149
        setattr(self,optionalpair[0],optionalpair[1]);
150
    # Ensure exclusive pair configurations are set and consistent.
151
    for exclusivepair in (
152
        ('ram8','ram32','ram8',True,),
153
      ):
154
      if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
155
        raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
156
      if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]):
157
        setattr(self,exclusivepair[2],exclusivepair[3]);
158
    # Set the string used to identify signals associated with this peripheral.
159
    self.namestring = self.basePortName;
160
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
161 3 sinclairrf
    self.address_width = int(math.log(self.size,2));
162 2 sinclairrf
    for signal in (
163
      ( 'i_%s_aresetn',         1,                      'input',        ),
164
      ( 'i_%s_aclk',            1,                      'input',        ),
165
      ( 'i_%s_awvalid',         1,                      'input',        ),
166
      ( 'o_%s_awready',         1,                      'output',       ),
167 3 sinclairrf
      ( 'i_%s_awaddr',          self.address_width,     'input',        ),
168 2 sinclairrf
      ( 'i_%s_wvalid',          1,                      'input',        ),
169
      ( 'o_%s_wready',          1,                      'output',       ),
170
      ( 'i_%s_wdata',           32,                     'input',        ),
171
      ( 'i_%s_wstrb',           4,                      'input',        ),
172
      ( 'o_%s_bresp',           2,                      'output',       ),
173
      ( 'o_%s_bvalid',          1,                      'output',       ),
174
      ( 'i_%s_bready',          1,                      'input',        ),
175
      ( 'i_%s_arvalid',         1,                      'input',        ),
176
      ( 'o_%s_arready',         1,                      'output',       ),
177 3 sinclairrf
      ( 'i_%s_araddr',          self.address_width,     'input',        ),
178 2 sinclairrf
      ( 'o_%s_rvalid',          1,                      'output',       ),
179
      ( 'i_%s_rready',          1,                      'input',        ),
180
      ( 'o_%s_rdata',           32,                     'output',       ),
181
      ( 'o_%s_rresp',           2,                      'output',       ),
182
    ):
183
      thisName = signal[0] % self.basePortName;
184
      config.AddIO(thisName,signal[1],signal[2],loc);
185 3 sinclairrf
    config.AddSignal('s__%s__mc_addr'  % self.namestring, self.address_width, loc);
186 2 sinclairrf
    config.AddSignal('s__%s__mc_rdata' % self.namestring, 8, loc);
187
    config.AddOutport((self.address,False,
188 3 sinclairrf
                      ('s__%s__mc_addr' % self.namestring, self.address_width, 'data', ),
189 2 sinclairrf
                      ),loc);
190
    config.AddInport((self.read,
191
                      ('s__%s__mc_rdata' % self.namestring, 8, 'data', ),
192
                      ),loc);
193
    self.ix_write = config.NOutports();
194
    config.AddOutport((self.write,False,
195
                      # empty list
196
                      ),loc);
197
    # Add the 'clog2' function to the processor (if required).
198
    config.functions['clog2'] = True;
199
 
200
  def GenVerilog(self,fp,config):
201
    body = self.LoadCore(self.peripheralFile,'.v');
202
    for subpair in (
203
      (r'\bL__',        'L__@NAME@__',                  ),
204
      (r'\bgen__',      'gen__@NAME@__',                        ),
205
      (r'\bi_a',        'i_@NAME@_a',                           ),
206
      (r'\bi_b',        'i_@NAME@_b',                           ),
207
      (r'\bi_r',        'i_@NAME@_r',                           ),
208
      (r'\bi_w',        'i_@NAME@_w',                           ),
209
      (r'\bix__',       'ix__@NAME@__',                         ),
210
      (r'\bo_',         'o_@NAME@_',                            ),
211
      (r'\bs__',        's__@NAME@__',                          ),
212
      (r'@IX_WRITE@',   "8'h%02x" % self.ix_write,              ),
213
      (r'@NAME@',       self.namestring,                        ),
214
      (r'@SIZE@',       str(self.size),                         ),
215
      (r'@MEM8@',       '1' if hasattr(self,'mem8') else '0',   ),
216
    ):
217
      body = re.sub(subpair[0],subpair[1],body);
218
    body = self.GenVerilogFinal(config,body);
219
    fp.write(body);
220 3 sinclairrf
 
221
    # Write the TCL script to facilitate creating Vivado IP for the port.
222
    vivadoFile = os.path.join(os.path.dirname(self.peripheralFile),'vivado_AXI4_Lite_Bus.py');
223
    execfile(vivadoFile,globals());
224
    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.