Improved rolled VHDL code generation. This is only active when using

GHDL as simulator. It's based on VHDL generators.

Using Icarus Verilog for VHDL synthesis is still in an early stage, and
the tool is not able to handle arrays. Thus, the generated VHDL code is
always completely unrolled
parent 5fd91c12
......@@ -162,6 +162,11 @@ class Filter():
rp = rp, rs = rs,
btype = btype,
ftype = ftype)
elif filterMethod == 'Manual':
# TODO: Validator needed
b = np.fromstring(str(self.textManualCoeffB.toPlainText()), sep=',')
a = np.fromstring(str(self.textManualCoeffA.toPlainText()), sep=',')
......@@ -182,6 +187,8 @@ class Filter():
if filterMethod == 'FIR 1':
flagManualCoeffA = False
flagManualCoeffB = False
flagFIRWindow = True
flagNumtaps = True
flagCutoff = True
......@@ -216,6 +223,8 @@ class Filter():
self.cbPassZero.setEnabled(True)
elif filterMethod == 'FIR 2':
flagManualCoeffA = False
flagManualCoeffB = False
flagFIRWindow = True
flagNumtaps = True
flagCutoff = False
......@@ -238,6 +247,8 @@ class Filter():
flagBType = False
elif filterMethod == 'IIR 1':
flagManualCoeffA = False
flagManualCoeffB = False
flagFIRWindow = False
flagNumtaps = False
flagCutoff = False
......@@ -260,6 +271,8 @@ class Filter():
flagBType = False
elif filterMethod == 'IIR 2':
flagManualCoeffA = False
flagManualCoeffB = False
flagFIRWindow = False
flagNumtaps = False
flagCutoff = False
......@@ -286,12 +299,44 @@ class Filter():
flagRp = False
flagRs = False
flagBType = True
elif filterMethod == 'Manual':
flagManualCoeffA = True
flagManualCoeffB = True
flagFIRWindow = False
flagNumtaps = False
flagCutoff = False
flagWidth = False
flagPassZero = False
flagScale = False
flagFrequency = False
flagGain = False
flagAntisymmetric = False
flagIIRMethod = False
flagWp = False
flagWs = False
flagGpass = False
flagGstop = False
flagOrder = False
flagOrder = False
flagWn = False
flagRp = False
flagRs = False
flagBType = False
else :
print('Not recognized filter description method')
# TODO: this is ugly, should be compacted in a cleaner structure!!
self.labelManualCoeffB.setVisible(flagManualCoeffB)
self.textManualCoeffB.setVisible(flagManualCoeffB)
self.labelManualCoeffA.setVisible(flagManualCoeffA)
self.textManualCoeffA.setVisible(flagManualCoeffA)
self.labelFIRWindow.setVisible(flagFIRWindow)
self.comboFIRWindow.setVisible(flagFIRWindow)
......@@ -524,6 +569,7 @@ class Filter():
self.comboResponseType.addItem("IIR 1") # scipy.signal.iirdesign
# TODO: this IIR 2 filter causes undetected problems!! We disable this
self.comboResponseType.addItem("IIR 2") # scipy.signal.iirfilter
self.comboResponseType.addItem("Manual") # define the coeff by hand
self.comboResponseType.setEditable(True)
self.comboResponseType.lineEdit().setReadOnly(True)
self.comboResponseType.lineEdit().setAlignment(Qt.AlignRight)
......@@ -533,6 +579,19 @@ class Filter():
self.connect(self.comboResponseType, SIGNAL('currentIndexChanged(int)'), self.on_parameter_change)
# Manual configuration
self.labelManualCoeffB = QLabel('B Coeff:')
self.textManualCoeffB = QTextEdit()
self.textManualCoeffB.setText('1')
self.connect(self.textManualCoeffB, SIGNAL('textChanged()'), self.update_parameter_set)
self.connect(self.textManualCoeffB, SIGNAL('textChanged()'), self.on_parameter_change)
self.labelManualCoeffA = QLabel('A Coeff:')
self.textManualCoeffA = QTextEdit()
self.textManualCoeffA.setText('1')
self.connect(self.textManualCoeffA, SIGNAL('textChanged()'), self.update_parameter_set)
self.connect(self.textManualCoeffA, SIGNAL('textChanged()'), self.on_parameter_change)
# The Elements for filter configuration are:
......@@ -805,6 +864,18 @@ class Filter():
hboxResponseType.addWidget(self.comboResponseType)
hboxResponseType.setStretch(0,1)
hboxResponseType.setStretch(1,1)
hboxManualCoeffB = QHBoxLayout()
hboxManualCoeffB.addWidget(self.labelManualCoeffB)
hboxManualCoeffB.addWidget(self.textManualCoeffB)
hboxManualCoeffB.setStretch(0,1)
hboxManualCoeffB.setStretch(1,1)
hboxManualCoeffA = QHBoxLayout()
hboxManualCoeffA.addWidget(self.labelManualCoeffA)
hboxManualCoeffA.addWidget(self.textManualCoeffA)
hboxManualCoeffA.setStretch(0,1)
hboxManualCoeffA.setStretch(1,1)
hboxFIRWindow = QHBoxLayout()
hboxFIRWindow.addWidget(self.labelFIRWindow)
......@@ -928,7 +999,8 @@ class Filter():
vboxFilterParameters = QVBoxLayout()
for parameterLayout in (hboxResponseType, hboxFIRWindow,
for parameterLayout in (hboxResponseType, hboxFIRWindow,
hboxManualCoeffB, hboxManualCoeffA,
hboxNumtaps, hboxCutoff,
hboxWidth, hboxPassZero, hboxScale,
hboxFrequency, hboxGain, hboxAntisymmetric,
......
# This file is part of librefdatool. librefdatool is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
# This file is part of Libre-FDATool.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
# Libre-FDATool is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Libre-FDATool is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Libre-FDATool. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2013 Javier D. Garcia-Lasheras
......@@ -76,6 +78,9 @@ class LibreFDATool(
self.simulatorBeginSignal.connect(self.on_simulator_begin)
self.simulatorEndSignal.connect(self.on_simulator_end)
# Choose GHDL as default
self.comboSimulatorEngine.setCurrentIndex(1)
self.runSimulator()
self.main_frame.setCurrentIndex(0)
......
......@@ -126,6 +126,13 @@ class Simcore:
structure = self.structure
name = self.name
# TODO: temporary assign of style depending on engine
if self.engine == 'GHDL':
style = 'rolled'
elif self.engine == 'Icarus Verilog':
style = 'unrolled'
# Code generation for a Transposed Direct Form FIR
hdlFile = open('{!s}.vhd'.format(name),'w')
......@@ -136,56 +143,56 @@ class Simcore:
hdlFile.write(hdl.entity(name, busX, busY))
hdlFile.write('\n')
hdlFile.write(hdl.architectureHeader(name, structure))
hdlFile.write(hdl.architectureHeader(name, structure, style=style))
hdlFile.write('\n')
# *** DECLARE INTERNAL SIGNALS ***
hdlFile.write(hdl.signalZ(self.M, self.N, busX, busY, busC, structure))
hdlFile.write(hdl.signalZ(self.M, self.N, busX, busY, busC, structure, style=style))
hdlFile.write('\n')
hdlFile.write(hdl.signalC(self.M, self.N, busC, structure))
hdlFile.write(hdl.signalC(self.M, self.N, busC, structure, style=style))
hdlFile.write('\n')
hdlFile.write(hdl.signalAdders(self.M, self.N, busX, busY, busC, structure))
hdlFile.write(hdl.signalAdders(self.M, self.N, busX, busY, busC, structure, style=style))
hdlFile.write('\n')
hdlFile.write(hdl.signalProducts(self.M, self.N, busX, busY, busC, structure))
hdlFile.write(hdl.signalProducts(self.M, self.N, busX, busY, busC, structure, style=style))
hdlFile.write('\n')
hdlFile.write(hdl.signalFeedback(self.M, self.N, busX, busY, busC, structure))
hdlFile.write(hdl.signalFeedback(self.M, self.N, busX, busY, busC, structure, style=style))
hdlFile.write('\n')
hdlFile.write("-- Begin Architecture\n")
hdlFile.write("begin\n\n")
hdlFile.write(hdl.sequentialBlock(M, N, clkEdge='posedge', rstActive='high'))
hdlFile.write("\n")
hdlFile.write('-- Arithmetics\n')
hdlFile.write("\n")
hdlFile.write(hdl.assignCoeff(M, N, self.icoefB, self.coefB,
self.icoefA, self.coefA, structure))
self.icoefA, self.coefA, structure, style=style))
hdlFile.write("\n")
hdlFile.write(hdl.sequentialBlock(M, N, clkEdge='posedge', rstActive='high', style=style))
hdlFile.write("\n")
# Products
hdlFile.write(hdl.arithProduct(M, N,
busX, busY, busC,
structure))
structure, style=style))
hdlFile.write("\n")
# Sums
hdlFile.write(hdl.arithAdders(M, N, structure))
hdlFile.write(hdl.arithAdders(M, N,
self.busX, self.busY, self.busC,
structure, style=style))
hdlFile.write("\n")
hdlFile.write(hdl.connectBlocks(M, N,
self.busX, self.busY, self.busC,
structure))
hdlFile.write('\n')
structure, style=style))
hdlFile.write('end {!s};\n'.format(structure))
hdlFile.close()
......
# This file is part of librefdatool. librefdatool is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
# This file is part of Libre-FDATool.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
# Libre-FDATool is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Libre-FDATool is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Copyright (C) 2013 Javier D. Garcia-Lasheras
# You should have received a copy of the GNU General Public License
# along with Libre-FDATool. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright (C) 2013 Javier D. Garcia-Lasheras
import sys
import datetime
class snippets:
......@@ -55,29 +57,33 @@ class snippets:
return entityString % entityDict
def architectureHeader(self, name, structure):
def architectureHeader(self, name, structure, style='unrolled'):
#TBD: include the appropriated realization diagram
now = datetime.datetime.now()
archHeadDict = {
'Name': name,
'Structure': structure
'Structure': structure,
'TimePrint': now.strftime("%Y-%m-%d %H:%M")
}
archHeadString = (
'architecture %(Structure)s of %(Name)s is\n\n'
'-- Architecture depends on selected realization\n'
'-- TODO: this header should each different realization\n'
'--\n'
'-- example, transposed direct form for FIR:\n'
'--\n'
'-- z^-1 z^-1 z^-1 z^-1\n'
'-- o-->--o-->--o-->- - - --o-->--o-->--o-->--o y[n]\n'
'-- | | | | | | \n'
'-- ^Bm ^Bm-1 ^Bm-2 ^B2 ^B1 ^B0\n'
'-- | | | | | |\n'
'-- x[n] o-->--o-->--o-->--o-->- - - --o-->--o-->--\n'
'--\n'
#'-- Architecture depends on selected realization\n'
#'-- TODO: this header should each different realization\n'
#'--\n'
#'-- example, transposed direct form for FIR:\n'
#'--\n'
#'-- z^-1 z^-1 z^-1 z^-1\n'
#'-- o-->--o-->--o-->- - - --o-->--o-->--o-->--o y[n]\n'
#'-- | | | | | | \n'
#'-- ^Bm ^Bm-1 ^Bm-2 ^B2 ^B1 ^B0\n'
#'-- | | | | | |\n'
#'-- x[n] o-->--o-->--o-->--o-->- - - --o-->--o-->--\n'
'-- This file has been generated with Libre-FDATool\n'
'-- Creation Time: %(TimePrint)s\n'
'\n'
)
return archHeadString % archHeadDict
......@@ -101,7 +107,7 @@ class snippets:
MSBpX = pX + qX - 1
LSBpX = qX
elif pDiff > 0:
signExt = '%(nameY)s({!s} downto {!s}) <= (others => %(nameX)s({!s}));\n'.format(pY+qY-1, pY+qY-pDiff, pX+qX-1)
signExt = '{!s}({!s} downto {!s}) <= (others => {!s}({!s}));\n'.format(nameY, pY+qY-1, pY+qY-pDiff, nameX, pX+qX-1)
MSBpY = pY + qY - 1 - pDiff
LSBpY = qY
MSBpX = pX + qX - 1
......@@ -129,7 +135,7 @@ class snippets:
elif qDiff > 0:
# Destination fractional part is > than the input one
# Fill with zeros the unused bits
trunkExt = '%(nameY)s({!s} downto 0) <= (others => \'0\');\n'.format(qDiff-1)
trunkExt = '{!s}({!s} downto 0) <= (others => \'0\');\n'.format(nameY, qDiff-1)
MSBqY = qY - 1
LSBqY = qDiff
MSBqX = qX - 1
......@@ -158,10 +164,12 @@ class snippets:
}
convertFPString = (
'-- Convert Fixed Point to %(nameY)s from %(nameX)s\n'
'%(signExt)s%(nameY)s(%(MSBpY)u downto %(LSBpY)u)'
' <= %(nameX)s(%(MSBpX)u downto %(LSBpX)u);\n'
'%(trunkExt)s%(nameY)s(%(MSBqY)u downto %(LSBqY)u)'
' <= %(nameX)s(%(MSBqX)u downto %(LSBqX)u);\n'
' <= %(nameX)s(%(MSBqX)u downto %(LSBqX)u);\n'
'\n'
)
return convertFPString % convertFPDict
......@@ -169,7 +177,7 @@ class snippets:
def sequentialBlock(self, M, N, clkEdge='posedge', rstActive='high'):
def sequentialBlock(self, M, N, clkEdge='posedge', rstActive='high', style='unrolled'):
# TBD: different rst and clk polarity
# Now, they are true and posedge respectively
......@@ -192,266 +200,511 @@ class snippets:
seqDict = {
'boolEdge': boolEdge,
'boolRst': boolRst
'boolRst': boolRst,
'M_2': M - 2,
'N_2': N - 2
}
if M >= 1 or N >= 1:
seqString = (
'-- Sequential block\n'
'z_block: process (clk)\n'
' begin\n'
' if (clk\'event and clk = \'%(boolEdge)s\') then\n'
' if (rst = \'%(boolRst)s\') then\n'
)
for ii in range(M-1):
seqString += ' zb%(ii)u <= (others => \'0\');\n' % {'ii': ii}
for ii in range(N-1):
seqString += ' za%(ii)u <= (others => \'0\');\n' % {'ii': ii}
seqString += ' else\n'
for ii in range(M-1):
seqString += ' zb%(ii)u <= zb%(ii)u_next;\n' % {'ii': ii}
for ii in range(N-1):
seqString += ' za%(ii)u <= za%(ii)u_next;\n' % {'ii': ii}
seqString += (
' end if;\n'
' end if;\n'
'end process;\n'
)
if style == 'unrolled':
seqString = (
'-- Sequential block\n'
'z_block: process (clk)\n'
' begin\n'
' if (clk\'event and clk = \'%(boolEdge)s\') then\n'
' if (rst = \'%(boolRst)s\') then\n'
)
for ii in range(M-1):
seqString += ' zb%(ii)u <= (others => \'0\');\n' % {'ii': ii}
for ii in range(N-1):
seqString += ' za%(ii)u <= (others => \'0\');\n' % {'ii': ii}
seqString += ' else\n'
for ii in range(M-1):
seqString += ' zb%(ii)u <= zb%(ii)u_next;\n' % {'ii': ii}
for ii in range(N-1):
seqString += ' za%(ii)u <= za%(ii)u_next;\n' % {'ii': ii}
seqString += (
' end if;\n'
' end if;\n'
'end process;\n'
)
elif style == 'rolled':
seqString = (
'----------------------------------\n'
'-- Sequential logic description --\n'
'----------------------------------\n'
'\n'
)
#arithProductString += 'pb_temp(%(ii)u) <= v * b%(ii)u;\n' % {'ii': ii}
#for x in 0 to 7 generate
#
#end generate
if M > 1:
seqString += (
'-- Sequential delay chain for the B block\n'
'seq_b_block: for x in 0 to %(M_2)u generate\n'
' reg_b: process (clk)\n'
' begin\n'
' if (clk\'event and clk = \'%(boolEdge)s\') then\n'
' if (rst = \'%(boolRst)s\') then\n'
' zb(x) <= (others => \'0\');\n'
' else\n'
' zb(x) <= zb_next(x);\n'
' end if;\n'
' end if;\n'
' end process reg_b;\n'
'end generate seq_b_block;\n'
'\n'
)
if N > 1:
seqString += (
'-- Sequential delay chain for the A block\n'
'seq_a_block: for x in 0 to %(N_2)u generate\n'
' reg_a: process (clk)\n'
' begin\n'
' if (clk\'event and clk = \'%(boolEdge)s\') then\n'
' if (rst = \'%(boolRst)s\') then\n'
' za(x) <= (others => \'0\');\n'
' else\n'
' za(x) <= za_next(x);\n'
' end if;\n'
' end if;\n'
' end process reg_a;\n'
'end generate seq_a_block;\n'
'\n'
)
return seqString % seqDict
def signalZ(self, M, N, busX, busY, busC, structure):
def signalZ(self, M, N, busX, busY, busC, structure, style='unrolled'):
signalZString = '-- Z^-1 delay blocks\n'
if structure == 'Direct_Form_I_Transposed':
# Z blocks in the b coefficients side
for ii in range(M-1):
signalZString += 'signal zb%(ii)u, zb%(ii)u_next: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalZString += '\n'
# Z blocks in the a coefficients side
for ii in range(N-1):
if ii != 0:
bus = busX + busC -1 -1
else:
bus = busX -1
signalZString += 'signal za%(ii)u, za%(ii)u_next: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': bus}
signalZString += '\n'
if style == 'unrolled':
# Z blocks in the b coefficients side
for ii in range(M-1):
signalZString += 'signal zb%(ii)u, zb%(ii)u_next: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalZString += '\n'
# Z blocks in the a coefficients side
for ii in range(N-1):
if ii != 0:
bus = busX + busC -1 -1
else:
bus = busX -1
signalZString += 'signal za%(ii)u, za%(ii)u_next: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': bus}
signalZString += '\n'
elif style == 'rolled':
if M > 1:
signalZString += 'type zb_array is array (0 to %(aMax)u) of signed(%(bus)u downto 0);\n' % {'aMax': M -2, 'bus': busX + busC -1 -1}
signalZString += 'signal zb, zb_next: zb_array;\n'
if N > 1:
signalZString += 'type za_array is array (0 to %(aMax)u) of signed(%(bus)u downto 0);\n' % {'aMax': N -2, 'bus': busX + busC -1 -1}
signalZString += 'signal za, za_next: za_array;\n'
signalZString += '\n'
return signalZString
def signalC(self, M, N, busC, structure):
def signalC(self, M, N, busC, structure, style='unrolled'):
signalCString = '-- Filter constants\n'
if structure == 'Direct_Form_I_Transposed':
# Z blocks in the b coefficients side
for ii in range(M):
signalCString += 'signal b%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busC - 1}
signalCString += '\n'
if style == 'unrolled':
# Z blocks in the b coefficients side
for ii in range(M):
signalCString += 'signal b%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busC - 1}
signalCString += '\n'
# Z blocks in the a coefficients side
for ii in range(N):
if ii != 0:
signalCString += 'signal a%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busC - 1}
signalCString += '\n'
# Z blocks in the a coefficients side
for ii in range(N):
if ii != 0:
signalCString += 'signal a%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busC - 1}
signalCString += '\n'
elif style == 'rolled':
if M > 0:
signalCString += 'type b_array is array (0 to %(aMax)u) of signed(%(bus)u downto 0);\n' % {'aMax': M -1, 'bus': busC -1}
signalCString += 'signal b: b_array;\n'
if N > 1:
signalCString += 'type a_array is array (0 to %(aMax)u) of signed(%(bus)u downto 0);\n' % {'aMax': N -1, 'bus': busC -1}
signalCString += 'signal a: a_array;\n'
return signalCString
def signalProducts(self, M, N, busX, busY, busC, structure):
def signalProducts(self, M, N, busX, busY, busC, structure, style='unrolled'):
signalProductString = '-- Filter Products\n'
if structure == 'Direct_Form_I_Transposed':
# Products from B coeff
for ii in range(M):
signalProductString += 'signal pb%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalProductString += '\n'
# Products from A coeff
for ii in range(N):
if ii != 0:
signalProductString += 'signal pa%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalProductString += '\n'
# Temporal Products from B coeff
for ii in range(M):
signalProductString += 'signal pb%(ii)u_temp: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1}
signalProductString += '\n'
# Temporal Products from A coeff
for ii in range(N):
if ii != 0:
signalProductString += 'signal pa%(ii)u_temp: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1}
signalProductString += '\n'
if style == 'unrolled':
# Products from B coeff
for ii in range(M):
signalProductString += 'signal pb%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalProductString += '\n'
# Products from A coeff
for ii in range(N):
if ii != 0:
signalProductString += 'signal pa%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalProductString += '\n'
# Temporal Products from B coeff
for ii in range(M):
signalProductString += 'signal pb%(ii)u_temp: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1}
signalProductString += '\n'
# Temporal Products from A coeff
for ii in range(N):
if ii != 0:
signalProductString += 'signal pa%(ii)u_temp: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1}
signalProductString += '\n'
elif style == 'rolled':
if M > 0:
signalProductString += 'type product_b_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': M -1, 'bus': busX + busC -1 -1}
signalProductString += 'signal pb: product_b_array;\n'
signalProductString += 'type product_b_temp_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': M -1, 'bus': busX + busC -1}
signalProductString += 'signal pb_temp: product_b_temp_array;\n'
if N > 1:
signalProductString += 'type product_a_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': N -2, 'bus': busX + busC -1 -1}
signalProductString += 'signal pa: product_a_array;\n'
signalProductString += 'type product_a_temp_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': N -2, 'bus': busX + busC -1}
signalProductString += 'signal pa_temp: product_a_temp_array;\n'
return signalProductString
def signalAdders(self, M, N, busX, busY, busC, structure):
def signalAdders(self, M, N, busX, busY, busC, structure, style='unrolled'):
signalAddString = '-- Filter Adders\n'
if structure == 'Direct_Form_I_Transposed':
# Adders in the b coefficients side
for ii in range(M-1):
signalAddString += 'signal sb%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalAddString += '\n'
# Adders in the a coefficients side
for ii in range(N-1):
if ii != 0:
bus = busX + busC -1 -1
else:
bus = busX -1
signalAddString += 'signal sa%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': bus}
signalAddString += '\n'
if style == 'unrolled':
# Adders in the b coefficients side
for ii in range(M-1):
signalAddString += 'signal sb%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
signalAddString += '\n'
# Adders in the a coefficients side
for ii in range(N-1):
if ii != 0:
bus = busX + busC -1 -1
else:
bus = busX -1
signalAddString += 'signal sa%(ii)u: signed(%(bus)u downto 0);\n' % {'ii': ii, 'bus': bus}
signalAddString += '\n'
if style == 'rolled':
if M > 1:
signalAddString += 'type sum_b_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': M -2, 'bus': busX + busC -1 -1}
signalAddString += 'signal sb: sum_b_array;\n'
if N > 1:
signalAddString += 'type sum_a_array is array (0 to %(Mmax)u) of signed(%(bus)u downto 0);\n' % {'Mmax': N -2, 'bus': busX + busC -1 -1}
signalAddString += 'signal sa: sum_a_array;\n'
return signalAddString
def signalFeedback(self, M, N, busX, busY, busC, structure):
def signalFeedback(self, M, N, busX, busY, busC, structure, style='unrolled'):
signalFeedbackString = ''
if structure == 'Direct_Form_I_Transposed':
signalFeedbackString += '-- Feedback loop accumulator\n'
signalFeedbackString += 'signal v: signed(%(bus)u downto 0);\n' % {'bus': busX -1}
# the same for rolled and unrolled
if N > 0:
signalFeedbackString += '-- Feedback loop accumulator\n'
signalFeedbackString += 'signal v: signed(%(bus)u downto 0);\n' % {'bus': busX -1}
if N > 1:
signalFeedbackString += 'signal add_in: signed(%(bus)u downto 0);\n' % {'bus': busX + busC -1 -1}
return signalFeedbackString
def assignCoeff(self, M, N, bCoeffBin, bCoeffFloat,
aCoeffBin, aCoeffFloat, structure):
aCoeffBin, aCoeffFloat, structure, style='unrolled'):
assignCoeffString = '-- Assign Coefficient\n'
if structure == 'Direct_Form_I_Transposed':
# Z blocks in the b coefficients side
for ii in range(M):
assignCoeffString += 'b%(ii)u <= \"%(BCoeffBin)s\"; -- %(BCoeffFloat)f\n' % {'ii': ii, 'BCoeffBin': bCoeffBin[ii], 'BCoeffFloat': bCoeffFloat[ii]}
assignCoeffString += '\n'
# Z blocks in the a coefficients side
for ii in range(N):
if ii != 0:
assignCoeffString += 'a%(ii)u <= \"%(ACoeffBin)s\"; -- %(ACoeffFloat)f\n' % {'ii': ii, 'ACoeffBin': aCoeffBin[ii], 'ACoeffFloat': aCoeffFloat[ii]}
assignCoeffString += '\n'
if style == 'unrolled':
assignCoeffString = '-- Assign Coefficients\n'
# Z blocks in the b coefficients side
for ii in range(M):
assignCoeffString += 'b%(ii)u <= \"%(BCoeffBin)s\"; -- %(BCoeffFloat)f\n' % {'ii': ii, 'BCoeffBin': bCoeffBin[ii], 'BCoeffFloat': bCoeffFloat[ii]}
assignCoeffString += '\n'
# Z blocks in the a coefficients side
for ii in range(N):
if ii != 0:
assignCoeffString += 'a%(ii)u <= \"%(ACoeffBin)s\"; -- %(ACoeffFloat)f\n' % {'ii': ii, 'ACoeffBin': aCoeffBin[ii], 'ACoeffFloat': aCoeffFloat[ii]}
assignCoeffString += '\n'
if style == 'rolled':
assignCoeffString = '-- Assign Coefficients\n'
# Z blocks in the a coefficients side
for ii in range(M):
assignCoeffString += 'b(%(ii)u) <= \"%(BCoeffBin)s\"; -- %(BCoeffFloat)f\n' % {'ii': ii, 'BCoeffBin': bCoeffBin[ii], 'BCoeffFloat': bCoeffFloat[ii]}
assignCoeffString += '\n'
for ii in range(N -1):
assignCoeffString += 'a(%(ii)u) <= \"%(ACoeffBin)s\"; -- %(ACoeffFloat)f\n' % {'ii': ii, 'ACoeffBin': aCoeffBin[ii+1], 'ACoeffFloat': aCoeffFloat[ii+1]}
assignCoeffString += '\n'
return assignCoeffString
def arithProduct(self, M, N, busX, busY, busC, structure):
def arithProduct(self, M, N, busX, busY, busC, structure, style='unrolled'):
arithProductString = '-- Product Arithmetics\n'
if structure == 'Direct_Form_I_Transposed':
# Execute products from B side
for ii in range(M):
arithProductString += 'pb%(ii)u_temp <= v * b%(ii)u;\n' % {'ii': ii}
arithProductString += 'pb%(ii)u <= pb%(ii)u_temp(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
arithProductString += '\n'
# Execute products from A side
for ii in range(N):
if ii != 0:
arithProductString += 'pa%(ii)u_temp <= v * a%(ii)u;\n' % {'ii': ii}
arithProductString += 'pa%(ii)u <= pa%(ii)u_temp(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
arithProductString += '\n'
if style == 'unrolled':
arithProductString = '-- Product Arithmetics\n'
# Execute products from B side
for ii in range(M):
arithProductString += 'pb%(ii)u_temp <= v * b%(ii)u;\n' % {'ii': ii}
arithProductString += 'pb%(ii)u <= pb%(ii)u_temp(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
#arithProductString += 'pb%(ii)u <= pb_temp(%(ii)u);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
arithProductString += '\n'
# Execute products from A side
for ii in range(N):
if ii != 0:
arithProductString += 'pa%(ii)u_temp <= v * a%(ii)u;\n' % {'ii': ii}
arithProductString += 'pa%(ii)u <= pa%(ii)u_temp(%(bus)u downto 0);\n' % {'ii': ii, 'bus': busX + busC -1 -1}
arithProductString += '\n'
elif style == 'rolled':
arithProductString = ''
return arithProductString
def arithAdders(self, M, N, structure):
def arithAdders(self, M, N, busX, busY, busC, structure, style='unrolled'):
arithAddersString = '-- Adder Arithmetics\n'
if structure == 'Direct_Form_I_Transposed':
# Z blocks in the b coefficients side
for ii in range(M-1):
arithAddersString += 'sb%(ii)u <= pb%(ii)u + zb%(ii)u;\n' % {'ii': ii}
arithAddersString += '\n'
# Z blocks in the a coefficients side
for ii in range(N-1):
if ii == 0:
arithAddersString += 'sa%(ii)u <= sig_in + za%(ii)u;\n' % {'ii': ii}
else:
arithAddersString += 'sa%(ii)u <= pa%(ii)u + za%(ii)u;\n' % {'ii': ii}
arithAddersString += '\n'
if style == 'unrolled':
arithAddersString = '-- Adder Arithmetics\n'
# Z blocks in the b coefficients side
for ii in range(M-1):
arithAddersString += 'sb%(ii)u <= pb%(ii)u + zb%(ii)u;\n' % {'ii': ii}
arithAddersString += '\n'
# Z blocks in the a coefficients side
for ii in range(N-1):
if ii == 0:
arithAddersString += 'sa%(ii)u <= sig_in + za%(ii)u;\n' % {'ii': ii}
else:
arithAddersString += 'sa%(ii)u <= pa%(ii)u + za%(ii)u;\n' % {'ii': ii}
arithAddersString += '\n'
elif style == 'rolled':
arithAddersString = '\n'
return arithAddersString
def connectBlocks(self, M, N, busX, busY, busC, structure):
def connectBlocks(self, M, N, busX, busY, busC, structure, style='unrolled'):
connectBlocksString = '-- Structure Blocks Connection\n'
if structure == 'Direct_Form_I_Transposed':
# Z blocks in the b coefficients side
for ii in range(M):
if ii == 0:
if M == 1:
outputStage = 'pb0'
if style == 'unrolled':
connectBlocksString = '-- Structure Blocks Connection\n'
# Z blocks in the b coefficients side
for ii in range(M):
if ii == 0:
if M == 1:
outputStage = 'pb0'
else:
outputStage = 'sb0'
connectBlocksString += self.convertFixedPoint(outputStage, busC[0] + busX[0] -1, busC[1] + busX[1],
'sig_out', busY[0], busY[1])
else:
outputStage = 'sb0'
connectBlocksString += self.convertFixedPoint(outputStage, busC[0] + busX[0] -1, busC[1] + busX[1],
'sig_out', busY[0], busY[1])
else:
if ii == (M-1):
sourceTypeB = 'p'
if ii == (M-1):
sourceTypeB = 'p'
else:
sourceTypeB = 's'
bConnectDict = {
'SrcType': sourceTypeB,
'Src': ii,
'Dst': ii - 1
}
connectBlocksString += 'zb%(Dst)u_next <= %(SrcType)sb%(Src)u;\n' % bConnectDict
connectBlocksString += '\n'
for ii in range(N):
if ii == 0:
if N == 1:
connectBlocksString += 'v <= sig_in;\n'
else:
connectBlocksString += 'v <= sa0;\n'
elif ii == 1:
if ii == (N-1):
firstStageA = 'pa1'
else:
firstStageA = 'sa1'
connectBlocksString += self.convertFixedPoint(firstStageA, busC[0] + busX[0] -1, busC[1] + busX[1],
'za0_next', busX[0], busX[1])
else:
sourceTypeB = 's'
if ii == (N-1):
sourceTypeA = 'p'
else:
sourceTypeA = 's'
aConnectDict = {
'SrcType': sourceTypeA,
'Src': ii,
'Dst': ii - 1
}
connectBlocksString += 'za%(Dst)u_next <= %(SrcType)sa%(Src)u;\n' % aConnectDict
connectBlocksString += '\n'
if style == 'rolled':
connectDict = {
'bus': busX[0] + busX[1] + busC[0] + busC[1] -1 -1,
'M_1': M - 1,
'M_2': M - 2,
'N_2': N - 2
}
connectBlocksString = (
'----------------------------------\n'
'-- Processing logic description --\n'
'----------------------------------\n'
'\n'
)
if N == 1:
connectBlocksString += (
'-- Bypassing the A processing block\n'
'v <= sig_in;\n'
'\n'
)
bConnectDict = {
'SrcType': sourceTypeB,
'Src': ii,
'Dst': ii - 1
}
connectBlocksString += 'zb%(Dst)u_next <= %(SrcType)sb%(Src)u;\n' % bConnectDict
connectBlocksString += '\n'
for ii in range(N):
if ii == 0:
if N == 1:
connectBlocksString += 'v <= sig_in;\n'
else:
connectBlocksString += 'v <= sa0;\n'
elif ii == 1:
if ii == (N-1):
firstStageA = 'pa1'
else:
firstStageA = 'sa1'
connectBlocksString += self.convertFixedPoint(firstStageA, busC[0] + busX[0] -1, busC[1] + busX[1],
'za0_next', busX[0], busX[1])
else:
if ii == (N-1):
sourceTypeA = 'p'
else:
sourceTypeA = 's'
aConnectDict = {
'SrcType': sourceTypeA,
'Src': ii,
'Dst': ii - 1
}
connectBlocksString += 'za%(Dst)u_next <= %(SrcType)sa%(Src)u;\n' % aConnectDict
connectBlocksString += '\n'
connectBlocksString += self.convertFixedPoint('sig_in', busX[0], busX[1],
'add_in', busC[0] + busX[0] -1, busC[1] + busX[1])
connectBlocksString += (
'-- Processing block for the Filter structure A side\n '
'connect_a_block: for n in 0 to %(N_2)u generate\n'
' -- Calculate products being generated\n'
' pa_temp(n) <= v * a(n);\n'
' pa(n) <= pa_temp(n)(%(bus)u downto 0);\n'
' -- Calculate sums being generated\n'
' -- ... input adder\n'
' add_a_block: if (n = 0) generate\n'
' sa(n) <= add_in + za(n);\n'
' end generate add_a_block;\n'
' -- ... the other adders in the loop\n'
' add_in_block: if (n /= 0) generate\n'
' sa(n) <= pa(n-1) + za(n);\n'
' end generate add_in_block;\n'
' -- Generate za_next connections\n'
' -- ... those halfway in the loop\n'
' mid_a_tap: if (n < %(N_2)u) generate\n'
' za_next(n) <= sa(n+1);\n'
' end generate mid_a_tap;\n'
' -- ... the final structure tap\n'
' final_a_tap: if (n = %(N_2)u) generate\n'
' za_next(n) <= pa(n);\n'
' end generate final_a_tap;\n'
'end generate connect_a_block;\n'
'\n'
)
connectBlocksString += self.convertFixedPoint('sa(0)', busC[0] + busX[0] -1, busC[1] + busX[1],
'v', busX[0], busX[1])
if M == 1:
connectBlocksString += (
'-- Calculate the only product\n'
'pb_temp(0) <= v * b(0);\n'
'pb(0) <= pb_temp(0)(%(bus)u downto 0);\n'
'\n'
)
connectBlocksString += self.convertFixedPoint('pb(0)', busC[0] + busX[0] -1, busC[1] + busX[1],
'sig_out', busY[0], busY[1])
else:
connectBlocksString += (
'-- Processing block for the Filter structure B side\n '
'process_b_block: for n in 0 to %(M_1)u generate\n'
' -- Calculate products being generated\n'
' pb_temp(n) <= v * b(n);\n'
' pb(n) <= pb_temp(n)(%(bus)u downto 0);\n'
' -- Calculate sums being generated\n'
' add_b_block: if (n < %(M_1)u) generate\n'
' sb(n) <= pb(n) + zb(n);\n'
' end generate add_b_block;\n'
' -- Calculate values for zb_next\n'
' -- ... those halfway in the loop\n'
' mid_b_tap: if (n < %(M_2)u) generate\n'
' zb_next(n) <= sb(n+1);\n'
' end generate mid_b_tap;\n'
' -- ... final structure\n'
' final_b_tap: if (n = %(M_2)u) generate\n'
' zb_next(n) <= pb(n+1);\n'
' end generate final_b_tap;\n'
'end generate process_b_block;\n'
'\n'
)
connectBlocksString += self.convertFixedPoint('sb(0)', busC[0] + busX[0] -1, busC[1] + busX[1],
'sig_out', busY[0], busY[1])
connectBlocksString = connectBlocksString % connectDict
return connectBlocksString
......@@ -471,6 +724,7 @@ class snippets:
}
testBenchString = (
'// This file has been generated with Libre-FDATool\n'
'module tb_%(Name)s;\n'
'\n'
'reg clk;\n'
......@@ -538,6 +792,7 @@ class snippets:
}
testBenchString = (
'-- This file has been generated with Libre-FDATool\n'
'LIBRARY ieee;\n'
'USE ieee.std_logic_1164.ALL;\n'
'USE ieee.numeric_std.all;\n'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment