From ada17c09cd3a74fd598ba98e4eed33c721429c67 Mon Sep 17 00:00:00 2001 From: Xavi Kraken Date: Sun, 31 Jul 2022 16:55:10 +0100 Subject: [PATCH] Pushing up some sample FPGA code to see if it's all set up right --- README.md | 16 +- .../vhdl/avalon_mm_basic_register_arbiter.vhd | 110 ++ fpga/avalon_mm/vhdl/avalon_mm_pkg.vhd | 17 + fpga/avalon_st/vhdl/avalon_st_128_mux.vhd | 112 ++ .../vhdl/avalon_st_128_synchronous_fifo.vhd | 82 ++ fpga/avalon_st/vhdl/avalon_st_pkg.vhd | 170 ++++ fpga/build/Makefile.ip | 143 +++ fpga/common_make_lists.mk | 1 + fpga/fifo/vhdl/synchronous_fifo.vhd | 137 +++ .../vhdl/useful_functions_pkg.vhd | 57 ++ .../vhdl/interactable_basic_register.vhd | 94 ++ .../vhdl/single_clock_dp_ram.vhd | 60 ++ fpga/maths/vhdl/maths_pkg.vhd | 23 + fpga/prng/lfsr/lfsr.mk | 18 + fpga/prng/lfsr/tests/Makefile | 23 + fpga/prng/lfsr/tests/lfsr_taps.txt | 785 ++++++++++++++ fpga/prng/lfsr/tests/lfsr_test.py | 67 ++ fpga/prng/lfsr/tests/lfsr_test_suite.py | 79 ++ fpga/prng/lfsr/tests/lfsr_test_wrapper.vhd | 52 + fpga/prng/lfsr/vhdl/lfsr.vhd | 98 ++ fpga/prng/lfsr/vhdl/lfsr_package.vhd | 958 ++++++++++++++++++ 21 files changed, 3101 insertions(+), 1 deletion(-) create mode 100644 fpga/avalon_mm/vhdl/avalon_mm_basic_register_arbiter.vhd create mode 100644 fpga/avalon_mm/vhdl/avalon_mm_pkg.vhd create mode 100644 fpga/avalon_st/vhdl/avalon_st_128_mux.vhd create mode 100644 fpga/avalon_st/vhdl/avalon_st_128_synchronous_fifo.vhd create mode 100644 fpga/avalon_st/vhdl/avalon_st_pkg.vhd create mode 100644 fpga/build/Makefile.ip create mode 100644 fpga/common_make_lists.mk create mode 100644 fpga/fifo/vhdl/synchronous_fifo.vhd create mode 100644 fpga/general_packages/vhdl/useful_functions_pkg.vhd create mode 100644 fpga/internal_register_storage/vhdl/interactable_basic_register.vhd create mode 100644 fpga/internal_register_storage/vhdl/single_clock_dp_ram.vhd create mode 100644 fpga/maths/vhdl/maths_pkg.vhd create mode 100644 fpga/prng/lfsr/lfsr.mk create mode 100644 fpga/prng/lfsr/tests/Makefile create mode 100644 fpga/prng/lfsr/tests/lfsr_taps.txt create mode 100644 fpga/prng/lfsr/tests/lfsr_test.py create mode 100644 fpga/prng/lfsr/tests/lfsr_test_suite.py create mode 100644 fpga/prng/lfsr/tests/lfsr_test_wrapper.vhd create mode 100644 fpga/prng/lfsr/vhdl/lfsr.vhd create mode 100644 fpga/prng/lfsr/vhdl/lfsr_package.vhd diff --git a/README.md b/README.md index 97dd0ab..7900a61 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ # Accelerated_Wireguard -A hardware accelerated wireguard project using commercial FPGAs \ No newline at end of file +A hardware accelerated wireguard project using commercial FPGAs + +## How to use the VHDL portion of this codebase +

While some of this might be being used in a synthesised image, much of the codebase *should* include the tools to simulate certain functionalities.
+
+To get the simulations up and running in linux please do the following:
+1) Open up a terminal window
+2) Label one of them "build window" and the other "results window"
+3) In the "build window" type in "sudo docker run -it --rm -v /tmp:/tmp -v ${MY_GIT_LOCATION}:/mnt -e DISPLAY cocotb_test". For me I use "sudo docker run -it --rm -v /tmp:/tmp -v /home/xavi/projects:/mnt -e DISPLAY cocotb_test"
+4) In the "build window" you will be prompted for your password. Please enter it
+5) In the "build window" you will find the codebase tree in the /mnt directory. You can navigate to your test from there
+6) In the "build window", once in your test folder, to run the test type in "make sim SIM_ARGS=--vcd=${OUTPUT_WAVE_FILE_NAME}.vcd". For me I use "make sim SIM_ARGS=--vcd=foo.vcd" often
+7) In your "results window" navigate to the same test folder you are in in your "build window"
+8) In your "results window" you will see a sub folder called "sim_build". Wnter that folder
+9) In your "results window" type the following to open the gtkwave viewer for the output waveform "gtkwave ${OUTPUT_WAVE_FILE_NAME}.vcd". For me I use "gtkwave foo.vcd "
\ No newline at end of file diff --git a/fpga/avalon_mm/vhdl/avalon_mm_basic_register_arbiter.vhd b/fpga/avalon_mm/vhdl/avalon_mm_basic_register_arbiter.vhd new file mode 100644 index 0000000..ccf63ef --- /dev/null +++ b/fpga/avalon_mm/vhdl/avalon_mm_basic_register_arbiter.vhd @@ -0,0 +1,110 @@ +-- This block arbitrates between multiple incoming avalon-mm transactions in a many to one fashion +-- It operates in a round robin format +-- It will wait for the current transaction to complete before sampling the next interface +-- It operates on a single clock domain +-- This operates with the "basic" port sizes used in my applications (see pkg for more details) +-- While the burstcount port exists, it currently only accepts burst_size 1 transactions +-- It can handle a variable amount of inputs, based on a generic + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.math_pkg.all; +use work.avalon_mm_pkg.all; + +entity avalon_mm_basic_register_arbiter is +generic +( + INPUTS : natural := 2 +); +port +( + clk : in std_logic; + rst : in std_logic; + + address_array : in BASIC_REGISTER_ADDRESS_ARRAY(INPUTS - 1 downto 0); + burst_count_array : in BASIC_REGISTER_BURST_COUNT_ARRAY(INPUTS - 1 downto 0); + read_array : in std_logic_vector(INPUTS - 1 downto 0); + write_array : in std_logic_vector(INPUTS - 1 downto 0); + write_data_array : in BASIC_REGISTER_DATA_ARRAY(INPUTS - 1 downto 0); + read_data_array : out BASIC_REGISTER_DATA_ARRAY(INPUTS - 1 downto 0); + read_data_valid_array : out std_logic_vector(INPUTS - 1 downto 0); + wait_request_array : out std_logic_vector(INPUTS - 1 downto 0); + + address : out std_logic_vector(BASIC_REGISTER_ADDRESS_WIDTH - 1 downto 0); + burst_count : out std_logic_vector(BASIC_REGISTER_BURST_COUNT_WIDTH - 1 downto 0); + read : out std_logic; + write : out std_logic; + write_data : out std_logic_vector(BASIC_REGISTER_DATA_WIDTH - 1 downto 0); + read_data : in std_logic_vector(BASIC_REGISTER_DATA_WIDTH - 1 downto 0); + read_data_valid : in std_logic; + wait_request : in std_logic +); +end entity; + +architecture rtl of avalon_mm_basic_register_arbiter is + + signal address_i : std_logic_vector(BASIC_REGISTER_ADDRESS_WIDTH - 1 downto 0); + signal burst_count_i : std_logic_vector(BASIC_REGISTER_BURST_COUNT_WIDTH - 1 downto 0); + signal read_i : std_logic; + signal write_i : std_logic; + signal write_data_i : std_logic_vector(BASIC_REGISTER_DATA_WIDTH - 1 downto 0); + + signal interface_index : unsigned(log_ceil(INPUTS) - 1 downto 0); + signal pending_response : std_logic; + +begin + + interface_sampling_proc : process(clk) + begin + if rising_edge(clk) then + -- If performing a read hold onto this interface until a response has been detected + if wait_request = '0' and read_i = '1' then + pending_response <= '1'; + end if; + + -- If response happens clear hold + if read_data_valid = '1' then + pending_response <= '0'; + end if; + + -- Increment sampled interface index + if (pending_response = '0' and not (wait_request = '0' and read = '1')) or read_data_valid = '1' then + if to_integer(interface_index) < INPUTS - 1 then + interface_index <= interface_index + 1; + else + interface_index <= (others => '0'); + end if; + end if; + + if rst = '1' then + pending_response <= '0'; + interface_index <= (others => '0'); + end if; + end if; + end process; + + -- Selecting which input to sample (cleaner and allows us to check internal signals) + address_i <= address_array(to_integer(interface_index)) when rst = '0' else (others => '0'); + burst_count_i <= burst_count_array(to_integer(interface_index)) when rst = '0' else (others => '0'); + read_i <= read_array(to_integer(interface_index)) when rst = '0' else '0'; + write_i <= write_array(to_integer(interface_index)) when rst = '0' else '0'; + write_data_i <= write_data_array(to_integer(interface_index)) when rst = '0' else (others => '0'); + + -- passing the sampled interface through to the other side + address_i <= address; + burst_count_i <= burst_count; + read_i <= read; + write_i <= write; + write_data_i <= write_data; + + -- Handling returning data + response_handler_gen : for i in INPUTS - 1 downto 0 generate + read_data_array <= read_data when i = to_integer(interface_index) and rst = '0' else (others => '0'); + read_data_valid_array <= read_data_valid when i = to_integer(interface_index) and rst = '0' else '0'; + wait_request_array <= wait_request or pending_response when i = to_integer(interface_index) and rst = '0' else '1'; + end generate; + +end architecture; \ No newline at end of file diff --git a/fpga/avalon_mm/vhdl/avalon_mm_pkg.vhd b/fpga/avalon_mm/vhdl/avalon_mm_pkg.vhd new file mode 100644 index 0000000..39f11d8 --- /dev/null +++ b/fpga/avalon_mm/vhdl/avalon_mm_pkg.vhd @@ -0,0 +1,17 @@ +-- This package should cover all non-project specific avalon_mm types, constraints and functions + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package avalon_mm_pkg is + + constant BASIC_REGISTER_ADDRESS_WIDTH : natural := 16; + constant BASIC_REGISTER_BURST_COUNT_WIDTH : natural := 8; + constant BASIC_REGISTER_DATA_WIDTH : natural := 32; + + type BASIC_REGISTER_ADDRESS_ARRAY is array (natural range <> of std_logic_vector(BASIC_REGISTER_ADDRESS_WIDTH - 1 downto 0); + type BASIC_REGISTER_DATA_ARRAY is array (natural range <> of std_logic_vector(BASIC_REGISTER_DATA_ARRAY - 1 downto 0); + type BASIC_REGISTER_BURST_COUNT_ARRAY is array (natural range <> of std_logic_vector(BASIC_REGISTER_BURST_COUNT_ARRAY - 1 downto 0); + +end package; \ No newline at end of file diff --git a/fpga/avalon_st/vhdl/avalon_st_128_mux.vhd b/fpga/avalon_st/vhdl/avalon_st_128_mux.vhd new file mode 100644 index 0000000..0411c26 --- /dev/null +++ b/fpga/avalon_st/vhdl/avalon_st_128_mux.vhd @@ -0,0 +1,112 @@ +-- This is a MUX for avalon_st_128 signals +-- This allows us to combine multiple avalon_st_128 streams into a single stream + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.avalon_st_pkg.all; + +entity avalon_st_128_mux is +generic +( + NUMBER_OF_INPUTS : natural := 2; + FIFO_DEPTH : natural := 5; + BACKPRESSURE_MARGIN : natural := 4 +); +port +( + clk : in std_logic; + rst : in std_logic; + + mux_in : in AVALON_ST_128_ARRAY_TYPE(NUMBER_OF_INPUTS - 1 downto 0); + mux_in_rdy : out std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); + + mux_out : out AVALON_ST_128; + mux_out_rdy : in std_logic +); +end entity; + +architecture rtl of avalon_st_128_mux is + + signal fifo_output : AVALON_ST_128_ARRAY_TYPE(NUMBER_OF_INPUTS - 1 downto 0); + signal fifo_output_rdy : std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); + + signal internal_fifo_empty : std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); + signal target_input_port : unsigned(log_ceil(NUMBER_OF_INPUTS) - 1 downto 0); + + signal mux_out_i : AVALON_ST_128; + +begin + + -- Generate a fifo per input + input_fifo_gen : for i in 0 to (NUMBER_OF_INPUTS - 1) generate + input_fifo : entity avalon_st_128_synchronous_fifo + generic map + ( + LOG2_DEPTH => FIFO_DEPTH, + BACKPRESSURE_MARGIN => BACKPRESSURE_MARGIN + ) + port map + ( + clk => clk, + rst => rst, + + input => mux_in(i), + input_rdy => mux_in_rdy(i), + + output => fifo_output(i), + output_rdy => fifo_output_rdy(i), + + fill => open, + + full => open, + empty => internal_fifo_empty(i) + ); + end generate; + + targetting_proc : process (clk) + begin + if rising_edge(clk) then + if mux_out_rdy = '1' then + if internal_fifo_empty(to_integer(target_input_port)) /= '0' then + -- stay on port until the last cycle of data has egressed, then switch + if mux_out_i.endofpacket = '1' and mux_out_i.valid = '1' then + if to_integer(target_input_port) < NUMBER_OF_INPUTS - 1 then + target_input_port <= target_input_port + 1; + else + target_input_port <= (others => '0'); + end if; + end if; + else + -- increment the target port if not at max port, else loop around to the lowest port + if to_integer(target_input_port) < NUMBER_OF_INPUTS - 1 then + target_input_port <= target_input_port + 1; + else + target_input_port <= (others => '0'); + end if; + end if; + end if; + + if rst = '1' then + target_input_port <= (others => '0'); + end if; + end if; + end process; + + -- map the fifo outputs to the actual output(exploded view as the valid has some extra conditions) + mux_out_i.data <= fifo_output(to_integer(target_input_port)).data when rst /= '1' else (others => '0'); + mux_out_i.startofpacket <= fifo_output(to_integer(target_input_port)).startofpacket when rst /= '1' else '0'; + mux_out_i.endofpacket <= fifo_output(to_integer(target_input_port)).endofpacket when rst /= '1' else '0'; + mux_out_i.empty <= fifo_output(to_integer(target_input_port)).empty when rst /= '1' else (others => '0'); + mux_out_i.error <= fifo_output(to_integer(target_input_port)).error when rst /= '1' else '0'; + mux_out_i.valid <= fifo_output(to_integer(target_input_port)).valid and mux_out_rdy when rst /= '1' else '0'; + + mux_out <= mux_out_i; + + rdy_control_gen : for i in 0 to (NUMBER_OF_INPUTS - 1) generate + fifo_output_rdy(i) <= mux_out_rdy when to_integer(target_input_port) = i and rst /= '1' else '0'; + end generate; + +end architecture; \ No newline at end of file diff --git a/fpga/avalon_st/vhdl/avalon_st_128_synchronous_fifo.vhd b/fpga/avalon_st/vhdl/avalon_st_128_synchronous_fifo.vhd new file mode 100644 index 0000000..25e0c90 --- /dev/null +++ b/fpga/avalon_st/vhdl/avalon_st_128_synchronous_fifo.vhd @@ -0,0 +1,82 @@ +-- A wrapper around our synchronous fifo that will format incoming avalon_ST_128 messages +-- into fifo transactions +-- Should be used a s a store / buffer inside my designs + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.avalon_st_pkg.all; + +entity avalon_st_128_synchronous_fifo is +generic +( + LOG2_DEPTH : natural := 5; + BACKPRESSURE_MARGIN : natural := 4 +); +port +( + clk : in std_logic; + rst : in std_logic; + + input : in AVALON_ST_128; + input_rdy : out std_logic; + + output : out AVALON_ST_128; + output_rdy : in std_logic; + + fill : out std_logic_vector(31 downto 0); + + full : out std_logic; + empty : out std_logic +); +end entity; + +architecture rtl of avalon_st_128_synchronous_fifo is + + constant FIFO_WIDTH : natural := input.data'length _ input.empty'length + 3; -- input.startofpacket'length + input.endofpacket'length + input.err'length (valid is not included here) + constant FIFO_DEPTH : natural := 2**LOG2_DEPTH; + + signal fifo_write_enable : std_logic; + signal fifo_write_data : std_logic_vector(FIFO_WIDTH - 1 downto 0); + + signal fifo_read_enable : std_logic; + signal fifo_read_data : std_logic_vector(FIFO_WIDTH - 1 downto 0); + + signal fifo_internal_count : std_logic_vector(31 downto 0); + +begin + + fifo_write_enable <= input.valid when rst /= '1' else '0'; -- No writes will be allowed upon a reset + fifo_read_enable <= output_rdy when rst /= '1' else '0'; + + basic_fifo : entity synchronous_fifo + generic map + ( + WIDTH => FIFO_WIDTH, + DEPTH => FIFO_DEPTH + ) + port map + ( + clk => clk, + rst => rst, + + write_enable => fifo_write_enable, + write_data => fifo_write_data, + + read_enable => fifo_read_enable, + read_data => fifo_read_data, + + empty => empty, + almost_empty => open, + almost_full => open, + full => full, + + count => fifo_internal_count + ); + + input_rdy <= '1' when (to_integer(unsigned(fifo_internal_count))) < (FIFO_DEPTH - BACKPRESSURE_MARGIN) else '0'; + fill <= fifo_internal_count; + +end architecture; \ No newline at end of file diff --git a/fpga/avalon_st/vhdl/avalon_st_pkg.vhd b/fpga/avalon_st/vhdl/avalon_st_pkg.vhd new file mode 100644 index 0000000..7241bc2 --- /dev/null +++ b/fpga/avalon_st/vhdl/avalon_st_pkg.vhd @@ -0,0 +1,170 @@ +-- This package contains all definitions relating to the implementation of the avalon_st protocol + +library ieee; +use ieee.std_logic_1164.all; + +package avalon_st_pkg is + type AVALON_ST_8 is record + data : std_logic_vector(7 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + error : std_logic; + end record; + + type AVALON_ST_16 is record + data : std_logic_vector(15 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(0 downto 0); + error : std_logic; + end record; + + type AVALON_ST_32 is record + data : std_logic_vector(31 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(0 downto 0); + error : std_logic; + end record; + + type AVALON_ST_64 is record + data : std_logic_vector(63 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(1 downto 0); + error : std_logic; + end record; + + type AVALON_ST_128 is record + data : std_logic_vector(127 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(2 downto 0); + error : std_logic; + end record; + + type AVALON_ST_256 is record + data : std_logic_vector(255 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(3 downto 0); + error : std_logic; + end record; + + type AVALON_ST_512 is record + data : std_logic_vector(511 downto 0); + valid : std_logic; + startofpacket : std_logic; + endofpacket : std_logic; + empty : std_logic_vector(4 downto 0); + error : std_logic; + end record; + + type AVALON_ST_8_ARRAY_TYPE is array (natural range <>) of AVALON_ST_8; + type AVALON_ST_16_ARRAY_TYPE is array (natural range <>) of AVALON_ST_16; + type AVALON_ST_32_ARRAY_TYPE is array (natural range <>) of AVALON_ST_32; + type AVALON_ST_64_ARRAY_TYPE is array (natural range <>) of AVALON_ST_64; + type AVALON_ST_128_ARRAY_TYPE is array (natural range <>) of AVALON_ST_128; + type AVALON_ST_256_ARRAY_TYPE is array (natural range <>) of AVALON_ST_256; + type AVALON_ST_512_ARRAY_TYPE is array (natural range <>) of AVALON_ST_512; + + function ZERO_AVALON_ST_8 return AVALON_ST_8; + function ZERO_AVALON_ST_16 return AVALON_ST_16; + function ZERO_AVALON_ST_32 return AVALON_ST_32; + function ZERO_AVALON_ST_64 return AVALON_ST_64; + function ZERO_AVALON_ST_128 return AVALON_ST_128; + function ZERO_AVALON_ST_256 return AVALON_ST_256; + function ZERO_AVALON_ST_512 return AVALON_ST_512; + +end package avalon_st_pkg; + +package body avalon_st_pkg is + + function ZERO_AVALON_ST_8 return AVALON_ST_8 is + variable returned_record : AVALON_ST_8; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_8; + + function ZERO_AVALON_ST_16 return AVALON_ST_16 is + variable returned_record : AVALON_ST_16; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_16; + + function ZERO_AVALON_ST_32 return AVALON_ST_32 is + variable returned_record : AVALON_ST_32; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_32; + + function ZERO_AVALON_ST_64 return AVALON_ST_64 is + variable returned_record : AVALON_ST_64; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_64; + + function ZERO_AVALON_ST_128 return AVALON_ST_128 is + variable returned_record : AVALON_ST_128; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_128; + + function ZERO_AVALON_ST_256 return AVALON_ST_256 is + variable returned_record : AVALON_ST_256; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_256; + + function ZERO_AVALON_ST_512 return AVALON_ST_512 is + variable returned_record : AVALON_ST_512; + begin + returned_record.data := (others => '0'); + returned_record.valid := '0'; + returned_record.startofpacket := '0'; + returned_record.endofpacket := '0'; + returned_record.empty := (others => '0'); + returned_record.error := '0'; + return returned_record; + end function ZERO_AVALON_ST_512; diff --git a/fpga/build/Makefile.ip b/fpga/build/Makefile.ip new file mode 100644 index 0000000..23001bc --- /dev/null +++ b/fpga/build/Makefile.ip @@ -0,0 +1,143 @@ +### +# Project configuration file +## + +TOPLEVEL ?= $(PROJECT) +ABOVE_PROJECT_DIR = `readlink -e $(PROJECT_DIR)/../` + +# Main +all: $(PROJECT).asm.rpt $(PROJECT).sta.rpt + ifeq ($(DEVICE_TYPE),FPGA) + $(MAKE) convert + endif + +# Map +$(PROJECT).syn.rpt: $(ASSIGNMENT_FILES) + quartus_syn --read_settings_file=on --write_settings_file-on $(PROJECT) -c $(PROJECT) + quartus_sh --script $(PINOUT_SH) $(PROJECT) + +# Fit +$(PROJECT).fit.rpt: $(PROJECT.syn.rpt) + quartus_fit $(FIT_ARGS) $(PROJECT) + +# Assemble +$(PROJECT).asm.rpt: $(PROJECT).fit.rpt + quartus_asm $(ASM_ARGS) $(PROJECT) + +# Timing analysis +$(PROJECT).sta.rpt: $(PROJECT).fit.rpt path_analysis.tcl + quartus_sta $(TAN_ARGS) $(PROJECT) + + ifeq ($(ENABLE_PATH_ANALYSIS), TRUE) + quartus_sta -t path_analysis.tcl + endif + +path_analysis.tcl: + echo -e project_open -force $(PROJECT) - revision $(PROJECT) > $@ + echo -e create_timing_netlist -model slow >> $@ + echo -e read_sdc >> $@ + echo -e update_timing_netlist >> $@ + echo -e report_path -fomr [get_keepers $(LAUNCH_REGISTER)] -to [get_keepers $(LATCH_REGISTER)] -npaths 1024 -file \"$PATH_ANALYSIS_REPORT_FILE)\" >> $@ + +# Convert +convert: + $(COF_SH) $(PROJECT) $(PART) $(PROMDEVICE) + quartus_cpf -c $(PROJECT).cof + quartus_cpf -c -d $(PROMDEVICE) $(PROJECT).sof $(PROJECT).pof + + ifeq ($HPS_INCLUDED),TRUE) + quartus_cpf -c --hps -o bitstream_compression=on $(PROJECT).sof $(PROJECT).rbf + endif + +# Archiving +$(PROJECT).qar: gen_qar.tcl + quartus_sh -t gen_qar.tcl + +gen_qar.tcl: + echo -e project_open -revision $(PROJECT) $(PROJECT) > $@ + echo -e project_archive $(PROJECT).qar -include_outputs -include_libraries -overwrite >> $@ + echo -e project_close >> $@ + +# Project Initialisation +$(ASSIGNMENT_FILES): ip_generate temp.tcl + quartus_sh --script temp.tcl + + ifeq ($(ENABLE_SIGNALTAP),TRUE) + quartus_stp $(PROJECT) -c $(PROJECT) -e std_file=$(SIGNALTAP_FILE) + endif + +ipgenerate: first.tcl + quartus_sh --prepare -f $(FAMILY) -d $(PART) -t $(TOP_LEVEL) $(PROJECT) + + ifneq ($(SRC_IP),) + quartus_sh --script first.tcl + quartus_ipgenerate $(PROJECT) -c $(PROJECT) --run_default_mode_op + endif + +first.tcl: + ifneq ($SRC_IP),) + echo -e 'set ipfiles $(SRC_IP)' > @ + echo -e 'set replaced_ipfiles [regsub -all -- "--ip_files=" $$ipfiles ","]' >> @ + echo -e 'if {[string equal -length [string length ","] "," $$replaced_ipfiles]} {' >> $@ + echo -e 'regsub ***=, $$replaced_ipfiles "" replaced_ipfiles }' >> $@ + echo -e 'if {[regexp {,} $$replaced_ipfiles]} {set ipfilelist [split $$replaced_ipfiles ,]}' >> $@ + endif + + ifneq ($SRC_QSYS),) + echo -e 'set qsysfiles $(SRC_IP)' > @ + echo -e 'set replaced_qsysfiles [regsub -all -- "--source=" $$qsysfiles ","]' >> @ + echo -e 'if {[string equal -length [string length ","] "," $$replaced_qsysfiles]} {' >> $@ + echo -e 'regsub ***=, $$replaced_qsysfiles "" replaced_qsysfiles }' >> $@ + echo -e 'if {[regexp {,} $$replaced_qsysfiles]} {set qsysfilelist [split $$replaced_qsysfiles ,]}' >> $@ + endif + + echo -e 'project open -revision $(PROJECT) $(PROJECT) + + ifneq ($SRC_IP),) + echo -e 'foreach ipfile $$ipfilelist {set_global_assignment -name IP_FILE $$ipfile }' >> $@ + endif + + ifneq ($SRC_QSYS),) + echo -e 'foreach qsysfile $$qsysfilelist {set_global_assignment -name QSYS_FILE $$qsysfile }' >> $@ + endif + + ifeq ($(VHDL_2008),TRUE) + echo -e 'set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008' >> $@ + endif + + echo -e 'project_close' >> $@ + +temp.tcl: + echo -e 'set hdlfiles $(SRC_HDL)' > @ + echo -e 'set replaced_hdlfiles [regsub -all -- "--ip_files=" $$hdlfiles ","]' >> @ + echo -e 'if {[string equal -length [string length ","] "," $$replaced_hdlfiles]} {' >> $@ + echo -e 'regsub ***=, $$replaced_hdlfiles "" replaced_hdlfiles }' >> $@ + echo -e 'if {[regexp {,} $$replaced_hdlfiles]} {set hdlfilelist [split $$replaced_hdlfiles ,]}' >> $@ + + echo -e 'project_open -revision $(PROJECT) $(PROJECT)' >> $@ + echo -e 'set_global_assignment -name SEED $(SEED)' $@ + echo -e 'setuniquehdlfilelist [lsort -unique $$hdlfilelist] >> $@ + echo -e 'foreach hdlfile $$uniquehdlfilelist {' >> $@ + + echo -e 'if [regexp {.vhd$$} $$hdlfile] {' >> $@ + echo -e 'set_global_assignment -name VHDL_FILE $$hdlfile' >> $@ + + echo -e '} elseif [regexp {.sv$$} $$hdlfile] {' >> $@ + echo -e 'set_global_assignment -name SYSTEMVERILOG_FILE $$hdlfile' >> $@ + + echo -e '} elseif [regexp {.sdc$$} $$hdlfile] {' >> $@ + echo -e 'set_global_assignment -name SDC_FILE $$hdlfile' >> $@ + + echo -e '} else {' >> $@ + echo -e 'set_global_assignment -name VERILOG_FILE $$hdlfile' >> $@ + echo -e '}}' >>@ + + echo -e 'set_global_assignment -name SDC_FILE $(CONSTRAINTS)' >> $@ + echo -e 'set_global_assignment -name STRATIXIII_CONFIGURATION_SCHEME "ACTIVE_SERIAL"' >> $@ + echo -e 'set_global_assignment -name SAFE_STATE_MACHINE ON' >> $@ + + ifeq ($(ENABLE_ADDITIONAL_QSF_SETTINGS),TRUE) + cat $(ADDITIONAL_QSF_SETTINGS) >> temp.tcl + endif + + echo -e 'project_close' >> $@ \ No newline at end of file diff --git a/fpga/common_make_lists.mk b/fpga/common_make_lists.mk new file mode 100644 index 0000000..23d7ee5 --- /dev/null +++ b/fpga/common_make_lists.mk @@ -0,0 +1 @@ +include $(PROJECT_DIR)/../fpga/prng/lfsr/lfsr.mk diff --git a/fpga/fifo/vhdl/synchronous_fifo.vhd b/fpga/fifo/vhdl/synchronous_fifo.vhd new file mode 100644 index 0000000..66b031f --- /dev/null +++ b/fpga/fifo/vhdl/synchronous_fifo.vhd @@ -0,0 +1,137 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity synchronous_fifo is + generic + ( + WIDTH : natural := 32; + DEPTH : natural := 8 + ); + port + ( + clk : in std_logic; + rst : in std_logic; + + write_enable : in std_logic; + write_data : in std_logic_vector(WIDTH - 1 downto 0); + + read_enable : in std_logic; + read_data : out std_logic_vector(WIDTH - 1 downto 0); + + empty : out std_logic; + almost_empty : out std_logic; + almost_full : out std_logic; + full : out std_logic; + + count : out std_logic_vector(31 downto 0) + ); +end entity; + +architecture rtl of synchrnous_fifo is + + signal bram_type is array (0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0); + signal bram : bram_type; + + signal write_address : integer; + signal read_address : integer; + + signal empty_i : std_logic; + signal full_i : std_logic; + + signal count_unsigned : unsigned(count'range); + +begin + + -- Assign internal signals to outputs + empty <= empty_i; + full <= full_i; + count <= std_logic_vector(count_unsigned); + + -- Define almost signals + almost_empty <= '1' when count_unsigned >= 2 else '0'; + almost_full <= '1' when count_unsigned >= (DEPTH -2) else '0'; + + determine_empty_or_full : process (write_address, read_address) + begin + if read=_address = write_address then + empty_i <= '1'; + else + empty_i <= '0'; + end if; + + if (read_address = 0 and write_address = (DEPTH - 1)) or (read_address = write_address + 1) then + full_i <= '1'; + else + full_i <= '0'; + end if; + end process; + + fifo_proc : process (clk) + variable operation : std_logic_vector(1 downto 0); + begin + if rising_edge(clk) then + operation := write_enable & read_enable; + + case operation is + when "01" => + if empty_i = '0' then + read_data <= bram(read_address); + + if read_address = (DEPTH - 1) then + read_address <= 0; + else + read_address <= read_address + 1; + end if; + + count_unsigned <= count_unsigned + 1; + end if; + + when "10" => + if full_i = '0' then + bram(write_address) <= write_data; + + if write_address = (DEPTH - 1) then + write_address <= 0; + else + write_address <= write_address + 1; + end if; + + count_unsigned = count_unsigned + 1; + end if; + + when "11" => + if empty_i = '0' then + read_data <= bram(read_address); + + if read_address = (DEPTH - 1) then + read_address <= 0; + else + read_address <= raed_address + 1; + end if; + + bram(write_address) <= write_data; + + if write_address = (DEPTH - 1) then + write_address <= 0; + else + write_address <= write_address + 1; + end if; + else + raed_data <= write_data; + end if; + + when others => + read_data <= (others => '0'); + + end case; + + if rst = '1' then + write_address <= 0; + read_address <= 0; + read_data <= (others => '0'); + count_unsigned <= (others => '0'); + end if; + end if; + end process; +end architecture; \ No newline at end of file diff --git a/fpga/general_packages/vhdl/useful_functions_pkg.vhd b/fpga/general_packages/vhdl/useful_functions_pkg.vhd new file mode 100644 index 0000000..b0548b1 --- /dev/null +++ b/fpga/general_packages/vhdl/useful_functions_pkg.vhd @@ -0,0 +1,57 @@ +-- This package should cover general useful functions that +-- will see a lot of use in my code but do not fit under +-- any specific umbrella. + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package useful_functions_pkg is + + function extend(input : unsigned; length : natural) return unsigned; + function extend(input : std_logic_vector; length : natural) return std_logic_vector; + function extend(input : std_logic; length : natural) return std_logic_vector; + +end package; + +package body useful_functions_pkg is + + function extend(input : unsigned; length : natural) return unsigned is + variable returned_vector : unsigned(length - 1 downto 0); + begin + if length >= input'length then + returned_vector(returned_vector'high downto input'length) := (others => '0'); + returned_vector(input'length - 1 downto 0) := input; + else + returned_vector := input(returned_vector'length - 1 downto 0); + end if; + + return returned_vector; + end function extend; + + function extend(input : std_logic_vector; length : natural) return std_logic_vector is + variable returned_vector : std_logic_vector(length - 1 downto 0); + begin + if length >= input'length then + returned_vector(returned_vector'high downto input'length) := (others => '0'); + returned_vector(input'length - 1 downto 0) := input; + else + returned_vector := input(returned_vector'length - 1 downto 0); + end if; + + return returned_vector; + end function extend; + + function extend(input : std_logic; length : natural) return std_logic_vector is + variable returned_vector : std_logic_vector(length - 1 downto 0); + begin + if length >= 1 then + returned_vector(length - 1 downto 1) := (others => '0'); + returned_vector(0) := input; + end if; + + return returned_vector; + + end function extend; + +end package body; \ No newline at end of file diff --git a/fpga/internal_register_storage/vhdl/interactable_basic_register.vhd b/fpga/internal_register_storage/vhdl/interactable_basic_register.vhd new file mode 100644 index 0000000..ed51bec --- /dev/null +++ b/fpga/internal_register_storage/vhdl/interactable_basic_register.vhd @@ -0,0 +1,94 @@ +-- This component is an interactable set of registers, which can listen to signals or set them in firmware +-- Intended to be used for debug in a HPS enabled system +-- It operates on a single clock +-- It should only listen to requests within it's address range +-- At the moment it can only operate with a burst count of 1 +-- There must be at least 1 input register in this incarnation + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.math_pkg.all; +use work.avalon_mm_pkg.all; + +entity interactable_basic_register is +generic +( + BASE_ADDRESS : std_logic_vector(31 downto 0) := (others => '0'); + BYTE_INDEXED : boolean := false; + INPUT_REGISTERS : natural := 2; + OUTPUT_REGISTERS : natural := 2 +); +port +( + clk : in std_logic; + rst : in std_logic; + + address : in std_logic_vector(BASIC_REGISTER_ADDRESS_WIDTH - 1 downto 0); + burst_count : in std_logic_vector(BASIC_REGISTER_BURST_COUNT_WIDTH - 1 downto 0); + read : in std_logic; + write : in std_logic; + write_data : in std_logic_vector(BASIC_REGISTER_DATA_WIDTH - 1 downto 0); + read_data : out std_logic_vector(BASIC_REGISTER_DATA_WIDTH - 1 downto 0); + read_data_valid : out std_logic; + wait_request : out std_logic; + + register_array_input : in BASIC_REGISTER_DATA_ARRAY((INPUT_REGISTERS + OUTPUT_REGISTERS) - 1 downto 0); + register_array_output : out BASIC_REGISTER_DATA_ARRAY((INPUT_REGISTERS + OUTPUT_REGISTERS) - 1 downto 0) +); +end entity; + +architecture rtl of interactable_basic_register is + + constant BYTES : integer := 2 ** (log_ceil(BASIC_REGISTER_DATA_WIDTH) - 3); + constant OUTPUT_START : integer := INPUT_REGISTERS; + + signal register_array_output_i : BASIC_REGISTER_DATA_ARRAY((INPUT_REGISTERS + OUTPUT_REGISTERS) - 1 downto 0) + +begin + + wait_request <= not (read or write); + + registers_interaction_proc : process(clk) + variable shifted_address : integer; + begin + if rising_edge(clk) then + -- Applying the base address, then byte index if selected + if BYTE_INDEXED = true then + shifted_address := to_integer(unsigned(address)) / BYTES - to_integer(unsigned(BASE_ADDRESS)) / BYTES; + else + shifted_address := to_integer(unsigned(address)) - to_integer(unsigned(BASE_ADDRESS)); + end if; + + read_data_valid <= '0'; + + -- Writes + if write = '1' then + if shifted_address >= OUTPUT_START and shifted_address < OUTPUT_START + OUTPUT_REGISTERS then + register_array_output_i(shifted_address - OUTPUT_START) <= write_data; + end if; + end if; + + -- Reads + if read = '1' then + if shifted_address >= OUTPUT_START and shifted_address < OUTPUT_START + OUTPUT_REGISTERS then + read_data <= register_array_output_i(shifted_address - OUTPUT_START); + read_data_valid <= '1'; + elsif shifted_address >= 0 and shifted_address < INPUT_REGISTERS then + read_data <= register_array_input(shifted_address); + read_data_valid <= '1'; + end if; + end if; + + if rst = '1' then + read_data <= (others => '0'); + read_data_valid <= '0'; + end if; + end if; + end process; + + register_array_output <= register_array_output_i; + +end architecture; \ No newline at end of file diff --git a/fpga/internal_register_storage/vhdl/single_clock_dp_ram.vhd b/fpga/internal_register_storage/vhdl/single_clock_dp_ram.vhd new file mode 100644 index 0000000..cd98393 --- /dev/null +++ b/fpga/internal_register_storage/vhdl/single_clock_dp_ram.vhd @@ -0,0 +1,60 @@ +-- This block is a very basic implementation of a dual port ram +-- It operates on a single clock domain +-- This design was made for testing purposes +-- Currently no reset or cleaning functionality +-- Will always report back a read of the address specified + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity single_clock_dp_ram is +generic +( + ADDRESS_WIDTH : natural := 16; + DATA_WIDTH : natural := 32 +); +port +( + clk : in std_logic; + + -- A side + a_address : in std_logic_vector(ADDRESS_WIDTH - 1 downto 0); + a_write : in std_logic; + a_write_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + a_read_data : out std_logic_vector(DATA_WIDTH - 1 downto 0); + + -- B side + b_address : in std_logic_vector(ADDRESS_WIDTH - 1 downto 0); + b_write : in std_logic; + b_write_data : in std_logic_vector(DATA_WIDTH - 1 downto 0); + b_read_data : out std_logic_vector(DATA_WIDTH - 1 downto 0) +); +end entity; + +architecture rtl of single_clock_dp_ram is + + type memory_type is array (2 ** ADDRESS_WIDTH - 1 downto 0) of std_logic_vector(DATA_WIDTH - 1 downto 0); + signal internal_registers : memory_type := (others => (others => '0')); + +begin + + dp_ram_proc : process(clk) + begin + if rising_edge(clk) then + if a_write = '1' then + internal_registers(to_integer(unsigned(a_address))) <= a_write_data; + end if; + + a_read_data <= internal_registers(to_integer(unsigned(a_address))); + + if b_write = '1' then + internal_registers(to_integer(unsigned(b_address))) <= b_write_data; + end if; + + b_read_data <= internal_registers(to_integer(unsigned(b_address))); + + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/fpga/maths/vhdl/maths_pkg.vhd b/fpga/maths/vhdl/maths_pkg.vhd new file mode 100644 index 0000000..b6dfabc --- /dev/null +++ b/fpga/maths/vhdl/maths_pkg.vhd @@ -0,0 +1,23 @@ +-- This package should cover all non-project specific maths functions that can be called +-- Some of these are only suitable for use pre-synthesis, as they will not function properly +-- during normal operation. These will be marked appropriately during creation + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +package maths_pkg is + + function log_ceil(input : natural) return natural; + +end package; + +package body maths_pkg is + + function log_ceil(input : natural) return natural is + begin + return natural(ceil(log2(real(input)))); + end function; + +end package body; \ No newline at end of file diff --git a/fpga/prng/lfsr/lfsr.mk b/fpga/prng/lfsr/lfsr.mk new file mode 100644 index 0000000..5d45471 --- /dev/null +++ b/fpga/prng/lfsr/lfsr.mk @@ -0,0 +1,18 @@ +ifndef $(LFSR_INCLUDED) +LFSR_INCLUDED = "yes" +LFSR_DIR = $(PROJECT_DIR)../fpga/prng/lfsr +LFSR_SRC_DIR = $(LFSR_DIR)/vhdl + +LFSR_SIM_SRC = \ + $(LFSR_SRC_DIR)/lfsr_package.vhd \ + $(LFSR_SRC_DIR)/lfsr.vhd + +LFSR_SYN_SRC = \ + --source=$(LFSR_SRC_DIR)/lfsr_package.vhd \ + --source=$(LFSR_SRC_DIR)/lfsr.vhd + +LFSR_TB_SRC = \ + $(LFSR_SIM_SRC) \ + $(LFSR_DIR)/tests/lfsr_test_wrapper.vhd + +endif diff --git a/fpga/prng/lfsr/tests/Makefile b/fpga/prng/lfsr/tests/Makefile new file mode 100644 index 0000000..a4543c4 --- /dev/null +++ b/fpga/prng/lfsr/tests/Makefile @@ -0,0 +1,23 @@ +# Default the chosen language to VHDL +TOPLEVEL_LANG ?= vhdl + +# Default the sim tool to GHDL +SIM ?= ghdl + +# Find the common_make_lists list that points to all the artifacts +PROJECT_DIR = ../../../ +include $(PROJECT_DIR)../fpga/common_make_lists.mk + +PWD=$(shell pwd) + +# The location of the VHDL files that will be used in the sim +SOURCE_FILES = $(abspath $(LFSR_TB_SRC)) + +# Formatting all the source files correctly to input into the simulation +VHDL_SOURCES = $(shell echo '$(SOURCE_FILES)' | tr " " "\n" | awk '!x[$$0]++' | tr "\n" " ") + +TOPLEVEL = lfsr_test_wrapper +MODULE := lfsr_test_suite + +include $(shell cocotb-config --makefiles)/Makefile.inc +include $(shell cocotb-config --makefiles)/Makefile.sim \ No newline at end of file diff --git a/fpga/prng/lfsr/tests/lfsr_taps.txt b/fpga/prng/lfsr/tests/lfsr_taps.txt new file mode 100644 index 0000000..59c4ef2 --- /dev/null +++ b/fpga/prng/lfsr/tests/lfsr_taps.txt @@ -0,0 +1,785 @@ + 2, 1, 0, 0 + 3, 2, 0, 0 + 4, 3, 0, 0 + 5, 3, 0, 0 + 6, 5, 0, 0 + 7, 6, 0, 0 + 8, 6, 5, 4 + 9, 5, 0, 0 + 10, 7, 0, 0 + 11, 9, 0, 0 + 12, 11, 8, 6 + 13, 12, 10, 9 + 14, 13, 11, 9 + 15, 14, 0, 0 + 16, 14, 13, 11 + 17, 14, 0, 0 + 18, 11, 0, 0 + 19, 18, 17, 14 + 20, 17, 0, 0 + 21, 19, 0, 0 + 22, 21, 0, 0 + 23, 18, 0, 0 + 24, 23, 21, 20 + 25, 22, 0, 0 + 26, 25, 24, 20 + 27, 26, 25, 22 + 28, 25, 0, 0 + 29, 27, 0, 0 + 30, 29, 26, 24 + 31, 28, 0, 0 + 32, 30, 26, 25 + 33, 20, 0, 0 + 34, 31, 30, 26 + 35, 33, 0, 0 + 36, 25, 0, 0 + 37, 36, 33, 31 + 38, 37, 33, 32 + 39, 35, 0, 0 + 40, 37, 36, 35 + 41, 38, 0, 0 + 42, 40, 37, 35 + 43, 42, 38, 37 + 44, 42, 39, 38 + 45, 44, 42, 41 + 46, 40, 39, 38 + 47, 42, 0, 0 + 48, 44, 41, 39 + 49, 40, 0, 0 + 50, 48, 47, 46 + 51, 50, 48, 45 + 52, 49, 0, 0 + 53, 52, 51, 47 + 54, 51, 48, 46 + 55, 31, 0, 0 + 56, 54, 52, 49 + 57, 50, 0, 0 + 58, 39, 0, 0 + 59, 57, 55, 52 + 60, 59, 0, 0 + 61, 60, 59, 56 + 62, 59, 57, 56 + 63, 62, 0, 0 + 64, 63, 61, 60 + 65, 47, 0, 0 + 66, 60, 58, 57 + 67, 66, 65, 62 + 68, 59, 0, 0 + 69, 67, 64, 63 + 70, 69, 67, 65 + 71, 65, 0, 0 + 72, 69, 63, 62 + 73, 48, 0, 0 + 74, 71, 70, 67 + 75, 74, 72, 69 + 76, 74, 72, 71 + 77, 75, 72, 71 + 78, 77, 76, 71 + 79, 70, 0, 0 + 80, 78, 76, 71 + 81, 77, 0, 0 + 82, 78, 76, 73 + 83, 81, 79, 76 + 84, 71, 0, 0 + 85, 84, 83, 77 + 86, 84, 81, 80 + 87, 74, 0, 0 + 88, 80, 79, 77 + 89, 51, 0, 0 + 90, 88, 87, 85 + 91, 90, 86, 83 + 92, 90, 87, 86 + 93, 91, 0, 0 + 94, 73, 0, 0 + 95, 84, 0, 0 + 96, 90, 87, 86 + 97, 91, 0, 0 + 98, 87, 0, 0 + 99, 95, 94, 92 +100, 63, 0, 0 +101, 100, 95, 94 +102, 99, 97, 96 +103, 94, 0, 0 +104, 103, 94, 93 +105, 89, 0, 0 +106, 91, 0, 0 +107, 105, 99, 98 +108, 77, 0, 0 +109, 107, 105, 104 +110, 109, 106, 104 +111, 101, 0, 0 +112, 108, 106, 101 +113, 104, 0, 0 +114, 113, 112, 103 +115, 110, 108, 107 +116, 114, 111, 110 +117, 116, 115, 112 +118, 85, 0, 0 +119, 111, 0, 0 +120, 118, 114, 111 +121, 103, 0, 0 +122, 121, 120, 116 +123, 121, 0, 0 +124, 87, 0, 0 +125, 120, 119, 118 +126, 124, 122, 119 +127, 126, 0, 0 +128, 127, 126, 121 +129, 124, 0, 0 +130, 127, 0, 0 +131, 129, 128, 123 +132, 103, 0, 0 +133, 131, 125, 124 +134, 77, 0, 0 +135, 124, 0, 0 +136, 134, 133, 128 +137, 116, 0, 0 +138, 137, 131, 130 +139, 136, 134, 131 +140, 111, 0, 0 +141, 140, 135, 128 +142, 121, 0, 0 +143, 141, 140, 138 +144, 142, 140, 137 +145, 93, 0, 0 +146, 144, 143, 141 +147, 145, 143, 136 +148, 121, 0, 0 +149, 142, 140, 139 +150, 97, 0, 0 +151, 148, 0, 0 +152, 150, 149, 146 +153, 152, 0, 0 +154, 153, 149, 145 +155, 151, 150, 148 +156, 153, 151, 147 +157, 155, 152, 151 +158, 153, 152, 150 +159, 128, 0, 0 +160, 158, 157, 155 +161, 143, 0, 0 +162, 158, 155, 154 +163, 160, 157, 156 +164, 159, 158, 152 +165, 162, 157, 156 +166, 164, 163, 156 +167, 161, 0, 0 +168, 162, 159, 152 +169, 135, 0, 0 +170, 147, 0, 0 +171, 169, 166, 165 +172, 165, 0, 0 +173, 171, 168, 165 +174, 161, 0, 0 +175, 169, 0, 0 +176, 167, 165, 164 +177, 169, 0, 0 +178, 91, 0, 0 +179, 178, 177, 175 +180, 173, 170, 168 +181, 180, 175, 174 +182, 181, 176, 174 +183, 127, 0, 0 +184, 177, 176, 175 +185, 161, 0, 0 +186, 180, 178, 177 +187, 182, 181, 180 +188, 186, 183, 182 +189, 187, 184, 183 +190, 188, 184, 177 +191, 182, 0, 0 +192, 190, 178, 177 +193, 178, 0, 0 +194, 107, 0, 0 +195, 193, 192, 187 +196, 194, 187, 185 +197, 195, 193, 188 +198, 133, 0, 0 +199, 165, 0, 0 +200, 198, 197, 195 +201, 187, 0, 0 +202, 147, 0, 0 +203, 202, 196, 195 +204, 201, 200, 194 +205, 203, 200, 196 +206, 201, 197, 196 +207, 164, 0, 0 +208, 207, 205, 199 +209, 203, 0, 0 +210, 207, 206, 198 +211, 203, 201, 200 +212, 107, 0, 0 +213, 211, 208, 207 +214, 213, 211, 209 +215, 192, 0, 0 +216, 215, 213, 209 +217, 172, 0, 0 +218, 207, 0, 0 +219, 218, 215, 211 +220, 211, 210, 208 +221, 219, 215, 213 +222, 220, 217, 214 +223, 190, 0, 0 +224, 222, 217, 212 +225, 193, 0, 0 +226, 223, 219, 216 +227, 223, 218, 217 +228, 226, 217, 216 +229, 228, 225, 219 +230, 224, 223, 222 +231, 205, 0, 0 +232, 228, 223, 221 +233, 159, 0, 0 +234, 203, 0, 0 +235, 234, 229, 226 +236, 231, 0, 0 +237, 236, 233, 230 +238, 237, 236, 233 +239, 203, 0, 0 +240, 237, 235, 232 +241, 171, 0, 0 +242, 241, 236, 231 +243, 242, 238, 235 +244, 243, 240, 235 +245, 244, 241, 239 +246, 245, 244, 235 +247, 165, 0, 0 +248, 238, 234, 233 +249, 163, 0, 0 +250, 147, 0, 0 +251, 249, 247, 244 +252, 185, 0, 0 +253, 252, 247, 246 +254, 253, 252, 247 +255, 203, 0, 0 +256, 254, 251, 246 +257, 245, 0, 0 +258, 175, 0, 0 +259, 257, 253, 249 +260, 253, 252, 250 +261, 257, 255, 254 +262, 258, 254, 253 +263, 170, 0, 0 +264, 263, 255, 254 +265, 223, 0, 0 +266, 219, 0, 0 +267, 264, 261, 259 +268, 243, 0, 0 +269, 268, 263, 262 +270, 217, 0, 0 +271, 213, 0, 0 +272, 270, 266, 263 +273, 250, 0, 0 +274, 207, 0, 0 +275, 266, 265, 264 +276, 275, 273, 270 +277, 274, 271, 265 +278, 273, 0, 0 +279, 274, 0, 0 +280, 278, 275, 271 +281, 188, 0, 0 +282, 247, 0, 0 +283, 278, 276, 271 +284, 165, 0, 0 +285, 280, 278, 275 +286, 217, 0, 0 +287, 216, 0, 0 +288, 287, 278, 277 +289, 268, 0, 0 +290, 288, 287, 285 +291, 286, 280, 279 +292, 195, 0, 0 +293, 292, 287, 282 +294, 233, 0, 0 +295, 247, 0, 0 +296, 292, 287, 285 +297, 292, 0, 0 +298, 294, 290, 287 +299, 295, 293, 288 +300, 293, 0, 0 +301, 299, 296, 292 +302, 261, 0, 0 +303, 297, 291, 290 +304, 303, 302, 293 +305, 203, 0, 0 +306, 305, 303, 299 +307, 305, 303, 299 +308, 306, 299, 293 +309, 307, 302, 299 +310, 309, 305, 302 +311, 308, 306, 304 +312, 307, 302, 301 +313, 234, 0, 0 +314, 299, 0, 0 +315, 314, 306, 305 +316, 181, 0, 0 +317, 315, 313, 310 +318, 313, 312, 310 +319, 283, 0, 0 +320, 319, 317, 316 +321, 290, 0, 0 +322, 255, 0, 0 +323, 322, 320, 313 +324, 321, 320, 318 +325, 323, 320, 315 +326, 325, 323, 316 +327, 293, 0, 0 +328, 323, 321, 319 +329, 279, 0, 0 +330, 328, 323, 322 +331, 329, 325, 321 +332, 209, 0, 0 +333, 331, 0, 0 +334, 333, 330, 327 +335, 333, 328, 325 +336, 335, 332, 329 +337, 282, 0, 0 +338, 336, 335, 332 +339, 332, 329, 323 +340, 337, 336, 329 +341, 336, 330, 327 +342, 217, 0, 0 +343, 268, 0, 0 +344, 338, 334, 333 +345, 323, 0, 0 +346, 344, 339, 335 +347, 344, 337, 336 +348, 344, 341, 340 +349, 347, 344, 343 +350, 297, 0, 0 +351, 317, 0, 0 +352, 346, 341, 339 +353, 284, 0, 0 +354, 349, 341, 340 +355, 354, 350, 349 +356, 349, 347, 346 +357, 355, 347, 346 +358, 351, 350, 344 +359, 291, 0, 0 +360, 359, 335, 334 +361, 360, 357, 354 +362, 299, 0, 0 +363, 362, 356, 355 +364, 297, 0, 0 +365, 360, 359, 356 +366, 337, 0, 0 +367, 346, 0, 0 +368, 361, 359, 351 +369, 278, 0, 0 +370, 231, 0, 0 +371, 369, 368, 363 +372, 369, 365, 357 +373, 371, 366, 365 +374, 369, 368, 366 +375, 359, 0, 0 +376, 371, 369, 368 +377, 336, 0, 0 +378, 335, 0, 0 +379, 375, 370, 369 +380, 333, 0, 0 +381, 380, 379, 376 +382, 301, 0, 0 +383, 293, 0, 0 +384, 378, 369, 368 +385, 379, 0, 0 +386, 303, 0, 0 +387, 385, 379, 378 +388, 387, 385, 374 +389, 384, 380, 379 +390, 301, 0, 0 +391, 363, 0, 0 +392, 386, 382, 379 +393, 386, 0, 0 +394, 259, 0, 0 +395, 390, 389, 384 +396, 371, 0, 0 +397, 392, 387, 385 +398, 393, 392, 384 +399, 313, 0, 0 +400, 398, 397, 395 +401, 249, 0, 0 +402, 399, 398, 393 +403, 398, 395, 394 +404, 215, 0, 0 +405, 398, 397, 388 +406, 249, 0, 0 +407, 336, 0, 0 +408, 407, 403, 401 +409, 322, 0, 0 +410, 407, 406, 400 +411, 408, 401, 399 +412, 265, 0, 0 +413, 407, 406, 403 +414, 405, 401, 398 +415, 313, 0, 0 +416, 414, 411, 407 +417, 310, 0, 0 +418, 417, 415, 403 +419, 415, 414, 404 +420, 412, 410, 407 +421, 419, 417, 416 +422, 273, 0, 0 +423, 398, 0, 0 +424, 422, 417, 415 +425, 413, 0, 0 +426, 415, 414, 412 +427, 422, 421, 416 +428, 323, 0, 0 +429, 422, 421, 419 +430, 419, 417, 415 +431, 311, 0, 0 +432, 429, 428, 419 +433, 400, 0, 0 +434, 429, 423, 422 +435, 430, 426, 423 +436, 271, 0, 0 +437, 436, 435, 431 +438, 373, 0, 0 +439, 390, 0, 0 +440, 439, 437, 436 +441, 410, 0, 0 +442, 440, 437, 435 +443, 442, 437, 433 +444, 435, 432, 431 +445, 441, 439, 438 +446, 341, 0, 0 +447, 374, 0, 0 +448, 444, 442, 437 +449, 315, 0, 0 +450, 371, 0, 0 +451, 450, 441, 435 +452, 448, 447, 446 +453, 449, 447, 438 +454, 449, 445, 444 +455, 417, 0, 0 +456, 454, 445, 433 +457, 441, 0, 0 +458, 255, 0, 0 +459, 457, 454, 447 +460, 399, 0, 0 +461, 460, 455, 454 +462, 389, 0, 0 +463, 370, 0, 0 +464, 460, 455, 441 +465, 406, 0, 0 +466, 460, 455, 452 +467, 466, 461, 456 +468, 464, 459, 453 +469, 467, 464, 460 +470, 321, 0, 0 +471, 470, 0, 0 +472, 470, 469, 461 +473, 470, 467, 465 +474, 283, 0, 0 +475, 471, 467, 466 +476, 461, 0, 0 +477, 470, 462, 461 +478, 357, 0, 0 +479, 375, 0, 0 +480, 473, 467, 464 +481, 343, 0, 0 +482, 477, 476, 473 +483, 479, 477, 474 +484, 379, 0, 0 +485, 479, 469, 468 +486, 481, 478, 472 +487, 393, 0, 0 +488, 487, 485, 484 +489, 406, 0, 0 +490, 271, 0, 0 +491, 488, 485, 480 +492, 491, 485, 484 +493, 490, 488, 483 +494, 357, 0, 0 +495, 419, 0, 0 +496, 494, 491, 480 +497, 419, 0, 0 +498, 495, 489, 487 +499, 494, 493, 488 +500, 499, 494, 490 +501, 499, 497, 496 +502, 498, 497, 494 +503, 500, 0, 0 +504, 502, 490, 483 +505, 349, 0, 0 +506, 411, 0, 0 +507, 504, 501, 494 +508, 399, 0, 0 +509, 506, 502, 501 +510, 501, 500, 498 +511, 501, 0, 0 +512, 510, 507, 504 +513, 428, 0, 0 +514, 511, 509, 507 +515, 511, 508, 501 +516, 514, 511, 509 +517, 515, 507, 505 +518, 485, 0, 0 +519, 440, 0, 0 +520, 509, 507, 503 +521, 489, 0, 0 +522, 518, 509, 507 +523, 521, 517, 510 +524, 357, 0, 0 +525, 524, 521, 519 +526, 525, 521, 517 +527, 480, 0, 0 +528, 526, 522, 517 +529, 487, 0, 0 +530, 527, 523, 520 +531, 529, 525, 519 +532, 531, 0, 0 +533, 531, 530, 529 +534, 533, 529, 527 +535, 533, 529, 527 +536, 533, 531, 529 +537, 443, 0, 0 +538, 537, 536, 533 +539, 535, 534, 529 +540, 361, 0, 0 +541, 537, 531, 528 +542, 540, 539, 533 +543, 527, 0, 0 +544, 538, 535, 531 +545, 423, 0, 0 +546, 545, 544, 538 +547, 543, 540, 534 +548, 545, 543, 538 +549, 546, 545, 533 +550, 357, 0, 0 +551, 416, 0, 0 +552, 550, 547, 532 +553, 514, 0, 0 +554, 551, 546, 543 +555, 551, 546, 545 +556, 403, 0, 0 +557, 552, 551, 550 +558, 553, 549, 544 +559, 525, 0, 0 +560, 554, 551, 549 +561, 490, 0, 0 +562, 560, 558, 551 +563, 561, 554, 549 +564, 401, 0, 0 +565, 564, 559, 554 +566, 413, 0, 0 +567, 424, 0, 0 +568, 558, 557, 551 +569, 492, 0, 0 +570, 503, 0, 0 +571, 569, 566, 561 +572, 571, 564, 560 +573, 569, 567, 563 +574, 561, 0, 0 +575, 429, 0, 0 +576, 573, 572, 563 +577, 552, 0, 0 +578, 562, 556, 555 +579, 572, 570, 567 +580, 579, 576, 574 +581, 575, 574, 568 +582, 497, 0, 0 +583, 453, 0, 0 +584, 581, 571, 570 +585, 464, 0, 0 +586, 584, 581, 579 +587, 586, 581, 576 +588, 437, 0, 0 +589, 586, 585, 579 +590, 497, 0, 0 +591, 587, 585, 582 +592, 591, 573, 568 +593, 507, 0, 0 +594, 575, 0, 0 +595, 594, 593, 586 +596, 592, 591, 590 +597, 588, 585, 583 +598, 597, 592, 591 +599, 569, 0, 0 +600, 599, 590, 589 +601, 400, 0, 0 +602, 596, 594, 591 +603, 600, 599, 597 +604, 600, 598, 589 +605, 600, 598, 595 +606, 602, 599, 591 +607, 502, 0, 0 +608, 606, 602, 585 +609, 578, 0, 0 +610, 483, 0, 0 +611, 609, 607, 601 +612, 607, 602, 598 +613, 609, 603, 594 +614, 613, 612, 607 +615, 404, 0, 0 +616, 614, 602, 597 +617, 417, 0, 0 +618, 615, 604, 598 +619, 614, 611, 610 +620, 619, 618, 611 +621, 616, 615, 609 +622, 325, 0, 0 +623, 555, 0, 0 +624, 617, 615, 612 +625, 492, 0, 0 +626, 623, 621, 613 +627, 622, 617, 613 +628, 405, 0, 0 +629, 627, 624, 623 +630, 628, 626, 623 +631, 324, 0, 0 +632, 629, 619, 613 +633, 532, 0, 0 +634, 319, 0, 0 +635, 631, 625, 621 +636, 632, 628, 623 +637, 636, 628, 623 +638, 637, 633, 632 +639, 623, 0, 0 +640, 638, 637, 626 +641, 630, 0, 0 +642, 523, 0, 0 +643, 641, 640, 632 +644, 634, 633, 632 +645, 641, 637, 634 +646, 397, 0, 0 +647, 642, 0, 0 +648, 647, 626, 625 +649, 612, 0, 0 +650, 647, 0, 0 +651, 646, 638, 637 +652, 559, 0, 0 +653, 646, 645, 643 +654, 649, 643, 640 +655, 567, 0, 0 +656, 646, 638, 637 +657, 619, 0, 0 +658, 603, 0, 0 +659, 657, 655, 644 +660, 657, 656, 648 +661, 657, 650, 649 +662, 365, 0, 0 +663, 406, 0, 0 +664, 662, 660, 649 +665, 632, 0, 0 +666, 664, 659, 656 +667, 664, 660, 649 +668, 658, 656, 651 +669, 667, 665, 664 +670, 517, 0, 0 +671, 656, 0, 0 +672, 667, 666, 661 +673, 645, 0, 0 +674, 671, 665, 660 +675, 674, 672, 669 +676, 435, 0, 0 +677, 674, 673, 669 +678, 675, 673, 663 +679, 613, 0, 0 +680, 679, 650, 645 +681, 678, 672, 670 +682, 681, 679, 675 +683, 682, 677, 672 +684, 681, 671, 666 +685, 684, 682, 681 +686, 489, 0, 0 +687, 674, 0, 0 +688, 682, 674, 669 +689, 675, 0, 0 +690, 687, 683, 680 +691, 689, 685, 678 +692, 393, 0, 0 +693, 691, 685, 678 +694, 691, 681, 677 +695, 483, 0, 0 +696, 694, 686, 673 +697, 430, 0, 0 +698, 483, 0, 0 +699, 698, 689, 684 +700, 698, 695, 694 +701, 699, 697, 685 +702, 665, 0, 0 +703, 702, 696, 691 +704, 701, 699, 692 +705, 686, 0, 0 +706, 697, 695, 692 +707, 702, 699, 692 +708, 421, 0, 0 +709, 708, 706, 705 +710, 709, 696, 695 +711, 619, 0, 0 +712, 709, 708, 707 +713, 672, 0, 0 +714, 691, 0, 0 +715, 714, 711, 708 +716, 533, 0, 0 +717, 716, 710, 701 +718, 717, 716, 713 +719, 569, 0, 0 +720, 718, 712, 709 +721, 712, 0, 0 +722, 491, 0, 0 +723, 717, 710, 707 +724, 719, 716, 711 +725, 720, 719, 716 +726, 721, 0, 0 +727, 547, 0, 0 +728, 726, 725, 724 +729, 671, 0, 0 +730, 583, 0, 0 +731, 729, 725, 723 +732, 729, 728, 725 +733, 731, 726, 725 +734, 724, 721, 720 +735, 691, 0, 0 +736, 730, 728, 723 +737, 732, 0, 0 +738, 391, 0, 0 +739, 731, 723, 721 +740, 587, 0, 0 +741, 738, 733, 732 +742, 741, 738, 730 +743, 653, 0, 0 +744, 743, 733, 731 +745, 487, 0, 0 +746, 395, 0, 0 +747, 743, 741, 737 +748, 744, 743, 733 +749, 748, 743, 742 +750, 746, 741, 734 +751, 733, 0, 0 +752, 749, 732, 731 +753, 595, 0, 0 +754, 735, 0, 0 +755, 754, 745, 743 +756, 407, 0, 0 +757, 756, 751, 750 +758, 757, 746, 741 +759, 661, 0, 0 +760, 757, 747, 734 +761, 758, 0, 0 +762, 679, 0, 0 +763, 754, 749, 747 +764, 761, 759, 758 +765, 760, 755, 754 +766, 757, 747, 744 +767, 599, 0, 0 +768, 764, 751, 749 +769, 649, 0, 0 +770, 768, 765, 756 +771, 765, 756, 754 +772, 765, 0, 0 +773, 767, 765, 763 +774, 589, 0, 0 +775, 408, 0, 0 +776, 773, 764, 759 +777, 748, 0, 0 +778, 403, 0, 0 +779, 776, 771, 769 +780, 775, 772, 764 +781, 779, 765, 764 +782, 453, 0, 0 +783, 715, 0, 0 +784, 778, 775, 771 +785, 693, 0, 0 +786, 782, 780, 771 \ No newline at end of file diff --git a/fpga/prng/lfsr/tests/lfsr_test.py b/fpga/prng/lfsr/tests/lfsr_test.py new file mode 100644 index 0000000..2e6cedc --- /dev/null +++ b/fpga/prng/lfsr/tests/lfsr_test.py @@ -0,0 +1,67 @@ +import sys +import cocotb + +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, ReadOnly +from cocotb.drivers import BitDriver +from cocotb.binary import BinaryValue +from cocotb.result import TestFailure, TestSuccess, ReturnValue + +class tests: + def __init__(self, dut): + self.dut = dut + + @cocotb.coroutine + def does_it_run_test(self): + # This test will let the lfsr run for a bit. + # We will verify the every time a valid goes high the value outputted is different from the previous value + # This is testing that some operation is happening + + print("INFO: Performing does_it_run_test test") + yield RisingEdge(self.dut.clk) + + print("INFO: Setting our test passing conditon to true") + test_passing = True + + print("INFO: Making the seed 0xDEADBEEF") + self.dut.seed <= BinaryValue(0xDEADBEEF, 32, False) + yield RisingEdge(self.dut.clk) + + print("INFO: Pushing rst high to lock in the seed") + self.dut.rst <= BinaryValue(1, 1, False) + yield RisingEdge(self.dut.clk) + + print("INFO: Pushing rst low for operation") + self.dut.rst <= BinaryValue(0, 1, False) + yield RisingEdge(self.dut.clk) + + print("INFO: Pushing lfsr_enable high") + self.dut.lfsr_enable <= BinaryValue(1, 1, False) + yield RisingEdge(self.dut.clk) + + print("INFO: Establishing value to check against's initial value to 0xDEADBEEF") + lfsr_data = BinaryValue(0xDEADBEEF, 32, False) + + print("INFO: Running for 100 cycles") + for i in range(100): + yield RisingEdge(self.dut.clk) + + # Checking that the lfsr output has changed after a clock cycle + if self.dut.lfsr_output == lfsr_data: + # Mark the first time that this did not work + if test_passing == True: + print("ERROR: Test failed at lfsr loop %d", i) + print("ERROR: Old lfsr value was %d", lfsr_data) + print("ERROR: Dut lfsr value was %d", self.dut.lfsr_output) + + # Now we change the "passing" bool to false + test_passing = False + + # Making value to check the current value of the lfsr's output + lfsr_data = self.dut.lfsr_output.value + + print("INFO: Evaluating result") + if test_passing == True: + raise TestSuccess("INFO: Each cycle of LFSR was distinct") + else: + raise TestFailure("INFO: Each cycle of LFSR was not distinct") \ No newline at end of file diff --git a/fpga/prng/lfsr/tests/lfsr_test_suite.py b/fpga/prng/lfsr/tests/lfsr_test_suite.py new file mode 100644 index 0000000..d1d220a --- /dev/null +++ b/fpga/prng/lfsr/tests/lfsr_test_suite.py @@ -0,0 +1,79 @@ +import sys +import cocotb + +from cocotb.clock import Clock +from cocotb.triggers import Timer, RisingEdge, ReadOnly +from cocotb.utils import get_sim_time +from cocotb.drivers import BitDriver +from cocotb.drivers.avalon import AvalonMaster +from cocotb.drivers.avalon import AvalonSTPkts as AvalonDriver +from cocotb.monitors.avalon import AvalonSTPkts as AvalonMonitor +from cocotb.binary import BinaryValue +from cocotb.regression import TestFactory +from cocotb.scoreboard import Scoreboard +from cocotb.result import TestFailure, TestSuccess, ReturnValue + +from cocotb.generators.byte import random_data, get_bytes +from cocotb.generators.bit import wave, intermittent_single_cycles, random_50_percent + +import lfsr_test + +class TestModelTB(object): + # For each test initialise... + def __init__(self, dut): + # define the dut + self.dut = dut + + # Define the testing modules + self.lfsr_tests = lfsr_test.tests(self.dut) + + # This is a coroutine that will be used to reset the test bench at the start of each test + @cocotb.coroutine + def try_system_reset(self, duration=10): + print("INFO: Sending reset to components under test") + yield RisingEdge(self.dut.clk) + self.dut.rst <= BinaryValue(1, 1, False) + yield RisingEdge(self.dut.clk) + + self.dut.lfsr_enable <= BinaryValue(0, 1, False) + self.dut.seed <= BinaryValue(0, 128, False) + + yield Timer(duration) + yield RisingEdge(self.dut.clk) + self.dut.rst <= BinaryValue(0, 1, False) + print("INFO: Reset complete") + +@cocotb.coroutine +def run_test(dut, test_selection): + # Fork the clock process + print("INFO: Forking clock for sim") + cocotb.fork(Clock(dut.clk, 10000).start()) # 10000 has been chosen arbirtarily + + # Give the class a shorthand and set it up + print("INFO: Importing test class") + tb = TestModelTB(dut) + + # Reset component to bring to known state + yield RisingEdge(dut.clk) + yield tb.try_system_reset() + + print("INFO: Determining whch test to run") + # Determine which test to perform + test_suite = test_selection.split()[0] + test_chosen = test_selection.split()[1] + + print("INFO: Selecting test suite: " + test_suite) + print("INFO: Selecting test to run: " + test_chosen) + if test_suite == "lfsr_test": + if test_chosen == "does_it_run_test": + yield tb.lfsr_tests.does_it_run_test() + else: + raise Exception("Invalid test selected") + else: + raise Exception("Invalid test suite selected") + +# Define the regression tests +factory = TestFactory(run_test) +factory.add_option("test_selection", ["lfsr_test does_it_run_test"]) + +factory.generate_tests() \ No newline at end of file diff --git a/fpga/prng/lfsr/tests/lfsr_test_wrapper.vhd b/fpga/prng/lfsr/tests/lfsr_test_wrapper.vhd new file mode 100644 index 0000000..e5236ee --- /dev/null +++ b/fpga/prng/lfsr/tests/lfsr_test_wrapper.vhd @@ -0,0 +1,52 @@ +-- This file is a wrapper for the LSFR variants so that they can be tested properly using the testbenching methods +-- This wrapper is not meant to see use outside of simulation + +-- The ports are as follows: +-- clk - Input port for a clocking signal +-- rst - Input port for a reset signal. Synchronous +-- en - Enables the specific entity being tested. Follows the size port +-- mode - This will determine the architecture being tested. 0 for fibonacci, 1 for galois +-- size - This determines which lfsr we are looking at in terms of taps +-- seed - This is used to set the seed in the entityies +-- output - This outputs the PRBS values generated by the LFSR under test + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity lfsr_test_wrapper is + generic + ( + SIZE : natural := 32 + ); + port + ( + clk : in std_logic; + rst : in std_logic; + seed : in std_logic_vector(SIZE - 1 downto 0); + + lfsr_enable : in std_logic; + lfsr_output : out std_logic_vector(SIZE - 1 downto 0) + ); +end entity; + +architecture tb of lfsr_test_wrapper is + +begin + + lfsr_i : entity work.lfsr + generic map + ( + SIZE => SIZE + ) + port map + ( + clk => clk, + rst => rst, + en => lfsr_enable, + + seed => seed, + output => lfsr_output + ); + +end tb; \ No newline at end of file diff --git a/fpga/prng/lfsr/vhdl/lfsr.vhd b/fpga/prng/lfsr/vhdl/lfsr.vhd new file mode 100644 index 0000000..3bb3768 --- /dev/null +++ b/fpga/prng/lfsr/vhdl/lfsr.vhd @@ -0,0 +1,98 @@ +-- This component is designed to have it's output stream size set at compilation and provide PRBS values appropriate for +-- the size defined. +-- You can seed this PRBS generator by changing the value of the seed port while in reset +-- This design follows that of a fibonacci linear feedback shift register + +-- The generics are as follows: +-- SIZE - This denotes the size of the output vector. This also effects the size of the seed, and the placement of taps in +-- the component + +-- The ports are as follows: +-- clk - Input port for the clocking signal +-- rst - Input port for the reset signal. Should be synchronous. +-- en - The enable port. The compoent will only output new data when this is high +-- seed - This input is the starting value of the PRBS generator when reset is enabled. It will affect subsequent outputs +-- output - This output is PBRS value generated by the componet. It will change every cycle if enable is high + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.lfsr_package.all; + +entity lfsr is + generic + ( + SIZE : natural := 128 + ); + port + ( + clk : in std_logic; + rst : in std_logic; + en : in std_logic; + + seed : in std_logic_vector(SIZE - 1 downto 0); + output : out std_logic_vector(SIZE - 1 downto 0) + ); +end entity; + +architecture rtl of lfsr is + -- signals + signal shift_register : std_logic_vector(SIZE - 1 downto 0); + signal feedback_in : std_logic; + signal feedback_out : std_logic_vector(0 to (number_of_taps(SIZE) - 1)); + +begin + + shift_register_proc : process (clk) + begin + if rising_edge(clk) then + if en = '1' then + shift_register(SIZE - 1 downto 1) <= shift_register(SIZE - 2 downto 0); + shift_register(0) <= feedback_in; + end if; + + if rst = '1' then + shift_register <= seed; + end if; + end if; + end process; + + feedback_calc_gen : for i in 1 to (number_of_taps(SIZE) - 1) generate + feedback_out(i) <= shift_register(tap_position(SIZE, i + 1) - 1) xor feedback_out(i - 1); + end generate; + + feedback_out(0) <= shift_register(SIZE - 1); + feedback_in <= feedback_out(number_of_taps(SIZE) - 1); + + output <= shift_register; + +end rtl; + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fpga/prng/lfsr/vhdl/lfsr_package.vhd b/fpga/prng/lfsr/vhdl/lfsr_package.vhd new file mode 100644 index 0000000..ce39f4e --- /dev/null +++ b/fpga/prng/lfsr/vhdl/lfsr_package.vhd @@ -0,0 +1,958 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package lfsr_package is + type number_of_taps_type is array(2 to 786) of natural; + type tap_position_type is array(2 to 786, 1 to 4) of natural; + + constant number_of_taps : number_of_taps_type := + ( + 2, 2, 2, 2, 2, + 2, 4, 2, 2, 2, + 4, 4, 4, 2, 4, + 2, 2, 4, 2, 2, + 2, 2, 4, 2, 4, + 4, 2, 2, 4, 2, + 4, 2, 4, 2, 2, + 4, 4, 2, 4, 2, + 4, 4, 4, 4, 4, + 2, 4, 2, 4, 4, + 2, 4, 4, 2, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 2, 4, + 4, 2, 4, 4, 2, + 4, 2, 4, 4, 4, + 4, 4, 2, 4, 2, + 4, 4, 2, 4, 4, + 2, 4, 2, 4, 4, + 4, 2, 2, 2, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 2, 2, + 4, 2, 4, 4, 2, + 4, 2, 4, 4, 4, + 4, 2, 2, 4, 2, + 4, 2, 2, 4, 4, + 2, 4, 2, 2, 4, + 2, 4, 2, 2, 4, + 2, 4, 4, 2, 4, + 2, 4, 4, 2, 4, + 4, 2, 4, 2, 2, + 4, 2, 4, 4, 4, + 4, 4, 2, 4, 2, + 4, 4, 4, 4, 4, + 2, 4, 2, 2, 4, + 2, 4, 2, 2, 4, + 2, 2, 4, 4, 4, + 4, 2, 4, 2, 4, + 4, 4, 4, 4, 2, + 4, 2, 2, 4, 4, + 4, 2, 2, 4, 2, + 2, 4, 4, 4, 4, + 2, 4, 2, 4, 4, + 2, 4, 4, 2, 4, + 2, 2, 4, 4, 4, + 4, 2, 4, 2, 4, + 4, 4, 4, 4, 2, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 2, + 4, 4, 4, 4, 4, + 2, 4, 2, 2, 4, + 2, 4, 4, 2, 4, + 2, 2, 4, 4, 4, + 4, 2, 4, 2, 2, + 4, 2, 4, 2, 2, + 4, 2, 2, 4, 4, + 4, 2, 2, 4, 2, + 2, 4, 2, 4, 2, + 2, 4, 2, 4, 4, + 2, 4, 2, 2, 4, + 2, 4, 4, 2, 4, + 2, 4, 4, 2, 4, + 4, 4, 4, 4, 4, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 2, + 2, 4, 4, 4, 4, + 2, 4, 2, 4, 4, + 2, 2, 4, 4, 4, + 2, 4, 4, 4, 4, + 2, 2, 4, 2, 4, + 4, 4, 4, 2, 2, + 4, 2, 4, 4, 4, + 4, 4, 2, 4, 4, + 2, 4, 2, 4, 2, + 2, 4, 2, 2, 4, + 4, 4, 4, 2, 4, + 2, 2, 4, 2, 4, + 2, 2, 4, 2, 2, + 4, 4, 4, 2, 2, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 2, + 4, 4, 2, 4, 2, + 2, 4, 2, 4, 4, + 2, 4, 4, 2, 4, + 2, 4, 4, 4, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 4, 2, + 4, 2, 4, 4, 2, + 4, 2, 2, 4, 2, + 4, 4, 4, 4, 2, + 2, 4, 2, 2, 4, + 4, 4, 4, 2, 4, + 2, 2, 4, 2, 4, + 2, 2, 4, 2, 4, + 4, 4, 4, 2, 2, + 4, 4, 2, 4, 2, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 4, + 2, 4, 2, 2, 4, + 4, 4, 2, 2, 4, + 2, 4, 4, 4, 4, + 4, 2, 4, 2, 2, + 4, 2, 4, 4, 2, + 4, 2, 4, 4, 4, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 4, + 2, 4, 2, 4, 4, + 2, 4, 4, 4, 4, + 2, 4, 4, 2, 4, + 4, 2, 4, 2, 4, + 4, 4, 4, 2, 2, + 4, 2, 4, 4, 2, + 4, 4, 2, 4, 2, + 4, 4, 2, 4, 2, + 2, 4, 2, 2, 4, + 4, 4, 2, 2, 4, + 2, 4, 4, 4, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 2, 4, + 4, 2, 2, 4, 4, + 4, 4, 2, 4, 2, + 4, 4, 4, 4, 4, + 2, 4, 2, 2, 4, + 4, 4, 4, 2, 4, + 2, 4, 4, 4, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 4, 2, + 4, 2, 2, 4, 4, + 4, 4, 2, 4, 2, + 2, 4, 4, 4, 2, + 2, 4, 2, 2, 4, + 2, 4, 4, 2, 4, + 2, 2, 4, 4, 4, + 2, 2, 4, 2, 4, + 4, 4, 4, 2, 2, + 4, 2, 4, 4, 2, + 4, 4, 2, 4, 4, + 4, 4, 4, 4, 2, + 2, 4, 2, 4, 4, + 2, 4, 4, 2, 4, + 2, 2, 4, 4, 4, + 2, 4, 4, 2, 4, + 4, 2, 4, 4, 2, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 2, + 2, 4, 4, 4, 2, + 2, 4, 2, 2, 4, + 4, 4, 4, 2, 4, + 2, 2, 4, 2, 4, + 4, 2, 4, 2, 2, + 4, 4, 4, 4, 2, + 4, 2, 2, 4, 2, + 4, 4, 2, 4, 2, + 2, 4, 4, 4, 4, + 2, 4, 2, 4, 4, + 2, 4, 2, 2, 4, + 2, 2, 4, 4, 4, + 2, 2, 4, 2, 4 + ); + + constant tap_position : tap_position_type := + ( + ( 2, 1, 0, 0), + ( 3, 2, 0, 0), + ( 4, 3, 0, 0), + ( 5, 3, 0, 0), + ( 6, 5, 0, 0), + ( 7, 6, 0, 0), + ( 8, 6, 5, 4), + ( 9, 5, 0, 0), + ( 10, 7, 0, 0), + ( 11, 9, 0, 0), + ( 12, 11, 8, 6), + ( 13, 12, 10, 9), + ( 14, 13, 11, 9), + ( 15, 14, 0, 0), + ( 16, 14, 13, 11), + ( 17, 14, 0, 0), + ( 18, 11, 0, 0), + ( 19, 18, 17, 14), + ( 20, 17, 0, 0), + ( 21, 19, 0, 0), + ( 22, 21, 0, 0), + ( 23, 18, 0, 0), + ( 24, 23, 21, 20), + ( 25, 22, 0, 0), + ( 26, 25, 24, 20), + ( 27, 26, 25, 22), + ( 28, 25, 0, 0), + ( 29, 27, 0, 0), + ( 30, 29, 26, 24), + ( 31, 28, 0, 0), + ( 32, 30, 26, 25), + ( 33, 20, 0, 0), + ( 34, 31, 30, 26), + ( 35, 33, 0, 0), + ( 36, 25, 0, 0), + ( 37, 36, 33, 31), + ( 38, 37, 33, 32), + ( 39, 35, 0, 0), + ( 40, 37, 36, 35), + ( 41, 38, 0, 0), + ( 42, 40, 37, 35), + ( 43, 42, 38, 37), + ( 44, 42, 39, 38), + ( 45, 44, 42, 41), + ( 46, 40, 39, 38), + ( 47, 42, 0, 0), + ( 48, 44, 41, 39), + ( 49, 40, 0, 0), + ( 50, 48, 47, 46), + ( 51, 50, 48, 45), + ( 52, 49, 0, 0), + ( 53, 52, 51, 47), + ( 54, 51, 48, 46), + ( 55, 31, 0, 0), + ( 56, 54, 52, 49), + ( 57, 50, 0, 0), + ( 58, 39, 0, 0), + ( 59, 57, 55, 52), + ( 60, 59, 0, 0), + ( 61, 60, 59, 56), + ( 62, 59, 57, 56), + ( 63, 62, 0, 0), + ( 64, 63, 61, 60), + ( 65, 47, 0, 0), + ( 66, 60, 58, 57), + ( 67, 66, 65, 62), + ( 68, 59, 0, 0), + ( 69, 67, 64, 63), + ( 70, 69, 67, 65), + ( 71, 65, 0, 0), + ( 72, 69, 63, 62), + ( 73, 48, 0, 0), + ( 74, 71, 70, 67), + ( 75, 74, 72, 69), + ( 76, 74, 72, 71), + ( 77, 75, 72, 71), + ( 78, 77, 76, 71), + ( 79, 70, 0, 0), + ( 80, 78, 76, 71), + ( 81, 77, 0, 0), + ( 82, 78, 76, 73), + ( 83, 81, 79, 76), + ( 84, 71, 0, 0), + ( 85, 84, 83, 77), + ( 86, 84, 81, 80), + ( 87, 74, 0, 0), + ( 88, 80, 79, 77), + ( 89, 51, 0, 0), + ( 90, 88, 87, 85), + ( 91, 90, 86, 83), + ( 92, 90, 87, 86), + ( 93, 91, 0, 0), + ( 94, 73, 0, 0), + ( 95, 84, 0, 0), + ( 96, 90, 87, 86), + ( 97, 91, 0, 0), + ( 98, 87, 0, 0), + ( 99, 95, 94, 92), + (100, 63, 0, 0), + (101, 100, 95, 94), + (102, 99, 97, 96), + (103, 94, 0, 0), + (104, 103, 94, 93), + (105, 89, 0, 0), + (106, 91, 0, 0), + (107, 105, 99, 98), + (108, 77, 0, 0), + (109, 107, 105, 104), + (110, 109, 106, 104), + (111, 101, 0, 0), + (112, 108, 106, 101), + (113, 104, 0, 0), + (114, 113, 112, 103), + (115, 110, 108, 107), + (116, 114, 111, 110), + (117, 116, 115, 112), + (118, 85, 0, 0), + (119, 111, 0, 0), + (120, 118, 114, 111), + (121, 103, 0, 0), + (122, 121, 120, 116), + (123, 121, 0, 0), + (124, 87, 0, 0), + (125, 120, 119, 118), + (126, 124, 122, 119), + (127, 126, 0, 0), + (128, 127, 126, 121), + (129, 124, 0, 0), + (130, 127, 0, 0), + (131, 129, 128, 123), + (132, 103, 0, 0), + (133, 131, 125, 124), + (134, 77, 0, 0), + (135, 124, 0, 0), + (136, 134, 133, 128), + (137, 116, 0, 0), + (138, 137, 131, 130), + (139, 136, 134, 131), + (140, 111, 0, 0), + (141, 140, 135, 128), + (142, 121, 0, 0), + (143, 141, 140, 138), + (144, 142, 140, 137), + (145, 93, 0, 0), + (146, 144, 143, 141), + (147, 145, 143, 136), + (148, 121, 0, 0), + (149, 142, 140, 139), + (150, 97, 0, 0), + (151, 148, 0, 0), + (152, 150, 149, 146), + (153, 152, 0, 0), + (154, 153, 149, 145), + (155, 151, 150, 148), + (156, 153, 151, 147), + (157, 155, 152, 151), + (158, 153, 152, 150), + (159, 128, 0, 0), + (160, 158, 157, 155), + (161, 143, 0, 0), + (162, 158, 155, 154), + (163, 160, 157, 156), + (164, 159, 158, 152), + (165, 162, 157, 156), + (166, 164, 163, 156), + (167, 161, 0, 0), + (168, 162, 159, 152), + (169, 135, 0, 0), + (170, 147, 0, 0), + (171, 169, 166, 165), + (172, 165, 0, 0), + (173, 171, 168, 165), + (174, 161, 0, 0), + (175, 169, 0, 0), + (176, 167, 165, 164), + (177, 169, 0, 0), + (178, 91, 0, 0), + (179, 178, 177, 175), + (180, 173, 170, 168), + (181, 180, 175, 174), + (182, 181, 176, 174), + (183, 127, 0, 0), + (184, 177, 176, 175), + (185, 161, 0, 0), + (186, 180, 178, 177), + (187, 182, 181, 180), + (188, 186, 183, 182), + (189, 187, 184, 183), + (190, 188, 184, 177), + (191, 182, 0, 0), + (192, 190, 178, 177), + (193, 178, 0, 0), + (194, 107, 0, 0), + (195, 193, 192, 187), + (196, 194, 187, 185), + (197, 195, 193, 188), + (198, 133, 0, 0), + (199, 165, 0, 0), + (200, 198, 197, 195), + (201, 187, 0, 0), + (202, 147, 0, 0), + (203, 202, 196, 195), + (204, 201, 200, 194), + (205, 203, 200, 196), + (206, 201, 197, 196), + (207, 164, 0, 0), + (208, 207, 205, 199), + (209, 203, 0, 0), + (210, 207, 206, 198), + (211, 203, 201, 200), + (212, 107, 0, 0), + (213, 211, 208, 207), + (214, 213, 211, 209), + (215, 192, 0, 0), + (216, 215, 213, 209), + (217, 172, 0, 0), + (218, 207, 0, 0), + (219, 218, 215, 211), + (220, 211, 210, 208), + (221, 219, 215, 213), + (222, 220, 217, 214), + (223, 190, 0, 0), + (224, 222, 217, 212), + (225, 193, 0, 0), + (226, 223, 219, 216), + (227, 223, 218, 217), + (228, 226, 217, 216), + (229, 228, 225, 219), + (230, 224, 223, 222), + (231, 205, 0, 0), + (232, 228, 223, 221), + (233, 159, 0, 0), + (234, 203, 0, 0), + (235, 234, 229, 226), + (236, 231, 0, 0), + (237, 236, 233, 230), + (238, 237, 236, 233), + (239, 203, 0, 0), + (240, 237, 235, 232), + (241, 171, 0, 0), + (242, 241, 236, 231), + (243, 242, 238, 235), + (244, 243, 240, 235), + (245, 244, 241, 239), + (246, 245, 244, 235), + (247, 165, 0, 0), + (248, 238, 234, 233), + (249, 163, 0, 0), + (250, 147, 0, 0), + (251, 249, 247, 244), + (252, 185, 0, 0), + (253, 252, 247, 246), + (254, 253, 252, 247), + (255, 203, 0, 0), + (256, 254, 251, 246), + (257, 245, 0, 0), + (258, 175, 0, 0), + (259, 257, 253, 249), + (260, 253, 252, 250), + (261, 257, 255, 254), + (262, 258, 254, 253), + (263, 170, 0, 0), + (264, 263, 255, 254), + (265, 223, 0, 0), + (266, 219, 0, 0), + (267, 264, 261, 259), + (268, 243, 0, 0), + (269, 268, 263, 262), + (270, 217, 0, 0), + (271, 213, 0, 0), + (272, 270, 266, 263), + (273, 250, 0, 0), + (274, 207, 0, 0), + (275, 266, 265, 264), + (276, 275, 273, 270), + (277, 274, 271, 265), + (278, 273, 0, 0), + (279, 274, 0, 0), + (280, 278, 275, 271), + (281, 188, 0, 0), + (282, 247, 0, 0), + (283, 278, 276, 271), + (284, 165, 0, 0), + (285, 280, 278, 275), + (286, 217, 0, 0), + (287, 216, 0, 0), + (288, 287, 278, 277), + (289, 268, 0, 0), + (290, 288, 287, 285), + (291, 286, 280, 279), + (292, 195, 0, 0), + (293, 292, 287, 282), + (294, 233, 0, 0), + (295, 247, 0, 0), + (296, 292, 287, 285), + (297, 292, 0, 0), + (298, 294, 290, 287), + (299, 295, 293, 288), + (300, 293, 0, 0), + (301, 299, 296, 292), + (302, 261, 0, 0), + (303, 297, 291, 290), + (304, 303, 302, 293), + (305, 203, 0, 0), + (306, 305, 303, 299), + (307, 305, 303, 299), + (308, 306, 299, 293), + (309, 307, 302, 299), + (310, 309, 305, 302), + (311, 308, 306, 304), + (312, 307, 302, 301), + (313, 234, 0, 0), + (314, 299, 0, 0), + (315, 314, 306, 305), + (316, 181, 0, 0), + (317, 315, 313, 310), + (318, 313, 312, 310), + (319, 283, 0, 0), + (320, 319, 317, 316), + (321, 290, 0, 0), + (322, 255, 0, 0), + (323, 322, 320, 313), + (324, 321, 320, 318), + (325, 323, 320, 315), + (326, 325, 323, 316), + (327, 293, 0, 0), + (328, 323, 321, 319), + (329, 279, 0, 0), + (330, 328, 323, 322), + (331, 329, 325, 321), + (332, 209, 0, 0), + (333, 331, 0, 0), + (334, 333, 330, 327), + (335, 333, 328, 325), + (336, 335, 332, 329), + (337, 282, 0, 0), + (338, 336, 335, 332), + (339, 332, 329, 323), + (340, 337, 336, 329), + (341, 336, 330, 327), + (342, 217, 0, 0), + (343, 268, 0, 0), + (344, 338, 334, 333), + (345, 323, 0, 0), + (346, 344, 339, 335), + (347, 344, 337, 336), + (348, 344, 341, 340), + (349, 347, 344, 343), + (350, 297, 0, 0), + (351, 317, 0, 0), + (352, 346, 341, 339), + (353, 284, 0, 0), + (354, 349, 341, 340), + (355, 354, 350, 349), + (356, 349, 347, 346), + (357, 355, 347, 346), + (358, 351, 350, 344), + (359, 291, 0, 0), + (360, 359, 335, 334), + (361, 360, 357, 354), + (362, 299, 0, 0), + (363, 362, 356, 355), + (364, 297, 0, 0), + (365, 360, 359, 356), + (366, 337, 0, 0), + (367, 346, 0, 0), + (368, 361, 359, 351), + (369, 278, 0, 0), + (370, 231, 0, 0), + (371, 369, 368, 363), + (372, 369, 365, 357), + (373, 371, 366, 365), + (374, 369, 368, 366), + (375, 359, 0, 0), + (376, 371, 369, 368), + (377, 336, 0, 0), + (378, 335, 0, 0), + (379, 375, 370, 369), + (380, 333, 0, 0), + (381, 380, 379, 376), + (382, 301, 0, 0), + (383, 293, 0, 0), + (384, 378, 369, 368), + (385, 379, 0, 0), + (386, 303, 0, 0), + (387, 385, 379, 378), + (388, 387, 385, 374), + (389, 384, 380, 379), + (390, 301, 0, 0), + (391, 363, 0, 0), + (392, 386, 382, 379), + (393, 386, 0, 0), + (394, 259, 0, 0), + (395, 390, 389, 384), + (396, 371, 0, 0), + (397, 392, 387, 385), + (398, 393, 392, 384), + (399, 313, 0, 0), + (400, 398, 397, 395), + (401, 249, 0, 0), + (402, 399, 398, 393), + (403, 398, 395, 394), + (404, 215, 0, 0), + (405, 398, 397, 388), + (406, 249, 0, 0), + (407, 336, 0, 0), + (408, 407, 403, 401), + (409, 322, 0, 0), + (410, 407, 406, 400), + (411, 408, 401, 399), + (412, 265, 0, 0), + (413, 407, 406, 403), + (414, 405, 401, 398), + (415, 313, 0, 0), + (416, 414, 411, 407), + (417, 310, 0, 0), + (418, 417, 415, 403), + (419, 415, 414, 404), + (420, 412, 410, 407), + (421, 419, 417, 416), + (422, 273, 0, 0), + (423, 398, 0, 0), + (424, 422, 417, 415), + (425, 413, 0, 0), + (426, 415, 414, 412), + (427, 422, 421, 416), + (428, 323, 0, 0), + (429, 422, 421, 419), + (430, 419, 417, 415), + (431, 311, 0, 0), + (432, 429, 428, 419), + (433, 400, 0, 0), + (434, 429, 423, 422), + (435, 430, 426, 423), + (436, 271, 0, 0), + (437, 436, 435, 431), + (438, 373, 0, 0), + (439, 390, 0, 0), + (440, 439, 437, 436), + (441, 410, 0, 0), + (442, 440, 437, 435), + (443, 442, 437, 433), + (444, 435, 432, 431), + (445, 441, 439, 438), + (446, 341, 0, 0), + (447, 374, 0, 0), + (448, 444, 442, 437), + (449, 315, 0, 0), + (450, 371, 0, 0), + (451, 450, 441, 435), + (452, 448, 447, 446), + (453, 449, 447, 438), + (454, 449, 445, 444), + (455, 417, 0, 0), + (456, 454, 445, 433), + (457, 441, 0, 0), + (458, 255, 0, 0), + (459, 457, 454, 447), + (460, 399, 0, 0), + (461, 460, 455, 454), + (462, 389, 0, 0), + (463, 370, 0, 0), + (464, 460, 455, 441), + (465, 406, 0, 0), + (466, 460, 455, 452), + (467, 466, 461, 456), + (468, 464, 459, 453), + (469, 467, 464, 460), + (470, 321, 0, 0), + (471, 470, 0, 0), + (472, 470, 469, 461), + (473, 470, 467, 465), + (474, 283, 0, 0), + (475, 471, 467, 466), + (476, 461, 0, 0), + (477, 470, 462, 461), + (478, 357, 0, 0), + (479, 375, 0, 0), + (480, 473, 467, 464), + (481, 343, 0, 0), + (482, 477, 476, 473), + (483, 479, 477, 474), + (484, 379, 0, 0), + (485, 479, 469, 468), + (486, 481, 478, 472), + (487, 393, 0, 0), + (488, 487, 485, 484), + (489, 406, 0, 0), + (490, 271, 0, 0), + (491, 488, 485, 480), + (492, 491, 485, 484), + (493, 490, 488, 483), + (494, 357, 0, 0), + (495, 419, 0, 0), + (496, 494, 491, 480), + (497, 419, 0, 0), + (498, 495, 489, 487), + (499, 494, 493, 488), + (500, 499, 494, 490), + (501, 499, 497, 496), + (502, 498, 497, 494), + (503, 500, 0, 0), + (504, 502, 490, 483), + (505, 349, 0, 0), + (506, 411, 0, 0), + (507, 504, 501, 494), + (508, 399, 0, 0), + (509, 506, 502, 501), + (510, 501, 500, 498), + (511, 501, 0, 0), + (512, 510, 507, 504), + (513, 428, 0, 0), + (514, 511, 509, 507), + (515, 511, 508, 501), + (516, 514, 511, 509), + (517, 515, 507, 505), + (518, 485, 0, 0), + (519, 440, 0, 0), + (520, 509, 507, 503), + (521, 489, 0, 0), + (522, 518, 509, 507), + (523, 521, 517, 510), + (524, 357, 0, 0), + (525, 524, 521, 519), + (526, 525, 521, 517), + (527, 480, 0, 0), + (528, 526, 522, 517), + (529, 487, 0, 0), + (530, 527, 523, 520), + (531, 529, 525, 519), + (532, 531, 0, 0), + (533, 531, 530, 529), + (534, 533, 529, 527), + (535, 533, 529, 527), + (536, 533, 531, 529), + (537, 443, 0, 0), + (538, 537, 536, 533), + (539, 535, 534, 529), + (540, 361, 0, 0), + (541, 537, 531, 528), + (542, 540, 539, 533), + (543, 527, 0, 0), + (544, 538, 535, 531), + (545, 423, 0, 0), + (546, 545, 544, 538), + (547, 543, 540, 534), + (548, 545, 543, 538), + (549, 546, 545, 533), + (550, 357, 0, 0), + (551, 416, 0, 0), + (552, 550, 547, 532), + (553, 514, 0, 0), + (554, 551, 546, 543), + (555, 551, 546, 545), + (556, 403, 0, 0), + (557, 552, 551, 550), + (558, 553, 549, 544), + (559, 525, 0, 0), + (560, 554, 551, 549), + (561, 490, 0, 0), + (562, 560, 558, 551), + (563, 561, 554, 549), + (564, 401, 0, 0), + (565, 564, 559, 554), + (566, 413, 0, 0), + (567, 424, 0, 0), + (568, 558, 557, 551), + (569, 492, 0, 0), + (570, 503, 0, 0), + (571, 569, 566, 561), + (572, 571, 564, 560), + (573, 569, 567, 563), + (574, 561, 0, 0), + (575, 429, 0, 0), + (576, 573, 572, 563), + (577, 552, 0, 0), + (578, 562, 556, 555), + (579, 572, 570, 567), + (580, 579, 576, 574), + (581, 575, 574, 568), + (582, 497, 0, 0), + (583, 453, 0, 0), + (584, 581, 571, 570), + (585, 464, 0, 0), + (586, 584, 581, 579), + (587, 586, 581, 576), + (588, 437, 0, 0), + (589, 586, 585, 579), + (590, 497, 0, 0), + (591, 587, 585, 582), + (592, 591, 573, 568), + (593, 507, 0, 0), + (594, 575, 0, 0), + (595, 594, 593, 586), + (596, 592, 591, 590), + (597, 588, 585, 583), + (598, 597, 592, 591), + (599, 569, 0, 0), + (600, 599, 590, 589), + (601, 400, 0, 0), + (602, 596, 594, 591), + (603, 600, 599, 597), + (604, 600, 598, 589), + (605, 600, 598, 595), + (606, 602, 599, 591), + (607, 502, 0, 0), + (608, 606, 602, 585), + (609, 578, 0, 0), + (610, 483, 0, 0), + (611, 609, 607, 601), + (612, 607, 602, 598), + (613, 609, 603, 594), + (614, 613, 612, 607), + (615, 404, 0, 0), + (616, 614, 602, 597), + (617, 417, 0, 0), + (618, 615, 604, 598), + (619, 614, 611, 610), + (620, 619, 618, 611), + (621, 616, 615, 609), + (622, 325, 0, 0), + (623, 555, 0, 0), + (624, 617, 615, 612), + (625, 492, 0, 0), + (626, 623, 621, 613), + (627, 622, 617, 613), + (628, 405, 0, 0), + (629, 627, 624, 623), + (630, 628, 626, 623), + (631, 324, 0, 0), + (632, 629, 619, 613), + (633, 532, 0, 0), + (634, 319, 0, 0), + (635, 631, 625, 621), + (636, 632, 628, 623), + (637, 636, 628, 623), + (638, 637, 633, 632), + (639, 623, 0, 0), + (640, 638, 637, 626), + (641, 630, 0, 0), + (642, 523, 0, 0), + (643, 641, 640, 632), + (644, 634, 633, 632), + (645, 641, 637, 634), + (646, 397, 0, 0), + (647, 642, 0, 0), + (648, 647, 626, 625), + (649, 612, 0, 0), + (650, 647, 0, 0), + (651, 646, 638, 637), + (652, 559, 0, 0), + (653, 646, 645, 643), + (654, 649, 643, 640), + (655, 567, 0, 0), + (656, 646, 638, 637), + (657, 619, 0, 0), + (658, 603, 0, 0), + (659, 657, 655, 644), + (660, 657, 656, 648), + (661, 657, 650, 649), + (662, 365, 0, 0), + (663, 406, 0, 0), + (664, 662, 660, 649), + (665, 632, 0, 0), + (666, 664, 659, 656), + (667, 664, 660, 649), + (668, 658, 656, 651), + (669, 667, 665, 664), + (670, 517, 0, 0), + (671, 656, 0, 0), + (672, 667, 666, 661), + (673, 645, 0, 0), + (674, 671, 665, 660), + (675, 674, 672, 669), + (676, 435, 0, 0), + (677, 674, 673, 669), + (678, 675, 673, 663), + (679, 613, 0, 0), + (680, 679, 650, 645), + (681, 678, 672, 670), + (682, 681, 679, 675), + (683, 682, 677, 672), + (684, 681, 671, 666), + (685, 684, 682, 681), + (686, 489, 0, 0), + (687, 674, 0, 0), + (688, 682, 674, 669), + (689, 675, 0, 0), + (690, 687, 683, 680), + (691, 689, 685, 678), + (692, 393, 0, 0), + (693, 691, 685, 678), + (694, 691, 681, 677), + (695, 483, 0, 0), + (696, 694, 686, 673), + (697, 430, 0, 0), + (698, 483, 0, 0), + (699, 698, 689, 684), + (700, 698, 695, 694), + (701, 699, 697, 685), + (702, 665, 0, 0), + (703, 702, 696, 691), + (704, 701, 699, 692), + (705, 686, 0, 0), + (706, 697, 695, 692), + (707, 702, 699, 692), + (708, 421, 0, 0), + (709, 708, 706, 705), + (710, 709, 696, 695), + (711, 619, 0, 0), + (712, 709, 708, 707), + (713, 672, 0, 0), + (714, 691, 0, 0), + (715, 714, 711, 708), + (716, 533, 0, 0), + (717, 716, 710, 701), + (718, 717, 716, 713), + (719, 569, 0, 0), + (720, 718, 712, 709), + (721, 712, 0, 0), + (722, 491, 0, 0), + (723, 717, 710, 707), + (724, 719, 716, 711), + (725, 720, 719, 716), + (726, 721, 0, 0), + (727, 547, 0, 0), + (728, 726, 725, 724), + (729, 671, 0, 0), + (730, 583, 0, 0), + (731, 729, 725, 723), + (732, 729, 728, 725), + (733, 731, 726, 725), + (734, 724, 721, 720), + (735, 691, 0, 0), + (736, 730, 728, 723), + (737, 732, 0, 0), + (738, 391, 0, 0), + (739, 731, 723, 721), + (740, 587, 0, 0), + (741, 738, 733, 732), + (742, 741, 738, 730), + (743, 653, 0, 0), + (744, 743, 733, 731), + (745, 487, 0, 0), + (746, 395, 0, 0), + (747, 743, 741, 737), + (748, 744, 743, 733), + (749, 748, 743, 742), + (750, 746, 741, 734), + (751, 733, 0, 0), + (752, 749, 732, 731), + (753, 595, 0, 0), + (754, 735, 0, 0), + (755, 754, 745, 743), + (756, 407, 0, 0), + (757, 756, 751, 750), + (758, 757, 746, 741), + (759, 661, 0, 0), + (760, 757, 747, 734), + (761, 758, 0, 0), + (762, 679, 0, 0), + (763, 754, 749, 747), + (764, 761, 759, 758), + (765, 760, 755, 754), + (766, 757, 747, 744), + (767, 599, 0, 0), + (768, 764, 751, 749), + (769, 649, 0, 0), + (770, 768, 765, 756), + (771, 765, 756, 754), + (772, 765, 0, 0), + (773, 767, 765, 763), + (774, 589, 0, 0), + (775, 408, 0, 0), + (776, 773, 764, 759), + (777, 748, 0, 0), + (778, 403, 0, 0), + (779, 776, 771, 769), + (780, 775, 772, 764), + (781, 779, 765, 764), + (782, 453, 0, 0), + (783, 715, 0, 0), + (784, 778, 775, 771), + (785, 693, 0, 0), + (786, 782, 780, 771) + ); +end package; \ No newline at end of file