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

Subversion Repositories tv80

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

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
        if (mem_mapped):
78
            self.req_pin = 'mreq_n'
79
        else:
80
            self.req_pin = 'iorq_n'
81
        self.tv80_intf()
82
 
83
    def tv80_intf (self):
84
        self.ports.append (port ('input', 'addr', self.addr_size))
85
        self.ports.append (port ('input', 'wr_data', self.data_size))
86
        self.ports.append (port ('output', 'rd_data', self.data_size))
87
        self.ports.append (port ('output', 'doe'))
88
        self.ports.append (port ('input','rd_n'))
89
        self.ports.append (port ('input', 'wr_n'))
90
        self.ports.append (port ('input', self.req_pin))
91
 
92
    def global_logic (self):
93
        # create select pin for this block
94
        self.nets.append (net('reg','block_select'))
95
        statements = ["block_select = (addr[%d:%d] == %d) & !%s;" % (self.addr_size-1,self.local_width,self.base_addr >> self.local_width, self.req_pin)]
96
 
97
        # create read and write selects for each register
98
        for r in self.registers:
99
            s = "%s_rd_sel = block_select & (addr[%d:%d] == %d) & !rd_n;" % (r.name,self.local_width-1,0,r.offset)
100
            statements.append (s)
101
            if r.write_cap():
102
                s = "%s_wr_sel = block_select & (addr[%d:%d] == %d) & !wr_n;" % (r.name,self.local_width-1,0,r.offset)
103
                statements.append (s)
104
 
105
        return comb_block (statements)
106
 
107
    def read_mux (self):
108
        s = ''
109
        for r in self.registers:
110
            s += "assign rd_data = (%s_rd_sel) ? %s : %d'bz;\n" % (r.name, r.name, self.data_size)
111
 
112
        return s
113
 
114
 
115
    def verilog (self):
116
        result = 'module ' + self.name + ' (\n'
117
        result += string.join (map (lambda x: x.name, self.ports), ',')
118
        result += ');\n'
119
 
120
        # print port list
121
        for p in self.ports:
122
            result += p.declaration() + '\n'
123
 
124
        # print net list
125
        for n in self.nets:
126
            result += n.declaration() + '\n'
127
 
128
        # create global logic
129
        result += self.global_logic()
130
        result += self.read_mux()
131
 
132
        # print function blocks
133
        for r in self.registers:
134
            result += r.verilog_body()
135
 
136
        result += 'endmodule;\n'
137
        return result
138
 
139
    def add_register (self, name, type, width):
140
        if (type == 'status'):
141
            self.add (status_reg (name,width))
142
        elif (type == 'config'):
143
            self.add (config_reg (name,width))
144
        else:
145
            print "Unknown register type",type
146
 
147
    def add (self, reg):
148
        self.registers.append (reg)
149
        self.ports.extend (reg.io())
150
        self.nets.extend (reg.nets())
151
        self.local_width = int(math.ceil (log2 (len (self.registers))))
152
        rnum = 0
153
        for r in self.registers:
154
            r.offset = rnum
155
            rnum += 1
156
 
157
class basic_register:
158
    def __init__ (self, name='', width=0):
159
        self.offset = 0
160
        self.width  = width
161
        self.name   = name
162
 
163
    def verilog_body (self):
164
        pass
165
 
166
    def io (self):
167
        return []
168
 
169
    def nets (self):
170
        return []
171
 
172
    def write_cap (self):
173
        return 0
174
 
175
class status_reg (basic_register):
176
    def __init__ (self, name='', width=0):
177
        basic_register.__init__(self, name, width)
178
 
179
    def verilog_body (self):
180
        pass
181
 
182
    def io (self):
183
        return [('input',self.width, self.name)]
184
 
185
    def nets (self):
186
        return [ net('reg', name + '_rd_sel')]
187
 
188
class config_reg (basic_register):
189
    def __init__ (self, name='', width=0):
190
        basic_register.__init__(self, name, width)
191
        self.default = 0
192
 
193
    def verilog_body (self):
194
        statements = ["if (reset) %s <= %d;" % (self.name, self.default),
195
                      "else if %s_wr_sel %s <= %s;" % (self.name, self.name, 'wr_data')
196
                      ]
197
        return seq_block ('clk', statements)
198
 
199
    def io (self):
200
        return [ port('output',self.name, self.width) ]
201
 
202
    def nets (self):
203
        return [ net('reg', self.name + '_rd_sel'), net('reg', self.name + '_wr_sel')]
204
 
205
    def write_cap (self):
206
        return 1
207
 

powered by: WebSVN 2.1.0

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