Pushing up some sample FPGA code to see if it's all set up right

This commit is contained in:
Xavi Kraken 2022-07-31 16:55:10 +01:00
parent ecd5c8cd09
commit ada17c09cd
21 changed files with 3101 additions and 1 deletions

View File

@ -1,3 +1,17 @@
# Accelerated_Wireguard # Accelerated_Wireguard
A hardware accelerated wireguard project using commercial FPGAs A hardware accelerated wireguard project using commercial FPGAs
## How to use the VHDL portion of this codebase
<p> While some of this might be being used in a synthesised image, much of the codebase *should* include the tools to simulate certain functionalities.<br>
<br>
To get the simulations up and running in linux please do the following:<br>
1) Open up a terminal window<br>
2) Label one of them "build window" and the other "results window"<br>
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"<br>
4) In the "build window" you will be prompted for your password. Please enter it<br>
5) In the "build window" you will find the codebase tree in the /mnt directory. You can navigate to your test from there<br>
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<br>
7) In your "results window" navigate to the same test folder you are in in your "build window"<br>
8) In your "results window" you will see a sub folder called "sim_build". Wnter that folder<br>
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 "<br>

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

143
fpga/build/Makefile.ip Normal file
View File

@ -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' >> $@

View File

@ -0,0 +1 @@
include $(PROJECT_DIR)/../fpga/prng/lfsr/lfsr.mk

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

18
fpga/prng/lfsr/lfsr.mk Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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()

View File

@ -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;

View File

@ -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;

View File

@ -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;