|
| 1 | +What's Pyverilog? |
| 2 | +============================== |
| 3 | + |
| 4 | +Pyverilog is open-source hardware design processing toolkit for Verilog HDL. |
| 5 | +All source codes are written in Python. |
| 6 | + |
| 7 | +Pyverilog includes **(1) code parser, (2) dataflow analyzer, (3) control-flow analyzer and (4) code generator**. |
| 8 | +You can create your own design analyzer, code translator and code generator of Verilog HDL based on this toolkit. |
| 9 | + |
| 10 | + |
| 11 | +Software Requirements |
| 12 | +============================== |
| 13 | + |
| 14 | +* Python (2.7, 3.3 or later) |
| 15 | +* Icarus Verilog (0.9.6 or later) |
| 16 | + - vparser.preprocessor.py uses 'iverilog -E' command instead of the preprocessor. |
| 17 | + - 'apt-get install iverilog' |
| 18 | +* Graphviz and Pygraphviz (Python3 does not support Pygraphviz) |
| 19 | + - graphgen.py in dataflow and controlflow.py in controlflow (without --nograph option) use Pygraphviz with Python 2.7. |
| 20 | + - If you do not use graphgen.py and controlflow.py (without --nograph) option, Python 3 is OK. |
| 21 | +* Jinja2 (2.7 or later) |
| 22 | + - ast\_code\_generator requires jinja2 module. |
| 23 | + - 'pip3 install jinja2' |
| 24 | + |
| 25 | + |
| 26 | +Tools |
| 27 | +============================== |
| 28 | + |
| 29 | +This software includes various tools for Verilog HDL design. |
| 30 | + |
| 31 | +* vparser: Code parser to generate AST (Abstract Syntax Tree) from source codes of Verilog HDL. |
| 32 | +* dataflow: Dataflow analyzer with an optimizer to remove redundant expressions and some dataflow handling tools. |
| 33 | +* controlflow: Control-flow analyzer with condition analyzer that identify when a signal is activated. |
| 34 | +* ast\_code\_generator: Verilog HDL code generator from AST. |
| 35 | + |
| 36 | + |
| 37 | +Getting Started |
| 38 | +============================== |
| 39 | + |
| 40 | +First, please prepare a Verilog HDL source file as below. The file name is 'test.v'. |
| 41 | +This sample design adds the input value internally whtn the enable signal is asserted. Then is outputs its partial value to the LED. |
| 42 | + |
| 43 | +```verilog |
| 44 | +module top |
| 45 | + ( |
| 46 | + input CLK, |
| 47 | + input RST, |
| 48 | + input enable, |
| 49 | + input [31:0] value, |
| 50 | + output [7:0] led |
| 51 | + ); |
| 52 | + reg [31:0] count; |
| 53 | + reg [7:0] state; |
| 54 | + assign led = count[23:16]; |
| 55 | + always @(posedge CLK) begin |
| 56 | + if(RST) begin |
| 57 | + count <= 0; |
| 58 | + state <= 0; |
| 59 | + end else begin |
| 60 | + if(state == 0) begin |
| 61 | + if(enable) state <= 1; |
| 62 | + end else if(state == 1) begin |
| 63 | + state <= 2; |
| 64 | + end else if(state == 2) begin |
| 65 | + count <= count + value; |
| 66 | + state <= 0; |
| 67 | + end |
| 68 | + end |
| 69 | + end |
| 70 | +endmodule |
| 71 | +``` |
| 72 | + |
| 73 | +Code parser |
| 74 | +------------------------------ |
| 75 | + |
| 76 | +Let's try syntax analysis. Please type the command as below. |
| 77 | + |
| 78 | +``` |
| 79 | +python3 pyverilog/vparser/parser.py test.v |
| 80 | +``` |
| 81 | + |
| 82 | +Then you got the result as below. The result of syntax analysis is displayed. |
| 83 | + |
| 84 | +``` |
| 85 | +Source: |
| 86 | + Description: |
| 87 | + ModuleDef: top |
| 88 | + Paramlist: |
| 89 | + Portlist: |
| 90 | + Ioport: |
| 91 | + Input: CLK, False |
| 92 | + Width: |
| 93 | + IntConst: 0 |
| 94 | + IntConst: 0 |
| 95 | + Ioport: |
| 96 | + Input: RST, False |
| 97 | + Width: |
| 98 | + IntConst: 0 |
| 99 | + IntConst: 0 |
| 100 | + Ioport: |
| 101 | + Input: enable, False |
| 102 | + Width: |
| 103 | + IntConst: 0 |
| 104 | + IntConst: 0 |
| 105 | + Ioport: |
| 106 | + Input: value, False |
| 107 | + Width: |
| 108 | + IntConst: 31 |
| 109 | + IntConst: 0 |
| 110 | + Ioport: |
| 111 | + Output: led, False |
| 112 | + Width: |
| 113 | + IntConst: 7 |
| 114 | + IntConst: 0 |
| 115 | + Decl: |
| 116 | + Reg: count, False |
| 117 | + Width: |
| 118 | + IntConst: 31 |
| 119 | + IntConst: 0 |
| 120 | + Decl: |
| 121 | + Reg: state, False |
| 122 | + Width: |
| 123 | + IntConst: 7 |
| 124 | + IntConst: 0 |
| 125 | + Assign: |
| 126 | + Lvalue: |
| 127 | + Identifier: led |
| 128 | + Rvalue: |
| 129 | + Partselect: |
| 130 | + Identifier: count |
| 131 | + IntConst: 23 |
| 132 | + IntConst: 16 |
| 133 | + Always: |
| 134 | + SensList: |
| 135 | + Sens: posedge |
| 136 | + Identifier: CLK |
| 137 | + Block: None |
| 138 | + IfStatement: |
| 139 | + Identifier: RST |
| 140 | + Block: None |
| 141 | + NonblockingSubstitution: |
| 142 | + Lvalue: |
| 143 | + Identifier: count |
| 144 | + Rvalue: |
| 145 | + IntConst: 0 |
| 146 | + NonblockingSubstitution: |
| 147 | + Lvalue: |
| 148 | + Identifier: state |
| 149 | + Rvalue: |
| 150 | + IntConst: 0 |
| 151 | + Block: None |
| 152 | + IfStatement: |
| 153 | + Eq: |
| 154 | + Identifier: state |
| 155 | + IntConst: 0 |
| 156 | + Block: None |
| 157 | + IfStatement: |
| 158 | + Identifier: enable |
| 159 | + NonblockingSubstitution: |
| 160 | + Lvalue: |
| 161 | + Identifier: state |
| 162 | + Rvalue: |
| 163 | + IntConst: 1 |
| 164 | + IfStatement: |
| 165 | + Eq: |
| 166 | + Identifier: state |
| 167 | + IntConst: 1 |
| 168 | + Block: None |
| 169 | + NonblockingSubstitution: |
| 170 | + Lvalue: |
| 171 | + Identifier: state |
| 172 | + Rvalue: |
| 173 | + IntConst: 2 |
| 174 | + IfStatement: |
| 175 | + Eq: |
| 176 | + Identifier: state |
| 177 | + IntConst: 2 |
| 178 | + Block: None |
| 179 | + NonblockingSubstitution: |
| 180 | + Lvalue: |
| 181 | + Identifier: count |
| 182 | + Rvalue: |
| 183 | + Plus: |
| 184 | + Identifier: count |
| 185 | + Identifier: value |
| 186 | + NonblockingSubstitution: |
| 187 | + Lvalue: |
| 188 | + Identifier: state |
| 189 | + Rvalue: |
| 190 | + IntConst: 0 |
| 191 | +``` |
| 192 | + |
| 193 | +Dataflow analyzer |
| 194 | +------------------------------ |
| 195 | + |
| 196 | +Let's try dataflow analysis. Please type the command as below. |
| 197 | + |
| 198 | +``` |
| 199 | +python3 pyverilog/dataflow/dataflow_analyzer.py -t top test.v |
| 200 | +``` |
| 201 | + |
| 202 | +Then you got the result as below. The result of each signal definition and each signal assignment are displayed. |
| 203 | + |
| 204 | +``` |
| 205 | +Directive: |
| 206 | +Instance: |
| 207 | +(top, 'top') |
| 208 | +Term: |
| 209 | +(Term name:top.led type:{'Output'} msb:(IntConst 7) lsb:(IntConst 0)) |
| 210 | +(Term name:top.enable type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 211 | +(Term name:top.CLK type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 212 | +(Term name:top.count type:{'Reg'} msb:(IntConst 31) lsb:(IntConst 0)) |
| 213 | +(Term name:top.state type:{'Reg'} msb:(IntConst 7) lsb:(IntConst 0)) |
| 214 | +(Term name:top.RST type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 215 | +(Term name:top.value type:{'Input'} msb:(IntConst 31) lsb:(IntConst 0)) |
| 216 | +Bind: |
| 217 | +(Bind dest:top.count tree:(Branch Cond:(Terminal top.RST) True:(IntConst 0) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 0)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 1)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 2)) True:(Operator Plus Next:(Terminal top.count),(Terminal top.value))))))) |
| 218 | +(Bind dest:top.state tree:(Branch Cond:(Terminal top.RST) True:(IntConst 0) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 0)) True:(Branch Cond:(Terminal top.enable) True:(IntConst 1)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 1)) True:(IntConst 2) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 2)) True:(IntConst 0)))))) |
| 219 | +(Bind dest:top.led tree:(Partselect Var:(Terminal top.count) MSB:(IntConst 23) LSB:(IntConst 16))) |
| 220 | +``` |
| 221 | + |
| 222 | +Let's view the result of dataflow analysis as a picture file. Now we select 'led' as the target. Please type the command as below. |
| 223 | + |
| 224 | +``` |
| 225 | +python3 pyverilog/dataflow/graphgen.py -t top -s top.led test.v |
| 226 | +``` |
| 227 | + |
| 228 | +Then you got a png file (out.png). The picture shows that the definition of 'led' is a part-selection of 'count' from 23-bit to 16-bit. |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | +Control-flow analyzer |
| 233 | +------------------------------ |
| 234 | + |
| 235 | +Let's try control-flow analysis. Please type the command as below. |
| 236 | + |
| 237 | +``` |
| 238 | +python2.7 pyverilog/controlflow/controlflow_analyzer.py -t top test.v |
| 239 | +``` |
| 240 | + |
| 241 | +Then you got the result as below. The result shows that the state machine structure and transition conditions to the next state in the state machine. |
| 242 | + |
| 243 | +``` |
| 244 | +FSM signal: top.count, Condition list length: 4 |
| 245 | +FSM signal: top.state, Condition list length: 5 |
| 246 | +Condition: (Ulnot, Eq), Inferring transition condition |
| 247 | +Condition: (Eq, top.enable), Inferring transition condition |
| 248 | +Condition: (Ulnot, Ulnot, Eq), Inferring transition condition |
| 249 | +# SIGNAL NAME: top.state |
| 250 | +# DELAY CNT: 0 |
| 251 | +0 --(top_enable>'d0)--> 1 |
| 252 | +1 --None--> 2 |
| 253 | +2 --None--> 0 |
| 254 | +Loop |
| 255 | +(0, 1, 2) |
| 256 | +``` |
| 257 | + |
| 258 | +You got also a png file (top_state.png). The picture shows that the graphical structure of the state machine. |
| 259 | + |
| 260 | + |
| 261 | + |
| 262 | +Code generator |
| 263 | +------------------------------ |
| 264 | + |
| 265 | +Finally, let's try code generation. Please prepare a Python script as below. The file name is 'test.py'. |
| 266 | +A Verilog HDL code is represented by using the AST classes defined in 'vparser.ast'. |
| 267 | + |
| 268 | +```python |
| 269 | +import pyverilog.vparser.ast as vast |
| 270 | +from pyverilog.ast_code_generator.codegen import ASTCodeGenerator |
| 271 | + |
| 272 | +params = vast.Paramlist(()) |
| 273 | +clk = vast.Ioport( vast.Input('CLK') ) |
| 274 | +rst = vast.Ioport( vast.Input('RST') ) |
| 275 | +width = vast.Width( vast.IntConst('7'), vast.IntConst('0') ) |
| 276 | +led = vast.Ioport( vast.Output('led', width=width) ) |
| 277 | +ports = vast.Portlist( (clk, rst, led) ) |
| 278 | +items = ( vast.Assign( vast.Identifier('led'), vast.IntConst('8') ) ,) |
| 279 | +ast = vast.ModuleDef("top", params, ports, items) |
| 280 | + |
| 281 | +codegen = ASTCodeGenerator() |
| 282 | +rslt = codegen.visit(ast) |
| 283 | +print(rslt) |
| 284 | +``` |
| 285 | + |
| 286 | +Please type the command as below at the same directory with Pyverilog. |
| 287 | + |
| 288 | +``` |
| 289 | +python3 test.py |
| 290 | +``` |
| 291 | + |
| 292 | +Then Verilog HDL code generated from the AST instances is displayed. |
| 293 | + |
| 294 | +```verilog |
| 295 | +
|
| 296 | +module top |
| 297 | + ( |
| 298 | + input [0:0] CLK, |
| 299 | +input [0:0] RST, |
| 300 | +output [7:0] led |
| 301 | +
|
| 302 | + ); |
| 303 | + assign led = 8; |
| 304 | +endmodule |
| 305 | +
|
| 306 | +``` |
| 307 | + |
| 308 | + |
| 309 | +Related Project and Site |
| 310 | +============================== |
| 311 | + |
| 312 | +[PyCoRAM](http://shtaxxx.github.io/PyCoRAM/) |
| 313 | +- Python-based Implementation of CoRAM Memory Architecture for AXI4 Interconnection on FPGAs |
| 314 | + |
| 315 | +[shtaxxx.hatenablog.com](http://shtaxxx.hatenablog.com/entry/2014/01/01/045856) |
| 316 | +- Blog entry for introduction and examples of Pyverilog (in Japansese) |
| 317 | + |
| 318 | + |
| 319 | +License |
| 320 | +============================== |
| 321 | + |
| 322 | +Apache License 2.0 |
| 323 | +(http://www.apache.org/licenses/LICENSE-2.0) |
| 324 | + |
| 325 | +This software package includes PLY-3.4. |
| 326 | +The license of PLY is BSD. |
| 327 | + |
| 328 | + |
| 329 | +Copyright and Contact |
| 330 | +============================== |
| 331 | + |
| 332 | +Copyright (C) 2013, Shinya Takamaeda-Yamazaki |
| 333 | + |
| 334 | +E-mail: takamaeda\_at\_arch.cs.titech.ac.jp |
| 335 | + |
0 commit comments