hi,
I’m using iCE40 parts, and also want seamless transition from sim to synth. I pass ‘SynType’ as an optional parameter through the design to select simulation or conversion for use in library parts etc.
I do not like the extra level of nesting, but have not recently found a way to work without it. Having some working code is good for now.
""" SB_RGBA_DRV.py """
from myhdl import *
@block
def SB_RGBA_DRV_Sim( \
RGBLEDEN,
RGB0PWM, RGB1PWM, RGB2PWM,
CURREN,
RGB0, RGB1, RGB2,
):
@always_comb
def PWMsimLogic():
RGB0.next = RGB0PWM
RGB1.next = RGB1PWM
RGB2.next = RGB2PWM
return PWMsimLogic
@block
def SB_RGBA_DRV_Inst( \
RGBLEDEN,
RGB0PWM, RGB1PWM, RGB2PWM,
CURREN,
RGB0, RGB1, RGB2,
):
''' Instantiation of library part SB_RGBA_DRV '''
RGB0_CURRENT = "0b000001"
RGB1_CURRENT = "0b000001"
RGB2_CURRENT = "0b000001"
@always()
def logic():
pass
RGB0.driven = "wire"
RGB1.driven = "wire"
RGB2.driven = "wire"
RGB0PWM.read = True
RGB1PWM.read = True
RGB2PWM.read = True
return logic
SB_RGBA_DRV_Inst.verilog_code = \
"""
// Instantiation of library part
SB_RGBA_DRV SB_RGBA_DRV_01 (
.RGBLEDEN (1'b1),
.RGB0PWM ($RGB0PWM), // green
.RGB1PWM ($RGB1PWM), // blue
.RGB2PWM ($RGB2PWM), // red
.CURREN (1'b1),
.RGB0 (GRNn), // green on UPDuino v2.0 Board
.RGB1 (BLUn), // blue
.RGB2 (REDn) // red
);
defparam SB_RGBA_DRV_01.RGB0_CURRENT = "$RGB0_CURRENT"; // "0b000001";
defparam SB_RGBA_DRV_01.RGB1_CURRENT = "$RGB1_CURRENT";
defparam SB_RGBA_DRV_01.RGB2_CURRENT = "$RGB2_CURRENT";
"""
SB_RGBA_DRV_Inst.VHDL_code = """ \
-- Instantiation of library part
SB_RGBA_DRV: SB_RGBA_DRV_01
--generic map(
-- RGB0_CURRENT => "$RGB0_CURRENT"; -- "0b000001",
-- RGB1_CURRENT => "$RGB0_CURRENT",
-- RGB2_CURRENT => "$RGB0_CURRENT";
port map(
RGBLEDEN -> (1'b1),
RGB0PWM -> ($RGB0PWM), -- green
RGB1PWM -> ($RGB1PWM), -- blue
RGB2PWM -> ($RGB2PWM), -- red
CURREN -> (1'b1),
RGB0 -> (GRNn), -- green on UPDuino v2.0 Board
RGB1 -> (BLUn), -- blue
RGB2 -> (REDn) -- red
);
"""
@block
def SB_RGBA_DRV( \
RGBLEDEN,
RGB0PWM, RGB1PWM, RGB2PWM,
CURREN,
RGB0, RGB1, RGB2,
SynType ):
''' SiBlu library part SB_RGBA_DRV '''
if SynType=="Sim": mySB_RGBA_DRV = SB_RGBA_DRV_Sim
else: mySB_RGBA_DRV = SB_RGBA_DRV_Inst
RGBdrv01 = mySB_RGBA_DRV( \
1, RGB0PWM, RGB1PWM, RGB2PWM,
1, RGB0, RGB1, RGB2, )
return RGBdrv01
This is working, but incomplete: the LED is fixed at minimum drive current. Also, the project VHDL export is not working.
This uninitialized RAM model works without extra symbolic indirection, and the demo project exports Verilog and VHDL. (No hardware test yet)
""" SB_RAM256X16_2013-08-28.py
2018-11-02 jc changed "(% s)" substitution to "$" type
"""
from myhdl import *
from random import randint
RdLatency = 3
@block
def SB_RAM256X16(RDATA, RADDR, RCLK, RCLKE, RE, \
WADDR, WCLK, WCLKE, WDATA, WE, MASK, SynType ):
''' sim & synth version of iCE40 block RAM '''
mem = [ Signal(intbv(0x5555)[16:]) for ii in range(256)]
RData_RClk = Signal(intbv(0)[16:])
@always(RCLK.posedge)
def RData_RClkLogic():
if ((RCLKE==1) and (RE==1)):
RData_RClk.next = mem[int(RADDR)]
@always(delay(RdLatency))
def RDATAlogic():
RDATA.next = RData_RClk
WData_WClk = Signal(intbv(0)[16:])
WAddr_WClk = Signal(intbv(0)[8:])
WEtm1, WEtm2 = [Signal(bool(0)) for ii in range(2)]
@always(WCLK.posedge)
def WEtm1Logic():
''' WEtm1 WEtm2 write process timing '''
WEtm1.next = WE & WCLKE
WEtm2.next = WEtm1
@always(WCLK.posedge)
def WData_WClkLogic():
if WCLKE & WEtm1:
WData_WClk.next = WDATA
WAddr_WClk.next = WADDR
@always(WCLK.posedge)
def WriteLogic():
if WEtm1 & WEtm2 & WCLKE & WE:
mem[int(WADDR)].next = \
(~MASK & WDATA) | (MASK & mem[WADDR])
#mem[int(WADDR)].next = WDATA
@always()
def NoLogic():
''' empty logic '''
pass
''' connection assurance '''
RDATA.driven = "wire"
RADDR.read = True
RCLK.read = True
RCLKE.read = True
RE.read = True
WADDR.read = True
WCLK.read = True
WCLKE.read = True
WDATA.read = True
WE.read = True
MASK.read = True # may cause trouble?
SB_RAM256X16.verilog_code = \
"""// iCE40 Library Part \\\\
SB_RAM256x16 SB_RAM256X16inst(
.RDATA($RDATA),
.RADDR($RADDR),
.RCLK($RCLK),
.RCLKE($RCLKE),
.RE($RE),
.WADDR($WADDR),
.WCLK($WCLK),
.WCLKE($WCLKE),
.WDATA($WDATA),
.WE($WE),
.MASK($MASK)
);
"""
SB_RAM256X16.vhdl_code = \
"""-- iCE40 Library Part --
RAM256X16: SB_RAM256X16
port map(
RDATA => $RDATA,
RADDR => $RADDR,
RCLK => $RCLK,
RCLKE => $RCLKE,
RE => $RE,
WADDR => $WADDR,
WCLK=> $WCLK,
WCLKE => $WCLKE,
WDATA => $WDATA,
MASK => $MASK,
WE => $WE
);
"""
if SynType=='Sim':
return RData_RClkLogic, RDATAlogic, WEtm1Logic, \
WData_WClkLogic, WriteLogic
else:
return NoLogic
There are other library parts which are working but incomplete, including an initialized RAM.
Jan Coombs