这是pyverilog的demo代码
from __future__ import absolute_import
from __future__ import print_function
import sys
import os
import pyverilog.vparser.ast as vast
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
def main():
datawid = vast.Parameter( 'DATAWID', vast.Rvalue(vast.IntConst('32')) )
params = vast.Paramlist( [datawid] )
clk = vast.Ioport( vast.Input('CLK') )
rst = vast.Ioport( vast.Input('RST') )
width = vast.Width( vast.IntConst('7'), vast.IntConst('0') )
led = vast.Ioport( vast.Output('led', width=width) )
ports = vast.Portlist( [clk, rst, led] )
width = vast.Width( vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('1')), vast.IntConst('0') )
count = vast.Reg('count', width=width)
assign = vast.Assign(
vast.Lvalue(vast.Identifier('led')),
vast.Rvalue(
vast.Partselect(
vast.Identifier('count'), # count
vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('1')), # [DATAWID-1:
vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('8'))))) # :DATAWID-8]
sens = vast.Sens(vast.Identifier('CLK'), type='posedge')
senslist = vast.SensList([ sens ])
assign_count_true = vast.NonblockingSubstitution(
vast.Lvalue(vast.Identifier('count')),
vast.Rvalue(vast.IntConst('0')))
if0_true = vast.Block([ assign_count_true ])
# count + 1
count_plus_1 = vast.Plus(vast.Identifier('count'), vast.IntConst('1'))
assign_count_false = vast.NonblockingSubstitution(
vast.Lvalue(vast.Identifier('count')),
vast.Rvalue(count_plus_1))
if0_false = vast.Block([ assign_count_false ])
if0 = vast.IfStatement(vast.Identifier('RST'), if0_true, if0_false)
statement = vast.Block([ if0 ])
always = vast.Always(senslist, statement)
items = []
items.append(count)
items.append(assign)
items.append(always)
ast = vast.ModuleDef("top", params, ports, items)
codegen = ASTCodeGenerator()
rslt = codegen.visit(ast)
print(rslt)
if __name__ == '__main__':
main()
生成的verilog
module top #
(
parameter DATAWID = 32
)
(
input CLK,
input RST,
output [7:0] led
);
reg [DATAWID-1:0] count;
assign led = count[DATAWID-1:DATAWID-8];
always @(posedge CLK) begin
if(RST) begin
count <= 0;
end else begin
count <= count + 1;
end
end
endmodule
直接操作ast去生成代码是非常啰嗦的,更一般一点的方法是先写一段verilog,然后用它的parser得到ast之后再手动操作ast去实现一段更复杂的代码生成。但是依然很麻烦
同一个作者倒是有另一个项目叫veriloggen,但是我现在已经不写hdl了,没实际试一下效果如何,看demo还行:
from __future__ import absolute_import
from __future__ import print_function
import sys
import os
from veriloggen import *
def mkLed():
m = Module('blinkled')
width = m.Parameter('WIDTH', 8)
clk = m.Input('CLK')
rst = m.Input('RST')
led = m.OutputReg('LED', width, initval=0)
count = m.Reg('count', 32, initval=0)
seq = Seq(m, 'seq', clk, rst)
seq.If(count == 1024 - 1)(
count(0)
).Else(
count.inc()
)
seq.If(count == 1024 - 1)(
led.inc()
)
seq(
Systask('display', "LED:%d count:%d", led, count)
)
return m
def mkTest():
m = Module('test')
# target instance
led = mkLed()
uut = Submodule(m, led, name='uut')
clk = uut['CLK']
rst = uut['RST']
simulation.setup_waveform(m, uut, m.get_vars())
simulation.setup_clock(m, clk, hperiod=5)
init = simulation.setup_reset(m, rst, m.make_reset(), period=100)
init.add(
Delay(1000 * 100),
Systask('finish'),
)
return m
if __name__ == '__main__':
test = mkTest()
verilog = test.to_verilog(filename='tmp.v')
#verilog = test.to_verilog()
print(verilog)
sim = simulation.Simulator(test)
rslt = sim.run()
print(rslt)
# sim.view_waveform()
【 在 lvsoft 的大作中提到: 】
: 图灵完备的宏是一把难驾驭的双刃剑啊...c++就在眼前...
: 真很需要这样的东西可以直接meta programming...
: 接做到语言里不行吗?并不难实现的啊…
--
FROM 111.198.57.*