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

Subversion Repositories tv80

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

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
import string, math
23
 
24
def log2 (num):
25
    return math.ceil (math.log (num) / math.log (2))
26
 
27
def comb_block (statements):
28
    result = 'always @*\n'
29
    result += '  begin\n'
30
    for s in statements:
31
        result += '    ' + s + '\n'
32
    result += '  end\n'
33
    return result
34
 
35
def seq_block (clock, statements):
36
    result = 'always @(posedge ' + clock + ')\n'
37
    result += '  begin\n'
38
    for s in statements:
39
        result += '    ' + s + '\n'
40
    result += '  end\n'
41
    return result
42
 
43
class net:
44
    def __init__ (self, type, name, width=1):
45
        self.width = width
46
        self.name  = name
47
        self.type  = type
48
 
49
    def declaration (self):
50
        if (self.width == 1):
51
            return self.type + ' ' + self.name + ';'
52
        else:
53
            return "%s [%d:0] %s;" % (self.type, self.width-1, self.name)
54
 
55
class port:
56
    def __init__ (self, direction, name, width=1):
57
        self.direction = direction
58
        self.width = width
59
        self.name = name
60
 
61
    def declaration (self):
62
        if (self.width == 1):
63
            return self.direction + ' ' + self.name + ';'
64
        else:
65
            return "%s [%d:0] %s;" % (self.direction, self.width-1, self.name)
66
 
67
class register_group:
68
    def __init__ (self, mem_mapped=0):
69
        self.base_addr = 0
70
        self.addr_size = 16
71
        self.data_size = 8
72
        self.name = ''
73
        self.local_width = 1
74
        self.registers = []
75
        self.ports = [port ('input', 'clk'), port('input','reset')]
76
        self.nets  = []
77 64 ghutchis
        self.interrupts = 0
78 59 ghutchis
        if (mem_mapped):
79
            self.req_pin = 'mreq_n'
80
        else:
81
            self.req_pin = 'iorq_n'
82
        self.tv80_intf()
83
 
84
    def tv80_intf (self):
85
        self.ports.append (port ('input', 'addr', self.addr_size))
86
        self.ports.append (port ('input', 'wr_data', self.data_size))
87
        self.ports.append (port ('output', 'rd_data', self.data_size))
88
        self.ports.append (port ('output', 'doe'))
89
        self.ports.append (port ('input','rd_n'))
90
        self.ports.append (port ('input', 'wr_n'))
91
        self.ports.append (port ('input', self.req_pin))
92 64 ghutchis
        self.nets.append (net('reg','rd_data',self.data_size))
93
        self.nets.append (net('reg','block_select'))
94
        self.nets.append (net('reg','doe'))
95 59 ghutchis
 
96 64 ghutchis
    # create a hook for post-processing to be done after all data has been
97
    # added to the object.
98
    def post (self):
99
        self.int_ports()
100
 
101
    # create port for interrupt pin, as well as port for data output enable
102
    # when interrupt is asserted.
103
    # This block should be called after all register data has been read.
104
    def int_ports (self):
105
        self.ports.append (port ('output','int_n'))
106
        self.nets.append (net ('reg','int_n'))
107
 
108
    def int_logic (self):
109
        statements = []
110
        int_nets = []
111
        for r in self.registers:
112
            if r.interrupt: int_nets.append (r.name + "_int")
113
        statements.append ("int_n = ~(" + string.join (int_nets, ' | ') + ");")
114
        return comb_block (statements)
115
 
116 59 ghutchis
    def global_logic (self):
117
        # create select pin for this block
118
        statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)]
119
 
120
        # create read and write selects for each register
121
        for r in self.registers:
122 64 ghutchis
            slogic =  "block_select & (addr[%d:%d] == %d) & !rd_n" % (self.local_width-1,0,r.offset)
123
            if r.interrupt:
124
                slogic = "%s_int | (%s)" % (r.name, slogic)
125
            s = "%s_rd_sel = %s;" % (r.name,slogic)
126 59 ghutchis
            statements.append (s)
127
            if r.write_cap():
128
                s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset)
129
                statements.append (s)
130
 
131
        return comb_block (statements)
132
 
133
    def read_mux (self):
134
        s = ''
135 64 ghutchis
        sments = []
136
        rd_sel_list = []
137
        # Old code for simple tri-state interface
138
        #for r in self.registers:
139
        #    s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size)
140
 
141
        sments.append ("case (1'b1)")
142 59 ghutchis
        for r in self.registers:
143 64 ghutchis
            sments.append ("  %s_rd_sel : rd_data = %s;" % (r.name, r.name))
144
            rd_sel_list.append (r.name + "_rd_sel")
145
        sments.append ("  default : rd_data = %d'bx;" % self.data_size)
146
        sments.append ("endcase")
147 59 ghutchis
 
148 64 ghutchis
        sments.append ("doe = %s;" % string.join (rd_sel_list, ' | '))
149
 
150
        return comb_block (sments)
151 59 ghutchis
 
152
 
153
    def verilog (self):
154 64 ghutchis
        self.post()
155
 
156 59 ghutchis
        result = 'module ' + self.name + ' (\n'
157
        result += string.join (map (lambda x: x.name, self.ports), ',')
158
        result += ');\n'
159
 
160
        # print port list
161
        for p in self.ports:
162
            result += p.declaration() + '\n'
163
 
164
        # print net list
165
        for n in self.nets:
166
            result += n.declaration() + '\n'
167
 
168
        # create global logic
169
        result += self.global_logic()
170
        result += self.read_mux()
171 64 ghutchis
        if (self.interrupts > 0): result += self.int_logic()
172 59 ghutchis
 
173
        # print function blocks
174
        for r in self.registers:
175
            result += r.verilog_body()
176
 
177 64 ghutchis
        result += 'endmodule\n'
178 59 ghutchis
        return result
179
 
180 64 ghutchis
    def add_register (self, type, params):
181
    #def add_register (self, name, type, width):
182 59 ghutchis
        if (type == 'status'):
183 64 ghutchis
            self.add (status_reg (params['name'],params['width']))
184 59 ghutchis
        elif (type == 'config'):
185 64 ghutchis
            self.add (config_reg (params['name'],params['width'],params['default']))
186
        elif (type == 'int_fixed'):
187
            r2 = config_reg (params['name'] + "_msk",params['width'],params['default'])
188
            r1 = int_fixed_reg (params['name'],r2,params['width'])
189
            self.add (r1)
190
            self.add (r2)
191
            self.interrupts += 1
192
        elif (type == 'soft_set'):
193
            self.add (soft_set_reg(params['name'],params['width'],params['default']))
194
        elif (type == 'read_stb'):
195
            self.add (read_stb_reg (params['name'],params['width']))
196
        elif (type == 'write_stb'):
197
            self.add (config_reg (params['name'],params['width'],params['default']))
198 59 ghutchis
        else:
199
            print "Unknown register type",type
200 64 ghutchis
 
201 59 ghutchis
    def add (self, reg):
202
        self.registers.append (reg)
203
        self.ports.extend (reg.io())
204
        self.nets.extend (reg.nets())
205
        self.local_width = int(math.ceil (log2 (len (self.registers))))
206
        rnum = 0
207
        for r in self.registers:
208
            r.offset = rnum
209
            rnum += 1
210
 
211
class basic_register:
212
    def __init__ (self, name='', width=0):
213
        self.offset = 0
214
        self.width  = width
215
        self.name   = name
216 64 ghutchis
        self.interrupt = 0
217 59 ghutchis
 
218
    def verilog_body (self):
219
        pass
220
 
221
    def io (self):
222
        return []
223
 
224
    def nets (self):
225
        return []
226
 
227
    def write_cap (self):
228
        return 0
229
 
230 64 ghutchis
    def id_comment (self):
231
        return "// register: %s\n" % self.name
232
 
233 59 ghutchis
class status_reg (basic_register):
234
    def __init__ (self, name='', width=0):
235
        basic_register.__init__(self, name, width)
236
 
237
    def verilog_body (self):
238 64 ghutchis
        return ''
239 59 ghutchis
 
240
    def io (self):
241 64 ghutchis
        return [port('input', self.name, self.width)]
242 59 ghutchis
 
243
    def nets (self):
244 64 ghutchis
        return [ net('reg', self.name + '_rd_sel')]
245 59 ghutchis
 
246
class config_reg (basic_register):
247 64 ghutchis
    def __init__ (self, name='', width=0, default=0):
248 59 ghutchis
        basic_register.__init__(self, name, width)
249 64 ghutchis
        self.default = default
250 59 ghutchis
 
251
    def verilog_body (self):
252
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
253 64 ghutchis
                      "else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data')
254 59 ghutchis
                      ]
255 64 ghutchis
        return self.id_comment() + seq_block ('clk', statements)
256 59 ghutchis
 
257
    def io (self):
258
        return [ port('output',self.name, self.width) ]
259
 
260
    def nets (self):
261 64 ghutchis
        return [ net('reg', self.name, self.width),
262
                 net('reg', self.name + '_rd_sel'),
263
                 net('reg', self.name + '_wr_sel')]
264 59 ghutchis
 
265
    def write_cap (self):
266
        return 1
267 64 ghutchis
 
268
class int_fixed_reg (basic_register):
269
    def __init__ (self, name, mask_reg, width=0):
270
        basic_register.__init__(self, name, width)
271
        self.mask_reg = mask_reg
272
        self.interrupt = 1
273
 
274
    def verilog_body (self):
275
        statements = ["if (reset) %s <= %d;" % (self.name, 0),
276
                      "else %s <= (%s_set | %s) & ~( {%d{%s}} & %s);" %
277
                      (self.name, self.name, self.name, self.width, self.name + '_wr_sel', 'wr_data'),
278
                      "if (reset) %s_int <= 0;" % self.name,
279
                      "else %s_int <= |(%s & ~%s);" % (self.name, self.name, self.mask_reg.name)
280
                      ]
281
        return self.id_comment() + seq_block ('clk', statements)
282
 
283
    def io (self):
284
        return [ port('input',self.name+"_set", self.width) ]
285
 
286
    def nets (self):
287
        return [ net('reg', self.name + '_rd_sel'),
288
                 net('reg', self.name, self.width),
289
                 net('reg', self.name + '_wr_sel'),
290
                 net('reg', self.name + '_int')]
291
 
292
    def write_cap (self):
293
        return 1
294
 
295
class soft_set_reg (basic_register):
296
    def __init__ (self, name='', width=0, default=0):
297
        basic_register.__init__(self, name, width)
298
        self.default = default
299
 
300
    def verilog_body (self):
301
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
302
                      "else %s <= ( ({%d{%s}} & %s) | %s) & ~(%s);" %
303
                            (self.name, self.width, self.name+'_wr_sel', 'wr_data',
304
                             self.name, self.name + '_clr')
305
                      ]
306
        return self.id_comment() + seq_block ('clk', statements)
307
 
308
    def io (self):
309
        return [ port('output',self.name, self.width),
310
                 port ('input',self.name+"_clr", self.width)]
311
 
312
    def nets (self):
313
        return [ net('reg', self.name, self.width),
314
                 net('reg', self.name + '_rd_sel'),
315
                 net('reg', self.name + '_wr_sel')]
316
 
317
    def write_cap (self):
318
        return 1
319
 
320
class write_stb_reg (config_reg):
321
    def __init__ (self, name='', width=0, default=0):
322
        config_reg.__init__(self, name, width, default)
323
 
324
    def verilog_body (self):
325
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
326
                      "else if (%s_wr_sel) %s <= %s;" % (self.name, self.name, 'wr_data'),
327
                      "if (reset) %s_stb <= 0;" % (self.name),
328
                      "else if (%s_wr_sel) %s_stb <= 1;" % (self.name),
329
                      "else %s_stb <= 0;" % (self.name)
330
                      ]
331
        return seq_block ('clk', statements)
332
 
333
    def io (self):
334
        io_list = config_reg.io (self)
335
        io_list.append ( port('output',self.name+"_stb") )
336
        return io_list
337
 
338
    def nets (self):
339
        net_list = config_reg.nets (self)
340
        net_list.append ( net('reg', self.name + "_stb") )
341
        return net_list
342
 
343
class read_stb_reg (status_reg):
344
    def __init__ (self, name='', width=0):
345
        status_reg.__init__(self, name, width)
346
 
347
    def verilog_body (self):
348
        statements = [
349
                      "if (reset) %s_stb <= 0;" % (self.name),
350
                      "else if (%s_rd_sel) %s_stb <= 1;" % (self.name, self.name),
351
                      "else %s_stb <= 0;" % (self.name)
352
                      ]
353
        return self.id_comment() + seq_block ('clk', statements)
354
 
355
    def io (self):
356
        io_list = status_reg.io (self)
357
        io_list.append (port('output',self.name+"_stb"))
358
        return io_list
359
 
360
    def nets (self):
361
        net_list = status_reg.nets(self)
362
        net_list.append (net('reg',self.name + '_stb'))
363
        return net_list

powered by: WebSVN 2.1.0

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