我正在尝试学习MyHDL,为此,我试图创建一个非常简单的人工神经元,以后可以在简单的人工神经网络中使用它。 首先,我设计了一个只能处理单个输入和重量信号并返回输出信号的人工神经元。
@block
def input_perceptron(clk, max_res, in_signal, w_signal, out_signal):
'''a hidden layer neuron
out_signal is the result of: transfer_function( input_i x weight_i )
'''
@always(clk.posedge)
def logic():
# Multiply inputs and scale down with the shift
weighted_signal = (in_signal * w_signal) >> max_res+1
# Perform desired transfer function
tf_result = rect_transfer_func( weighted_signal, max_res )
# Assign new result
out_signal.next = tf_result
# The perceptron block must return this - MyHDL syntax
return instances()
要将其转换为Verilog,我使用了另一个功能:
def converter(max_res=16, hdl='Verilog'):
# Initialize Signals
max_val = 1 << max_res + 1
clk = Signal( bool(0) )
in_signal = Signal( intbv( randrange(max_val), min=0, max=max_val ) )
w_signal = Signal( intbv( randrange(max_val), min=0, max=max_val ) )
out_signal = Signal( intbv( 0, min=0, max=max_val ) )
# Instantiate component
perceptron_inst = input_perceptron(clk, max_res, in_signal, w_signal, out_signal)
# Convert component to desired HDL language
perceptron_inst.convert(hdl=hdl)
到目前为止一切都很好。仿真不仅显示了我的期望,而且转换后的代码是正确的,而且我能够在Vivado中进行合成。 但是,在神经网络中,隐藏层和输出层神经元必须能够处理来自多个源(也就是信号列表或总线)的信息,这就是我遇到的麻烦。
通过使用MyHDL和Python的惊人功能来运行模拟,我能够通过将信号列表用作输入和权重,使用以下代码正确模拟简单的感知器:
@block
def perceptron(clk, max_val, max_res, in_bus, w_bus, out_signal):
''' Perceptron
out_signal is the result of: transfer_function( sum( input_i x weight_i ) )
'''
@always(clk.posedge)
def logic():
# Multiply inputs and scale down
sum_weighted_inputs = 0
for i in range(len(in_bus)):
weighted_input = in_bus[i] * w_bus[i] >> max_res+1
sum_weighted_inputs += weighted_input
# Perform desired transfer function
tf = step_transfer_func(sum_weighted_inputs, max_res, max_val)
# Assign new result to ouput port
out_signal.next = tf
return instances()
浏览文档(docs)之后,我了解到在MyHDL中,一个块不能将信号列表用作端口,并且根据this chapter,我应该转换我的信号列表放入ConcatSignal,我就是这样:
def converter(max_res, num_inputs, hdl='Verilog'):
# Clock parameters
clk = Signal( bool(0) )
# Signal parameters: inputs, weights and outputs
max_val = 1 << max_res + 1
out_signal = Signal( intbv( 0, min=0, max=max_val )[max_res+1:] )
in_list = [Signal( intbv( randrange(max_val), min=0, max=max_val )[max_res+1:] ) for i in range(num_inputs)]
w_list = [Signal( intbv( randrange(max_val), min=0, max=max_val )[max_res+1:] ) for i in range(num_inputs)]
# Converting to a bus in HDL
input_bus = ConcatSignal(*reversed(in_list))
weight_bus = ConcatSignal(*reversed(w_list))
# Instantiate component
perceptron_inst = perceptron(clk, max_val, max_res, input_bus, weight_bus, out_signal)
# Convert component to desired HDL language
perceptron_inst.convert(hdl=hdl)
当我尝试模拟设计时,一切都会按预期工作,但是在转换时会出现一个小错误:感知器的in_bus
和w_bus
输入在Verilog中定义为output
端口而不是input
端口。因此,还会为这些端口生成2 wires
,并为它们分配值None
。
有趣的是,如果我只是删除生成的wires
和None
分配,以及如果我手动将output
更改为{{1, }}(对于Verilog文件中的input
和in_bus
,则代码是可合成的。在这些更改之后,如果我看看Vivado精心设计的设计,该模块似乎正是我想要的。
尽管我可以在Verilog文件中手动解决此问题,但是我感觉到此问题来自我对MyHDL的错误使用/缺乏理解。我不明白为什么使用w_bus
会突然将ConcatSignal
端口变成input
端口。
对我在这里缺少什么有任何想法吗?
答案 0 :(得分:1)
您不能将信号列表用作顶级端口,而是要创建一个具有单个输入的包装器,创建信号列表,然后将其传递给通用端口。
>