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

Subversion Repositories tv80

[/] [tv80/] [trunk/] [scripts/] [reglib.py] - Blame information for rev 90

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

Line No. Rev Author Line
1 59 ghutchis
#!/usr/bin/env python
2
# Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
3
#
4
# Permission is hereby granted, free of charge, to any person obtaining a
5
# copy of this software and associated documentation files (the "Software"),
6
# to deal in the Software without restriction, including without limitation
7
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
# and/or sell copies of the Software, and to permit persons to whom the
9
# Software is furnished to do so, subject to the following conditions:
10
#
11
# The above copyright notice and this permission notice shall be included
12
# in all copies or substantial portions of the Software.
13
#
14
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
 
22 67 ghutchis
import string, math, re
23 59 ghutchis
 
24
def log2 (num):
25
    return math.ceil (math.log (num) / math.log (2))
26
 
27 67 ghutchis
# function that tries to interpret a number in Verilog notation
28
def number (str):
29
    try:
30
        robj = re.compile ("(\d+)'([dhb])([\da-fA-F]+)")
31
        mobj = robj.match (str)
32
        if (mobj):
33
            if mobj.group(2) == 'h': radix = 16
34
            elif mobj.group(2) == 'b': radix = 2
35
            else: radix = 10
36
 
37
            return int (mobj.group(3), radix)
38
        else:
39
            return int(str)
40
    except ValueError:
41
        print "ERROR: number conversion of %s failed" % str
42
        return 0
43
 
44 59 ghutchis
def comb_block (statements):
45
    result = 'always @*\n'
46
    result += '  begin\n'
47
    for s in statements:
48
        result += '    ' + s + '\n'
49
    result += '  end\n'
50
    return result
51
 
52
def seq_block (clock, statements):
53
    result = 'always @(posedge ' + clock + ')\n'
54
    result += '  begin\n'
55
    for s in statements:
56
        result += '    ' + s + '\n'
57
    result += '  end\n'
58
    return result
59
 
60
class net:
61
    def __init__ (self, type, name, width=1):
62
        self.width = width
63
        self.name  = name
64
        self.type  = type
65
 
66
    def declaration (self):
67
        if (self.width == 1):
68
            return self.type + ' ' + self.name + ';'
69
        else:
70
            return "%s [%d:0] %s;" % (self.type, self.width-1, self.name)
71
 
72
class port:
73
    def __init__ (self, direction, name, width=1):
74
        self.direction = direction
75
        self.width = width
76
        self.name = name
77
 
78
    def declaration (self):
79
        if (self.width == 1):
80
            return self.direction + ' ' + self.name + ';'
81
        else:
82
            return "%s [%d:0] %s;" % (self.direction, self.width-1, self.name)
83
 
84
class register_group:
85
    def __init__ (self, mem_mapped=0):
86
        self.base_addr = 0
87
        self.addr_size = 16
88
        self.data_size = 8
89
        self.name = ''
90
        self.local_width = 1
91
        self.registers = []
92
        self.ports = [port ('input', 'clk'), port('input','reset')]
93
        self.nets  = []
94 64 ghutchis
        self.interrupts = 0
95 59 ghutchis
        if (mem_mapped):
96
            self.req_pin = 'mreq_n'
97
        else:
98
            self.req_pin = 'iorq_n'
99
        self.tv80_intf()
100
 
101
    def tv80_intf (self):
102
        self.ports.append (port ('input', 'addr', self.addr_size))
103
        self.ports.append (port ('input', 'wr_data', self.data_size))
104
        self.ports.append (port ('output', 'rd_data', self.data_size))
105
        self.ports.append (port ('output', 'doe'))
106
        self.ports.append (port ('input','rd_n'))
107
        self.ports.append (port ('input', 'wr_n'))
108
        self.ports.append (port ('input', self.req_pin))
109 64 ghutchis
        self.nets.append (net('reg','rd_data',self.data_size))
110
        self.nets.append (net('reg','block_select'))
111
        self.nets.append (net('reg','doe'))
112 59 ghutchis
 
113 64 ghutchis
    # create a hook for post-processing to be done after all data has been
114
    # added to the object.
115
    def post (self):
116 67 ghutchis
        if (self.interrupts):
117
            self.int_ports()
118 64 ghutchis
 
119
    # create port for interrupt pin, as well as port for data output enable
120
    # when interrupt is asserted.
121
    # This block should be called after all register data has been read.
122
    def int_ports (self):
123
        self.ports.append (port ('output','int_n'))
124
        self.nets.append (net ('reg','int_n'))
125 67 ghutchis
        self.nets.append (net ('reg','int_vec',self.data_size))
126 64 ghutchis
 
127
    def int_logic (self):
128
        statements = []
129
        int_nets = []
130
        for r in self.registers:
131
            if r.interrupt: int_nets.append (r.name + "_int")
132
        statements.append ("int_n = ~(" + string.join (int_nets, ' | ') + ");")
133
        return comb_block (statements)
134
 
135 59 ghutchis
    def global_logic (self):
136
        # create select pin for this block
137
        statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)]
138
 
139
        # create read and write selects for each register
140
        for r in self.registers:
141 64 ghutchis
            slogic =  "block_select & (addr[%d:%d] == %d) & !rd_n" % (self.local_width-1,0,r.offset)
142 67 ghutchis
            #if r.interrupt:
143
            #    slogic = "%s_int | (%s)" % (r.name, slogic)
144 64 ghutchis
            s = "%s_rd_sel = %s;" % (r.name,slogic)
145 59 ghutchis
            statements.append (s)
146
            if r.write_cap():
147
                s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset)
148
                statements.append (s)
149
 
150
        return comb_block (statements)
151
 
152
    def read_mux (self):
153
        s = ''
154 64 ghutchis
        sments = []
155
        rd_sel_list = []
156
        # Old code for simple tri-state interface
157
        #for r in self.registers:
158
        #    s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size)
159
 
160 67 ghutchis
        # create interrupt address mux
161
        if (self.interrupts):
162
            sments.append ("case (1'b1)")
163
            for r in self.registers:
164
                if r.interrupt:
165
                    sments.append ("  %s_int : int_vec = %d;" % (r.name, r.int_value))
166
            sments.append ("  default : int_vec = %d'bx;" % self.data_size)
167
            sments.append ("endcase")
168
 
169
        # create data-output mux
170 64 ghutchis
        sments.append ("case (1'b1)")
171 59 ghutchis
        for r in self.registers:
172 64 ghutchis
            sments.append ("  %s_rd_sel : rd_data = %s;" % (r.name, r.name))
173
            rd_sel_list.append (r.name + "_rd_sel")
174 67 ghutchis
        if (self.interrupts):
175
            sments.append ("  default : rd_data = int_vec;")
176
        else: sments.append ("  default : rd_data = %d'bx;" % self.data_size)
177 64 ghutchis
        sments.append ("endcase")
178 59 ghutchis
 
179 64 ghutchis
        sments.append ("doe = %s;" % string.join (rd_sel_list, ' | '))
180
 
181
        return comb_block (sments)
182 59 ghutchis
 
183
 
184
    def verilog (self):
185 64 ghutchis
        self.post()
186
 
187 59 ghutchis
        result = 'module ' + self.name + ' (\n'
188
        result += string.join (map (lambda x: x.name, self.ports), ',')
189
        result += ');\n'
190
 
191
        # print port list
192
        for p in self.ports:
193
            result += p.declaration() + '\n'
194
 
195
        # print net list
196
        for n in self.nets:
197
            result += n.declaration() + '\n'
198
 
199
        # create global logic
200
        result += self.global_logic()
201
        result += self.read_mux()
202 64 ghutchis
        if (self.interrupts > 0): result += self.int_logic()
203 59 ghutchis
 
204
        # print function blocks
205
        for r in self.registers:
206
            result += r.verilog_body()
207
 
208 64 ghutchis
        result += 'endmodule\n'
209 59 ghutchis
        return result
210
 
211 64 ghutchis
    def add_register (self, type, params):
212
    #def add_register (self, name, type, width):
213 59 ghutchis
        if (type == 'status'):
214 64 ghutchis
            self.add (status_reg (params['name'],params['width']))
215 59 ghutchis
        elif (type == 'config'):
216 64 ghutchis
            self.add (config_reg (params['name'],params['width'],params['default']))
217
        elif (type == 'int_fixed'):
218
            r2 = config_reg (params['name'] + "_msk",params['width'],params['default'])
219 67 ghutchis
            r1 = int_fixed_reg (params['name'],r2,number(params['int_value']),params['width'])
220 64 ghutchis
            self.add (r1)
221
            self.add (r2)
222
            self.interrupts += 1
223
        elif (type == 'soft_set'):
224
            self.add (soft_set_reg(params['name'],params['width'],params['default']))
225
        elif (type == 'read_stb'):
226
            self.add (read_stb_reg (params['name'],params['width']))
227
        elif (type == 'write_stb'):
228 67 ghutchis
            self.add (write_stb_reg (params['name'],params['width'],params['default']))
229 90 ghutchis
        elif (type == 'hw_load'):
230
            self.add (hw_load_reg (params['name'],params['width']))
231 59 ghutchis
        else:
232
            print "Unknown register type",type
233 64 ghutchis
 
234 59 ghutchis
    def add (self, reg):
235
        self.registers.append (reg)
236
        self.ports.extend (reg.io())
237
        self.nets.extend (reg.nets())
238
        self.local_width = int(math.ceil (log2 (len (self.registers))))
239
        rnum = 0
240
        for r in self.registers:
241
            r.offset = rnum
242
            rnum += 1
243
 
244
class basic_register:
245
    def __init__ (self, name='', width=0):
246
        self.offset = 0
247
        self.width  = width
248
        self.name   = name
249 64 ghutchis
        self.interrupt = 0
250 59 ghutchis
 
251
    def verilog_body (self):
252
        pass
253
 
254
    def io (self):
255
        return []
256
 
257
    def nets (self):
258
        return []
259
 
260
    def write_cap (self):
261
        return 0
262
 
263 64 ghutchis
    def id_comment (self):
264
        return "// register: %s\n" % self.name
265
 
266 59 ghutchis
class status_reg (basic_register):
267
    def __init__ (self, name='', width=0):
268
        basic_register.__init__(self, name, width)
269
 
270
    def verilog_body (self):
271 64 ghutchis
        return ''
272 59 ghutchis
 
273
    def io (self):
274 64 ghutchis
        return [port('input', self.name, self.width)]
275 59 ghutchis
 
276
    def nets (self):
277 64 ghutchis
        return [ net('reg', self.name + '_rd_sel')]
278 59 ghutchis
 
279
class config_reg (basic_register):
280 64 ghutchis
    def __init__ (self, name='', width=0, default=0):
281 59 ghutchis
        basic_register.__init__(self, name, width)
282 64 ghutchis
        self.default = default
283 59 ghutchis
 
284
    def verilog_body (self):
285
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
286 64 ghutchis
                      "else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data')
287 59 ghutchis
                      ]
288 64 ghutchis
        return self.id_comment() + seq_block ('clk', statements)
289 59 ghutchis
 
290
    def io (self):
291
        return [ port('output',self.name, self.width) ]
292
 
293
    def nets (self):
294 64 ghutchis
        return [ net('reg', self.name, self.width),
295
                 net('reg', self.name + '_rd_sel'),
296
                 net('reg', self.name + '_wr_sel')]
297 59 ghutchis
 
298
    def write_cap (self):
299
        return 1
300 64 ghutchis
 
301 90 ghutchis
class hw_load_reg (config_reg):
302
    def __init__ (self, name='', width=0, default=0):
303
        basic_register.__init__(self, name, width)
304
        self.default = default
305
 
306
    def verilog_body (self):
307
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
308
                      "else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'),
309
                      "else if (%s_load) %s <= %s_wrdata;" % (self.name,self.name,self.name)
310
                      ]
311
        return self.id_comment() + seq_block ('clk', statements)
312
 
313
    def io (self):
314
        return [ port('input', self.name+'_wrdata', self.width),
315
                 port('input', self.name+'_load', 1),
316
                 port('output',self.name, self.width) ]
317
 
318
    def nets (self):
319
        return [ net('reg', self.name, self.width),
320
                 net('reg', self.name + '_rd_sel'),
321
                 net('reg', self.name + '_wr_sel')]
322
 
323
    def write_cap (self):
324
        return 1
325
 
326
 
327 64 ghutchis
class int_fixed_reg (basic_register):
328 67 ghutchis
    def __init__ (self, name, mask_reg, int_value, width=0):
329 64 ghutchis
        basic_register.__init__(self, name, width)
330
        self.mask_reg = mask_reg
331
        self.interrupt = 1
332 67 ghutchis
        self.int_value = int_value
333 64 ghutchis
 
334
    def verilog_body (self):
335
        statements = ["if (reset) %s <= %d;" % (self.name, 0),
336
                      "else %s <= (%s_set | %s) & ~( {%d{%s}} & %s);" %
337
                      (self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'wr_data'),
338
                      "if (reset) %s_int <= 0;" % self.name,
339
                      "else %s_int <= |(%s & ~%s);" % (self.name, self.name, self.mask_reg.name)
340
                      ]
341
        return self.id_comment() + seq_block ('clk', statements)
342
 
343
    def io (self):
344
        return [ port('input',self.name+"_set", self.width) ]
345
 
346
    def nets (self):
347
        return [ net('reg', self.name + '_rd_sel'),
348
                 net('reg', self.name, self.width),
349
                 net('reg', self.name + '_wr_sel'),
350
                 net('reg', self.name + '_int')]
351
 
352
    def write_cap (self):
353
        return 1
354
 
355
class soft_set_reg (basic_register):
356
    def __init__ (self, name='', width=0, default=0):
357
        basic_register.__init__(self, name, width)
358
        self.default = default
359
 
360
    def verilog_body (self):
361
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
362
                      "else %s <= ( ({%d{%s}} & %s) | %s) & ~(%s);" %
363
                            (self.name, self.width, self.name+'_wr_sel', 'wr_data',
364
                             self.name, self.name + '_clr')
365
                      ]
366
        return self.id_comment() + seq_block ('clk', statements)
367
 
368
    def io (self):
369
        return [ port('output',self.name, self.width),
370
                 port ('input',self.name+"_clr", self.width)]
371
 
372
    def nets (self):
373
        return [ net('reg', self.name, self.width),
374
                 net('reg', self.name + '_rd_sel'),
375
                 net('reg', self.name + '_wr_sel')]
376
 
377
    def write_cap (self):
378
        return 1
379
 
380
class write_stb_reg (config_reg):
381
    def __init__ (self, name='', width=0, default=0):
382
        config_reg.__init__(self, name, width, default)
383
 
384
    def verilog_body (self):
385
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
386
                      "else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'),
387
                      "if (reset) %s_stb <= 0;" % (self.name),
388 67 ghutchis
                      "else if (%s_wr_sel) %s_stb <= 1;" % (self.name, self.name),
389 64 ghutchis
                      "else %s_stb <= 0;" % (self.name)
390
                      ]
391
        return seq_block ('clk', statements)
392
 
393
    def io (self):
394
        io_list = config_reg.io (self)
395
        io_list.append ( port('output',self.name+"_stb") )
396
        return io_list
397
 
398
    def nets (self):
399
        net_list = config_reg.nets (self)
400
        net_list.append ( net('reg', self.name + "_stb") )
401
        return net_list
402
 
403
class read_stb_reg (status_reg):
404
    def __init__ (self, name='', width=0):
405
        status_reg.__init__(self, name, width)
406
 
407
    def verilog_body (self):
408
        statements = [
409
                      "if (reset) %s_stb <= 0;" % (self.name),
410
                      "else if (%s_rd_sel) %s_stb <= 1;" % (self.name, self.name),
411
                      "else %s_stb <= 0;" % (self.name)
412
                      ]
413
        return self.id_comment() + seq_block ('clk', statements)
414
 
415
    def io (self):
416
        io_list = status_reg.io (self)
417
        io_list.append (port('output',self.name+"_stb"))
418
        return io_list
419
 
420
    def nets (self):
421
        net_list = status_reg.nets(self)
422
        net_list.append (net('reg',self.name + '_stb'))
423
        return net_list

powered by: WebSVN 2.1.0

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