I started using MyHDL a couple of weeks ago. It is a nice tool and I’m very happy with it. I only struggle with a problem. In a design I want to use a stored value in a register. This register is also an output. The design runs fine in MyHDL, but gives the following error when I export and run it in Verilog:
** ToVerilogWarning: Output port is read internally: outA
This error is understandable of course, but what is the right way to implement it?
To explain the problem better I made an example:
def blockA(clk,inA,outA):
@always(clk.posedge)
def logicBlockA():
outA.next = outA+inA
return logicBlockA
I also tried to add a buffer. This solves the error/warning, but the design still doesn’t work properly.
def blockA(clk,inA,outA):
out_temp = Signal(intbv(0)[bitW:])
@always(clk.posedge)
def logicBlockA():
out_temp.next = out_temp+inA
@always_comb
def logicBuf():
outA.next = out_temp
return logicBuf, logicBlockA
How to solve this problem? Thanks for your reply.
The warning is typically benign not sure the roots of the warning (I typically have numerous of these).
How is it not working correctly? Seems straightforward that you have a accumulator. What does your testbench output show?
Thanks for your reply cfelton.
The outputs of my testbench only shows 0, which is also the initial value of the signal.
For simulation of the Verilog code I use the Iverilog simulator.
Export Verilog
** ToVerilogWarning: Output port is read internally: outA
Run Verilog
Command # iverilog -o blockA blockA.v tb_blockA.v
Command # vvp -m ../myhdl.vpi blockA
Start Simulation
in out | correct out
--------------------------
0 0 | 0
1 0 | 1
2 0 | 3
3 0 | 6
4 0 | 10
5 0 | 15
6 0 | 21
7 0 | 28
8 0 | 36
9 0 | 45
simulation finished
Full code
#!/Users/MvL/anaconda/bin/python3
# -*- coding: utf-8 -*-
import os
from myhdl import *
bitW = 32
def ClkDriver(clk):
halfPeriod = delay(5)
@always(halfPeriod)
def driveClk():
clk.next = not clk
return driveClk
def blockA(clk,inA,outA):
@always(clk.posedge)
def logicBlockA():
outA.next = outA+inA
return logicBlockA
def blockB(clk,inA,outA):
out_temp = Signal(intbv(0)[bitW:])
@always(clk.posedge)
def logicBlockA():
out_temp.next = out_temp+inA
@always_comb
def logicBuf():
outA.next = out_temp
return logicBuf, logicBlockA
def blockAVerilog(clk,inA,outA):
print(" Run Verilog")
cmd = 'iverilog -o blockA blockA.v tb_blockA.v'
print(" Command #",cmd)
os.system(cmd)
cmd = 'vvp -m ../myhdl.vpi blockA'
print(" Command #",cmd)
return Cosimulation(cmd,clk=clk,inA=inA,outA=outA)
def exportVerilog():
clk = Signal(bool(0))
inA = Signal(intbv(0)[bitW:])
outA = Signal(intbv(0)[bitW:])
print(" Export Verilog")
toVerilog(blockA, clk, inA, outA)
def testBench(simVer):
clk = Signal(bool(0))
inA = Signal(intbv(0)[bitW:])
outA = Signal(intbv(0)[bitW:])
clkdriver_inst = ClkDriver(clk)
if simVer==1:
exportVerilog()
dut = blockAVerilog(clk,inA,outA)
else:
dut = blockA(clk,inA,outA)
print("\n Start Simulation")
print(" in out | correct out")
print("-"*26)
@instance
def stimulus():
result = 0
for i in range(0,10):
yield clk.posedge
inA.next = i
yield clk.negedge
result = i+result
print("{:>5d} {:>5d} | {:>5d}".format(int(inA),int(outA),result))
# stop simulation
print("simulation finished")
raise StopSimulation
return dut, stimulus, clkdriver_inst
if __name__ == "__main__":
simVer = 1 # Simulate with 0= MyHDL 1= Verilog
#tb = traceSignals(testBench)
sim = Simulation(testBench(simVer))
sim.run()
I should have asked this to start with, which version of myhdl are you using? If you are using the latest in the github master branch you will need the @block decorator.
I use the latest stable version of MyHDL, 0.9.
And for simulation Iverilog 10.0.
Is it better to use MyHDL 1.0 form Github?