Skip to content

Commit

Permalink
add serializer module
Browse files Browse the repository at this point in the history
This way, the output is only one class per cycle. All classes would require
a too big bandwidth.
  • Loading branch information
marph91 committed Mar 21, 2021
1 parent ab11a7b commit 03f57ca
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 3 deletions.
63 changes: 60 additions & 3 deletions playground/04_custom_toplevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,49 @@ def get_instance(self):
);"""


class Serializer(Layer):
def __init__(self, name, parameter):
super().__init__(name, parameter)

self.control_signal = Parameter(f"sl_valid_{self.info['name']}", "std_logic")
self.signals = [self.control_signal]

def update(self, previous_layer_info):
self.previous_name = previous_layer_info["name"]

self.constants["C_DATA_COUNT"] = Parameter(
f"C_DATA_COUNT_{self.info['name'].upper()}",
"integer",
previous_layer_info["channel"],
)
self.constants["C_DATA_BITWIDTH"] = Parameter(
f"C_DATA_BITWIDTH_{self.info['name'].upper()}",
"integer",
previous_layer_info["bitwidth"],
)

self.data_signal = Parameter(
f"slv_data_{self.info['name']}",
f"std_logic_vector({self.constants['C_DATA_BITWIDTH'].name} - 1 downto 0)",
)
self.signals.append(self.data_signal)

def get_instance(self):
return f"""
i_serializer_{self.info["name"]} : entity util.serializer
generic map (
C_DATA_COUNT => {self.constants["C_DATA_COUNT"].name},
C_DATA_BITWIDTH => {self.constants["C_DATA_BITWIDTH"].name}
)
port map (
isl_clk => isl_clk,
isl_valid => sl_valid_{self.previous_name},
islv_data => slv_data_{self.previous_name},
oslv_data => {self.data_signal.name},
osl_valid => {self.control_signal.name}
);"""


def parameter_to_vhdl(type_, parameter):
vhdl = []
for par in parameter:
Expand Down Expand Up @@ -289,7 +332,8 @@ def __init__(
library ieee;
use ieee.std_logic_1164.all;
library cnn_lib;"""
library cnn_lib;
library util;"""

# TODO: input_channel
self.entity = f"""
Expand All @@ -303,7 +347,7 @@ def __init__(
isl_start : in std_logic;
isl_valid : in std_logic;
islv_data : in std_logic_vector(C_INPUT_CHANNEL * C_INPUT_CHANNEL_BITWIDTH - 1 downto 0);
oslv_data : out std_logic_vector({self.output_classes * self.output_bitwidth} - 1 downto 0);
oslv_data : out std_logic_vector({self.output_bitwidth} - 1 downto 0);
osl_valid : out std_logic;
osl_finish : out std_logic
);
Expand All @@ -330,6 +374,9 @@ def to_vhdl(self):
implementation.append(f"{self.input_control_signal.name} <= isl_valid;")
implementation.append(f"{self.input_data_signal.name} <= islv_data;")

# append the output serializer
self.layers.append(Serializer("output", []))

# parse the bnn
for layer in self.layers:
layer.update(self.previous_layer_info)
Expand Down Expand Up @@ -363,7 +410,7 @@ def to_vhdl(self):
if __name__ == "__main__":
input_channel = 1
input_channel_bitwidth = 8
output_channel = 64
output_channel = 8
output_channel_bitwidth = 8
b = Bnn(
8,
Expand Down Expand Up @@ -413,6 +460,16 @@ def to_vhdl(self):
b.add_layer(c)
c = Convolution(
"ddd",
[
Parameter("C_KERNEL_SIZE", "integer range 1 to 7", "1"),
Parameter("C_STRIDE", "integer", "1"),
Parameter("C_OUTPUT_CHANNEL", "integer", "64"),
Parameter("C_OUTPUT_CHANNEL_BITWIDTH", "integer", "1"),
],
)
b.add_layer(c)
c = Convolution(
"eee",
[
Parameter("C_KERNEL_SIZE", "integer range 1 to 7", "1"),
Parameter("C_STRIDE", "integer", "1"),
Expand Down
58 changes: 58 additions & 0 deletions src/util/serializer.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
library ieee;
use ieee.std_logic_1164.all;

entity serializer is
generic (
C_DATA_COUNT : integer := 4;
C_DATA_BITWIDTH : integer := 8
);
port (
isl_clk : in std_logic;
isl_valid : in std_logic;
islv_data : in std_logic_vector(C_DATA_COUNT * C_DATA_BITWIDTH - 1 downto 0);
oslv_data : out std_logic_vector(C_DATA_BITWIDTH - 1 downto 0);
osl_valid : out std_logic
);
end entity serializer;

architecture rtl of serializer is

type t_data is array (0 to C_DATA_COUNT - 1) of std_logic_vector(C_DATA_BITWIDTH - 1 downto 0);

signal a_data : t_data;

signal int_output_valid_cycles : integer range 0 to C_DATA_COUNT;

function get_slice (vector: std_logic_vector; int_byte_index : natural; int_slice_size : natural) return std_logic_vector is
begin
return vector((int_byte_index + 1) * int_slice_size - 1 downto int_byte_index * int_slice_size);
end function;

begin

proc_serializer : process (isl_clk) is
begin

if (rising_edge(isl_clk)) then
a_data <= a_data(1 to a_data'high) & a_data(0);

if (isl_valid = '1') then
assert int_output_valid_cycles = 0;
int_output_valid_cycles <= C_DATA_COUNT;
for i in a_data'range loop
a_data(i) <= get_slice(islv_data, i, C_DATA_BITWIDTH);
end loop;
end if;

if (int_output_valid_cycles > 0) then
int_output_valid_cycles <= int_output_valid_cycles - 1;
end if;
end if;

end process proc_serializer;

osl_valid <= '1' when int_output_valid_cycles > 0 else
'0';
oslv_data <= a_data(0);

end architecture rtl;

0 comments on commit 03f57ca

Please sign in to comment.