Compare commits

...

7 commits

Author SHA1 Message Date
Xiretza 6ff0e77d38 makefile: make ghdl error on warnings 2022-06-07 07:34:09 +02:00
Xiretza 645a838a73 vhdl: use UDP packet length 2022-06-07 07:34:09 +02:00
Xiretza 70a7b0520a vhdl: only run encoders once all pixels are received 2022-06-07 07:34:09 +02:00
Xiretza 9ca64a7d4d Update ws2812 submodule 2022-06-07 07:34:09 +02:00
Xiretza 0f497e76e8 vhdl: implement bounds checking for strand number 2022-06-07 07:34:09 +02:00
Xiretza fcfa9eb7d0 vhdl: workaround ghdl#2080
https://github.com/ghdl/ghdl/issues/2080
2022-06-07 07:34:09 +02:00
Xiretza 3c5c3a4555 vhdl: use big-endian network byte order
liteeth splits the rx data stream into 4-byte chunks and interprets them as
little-endian 32-bit vecs; similar for the other direction.
2022-06-07 07:34:09 +02:00
5 changed files with 60 additions and 15 deletions

View file

@ -2,7 +2,7 @@ SYNTH_OUTPUT_FILE = $(SYNTH_WORKDIR)/$(YOSYS_MODULE_NAME).json
$(SYNTH_WORKDIR)/%.json: $(VHDL_FILES) $(VERILOG_FILES) | $(SYNTH_WORKDIR) $(GHDL_WORKDIR)/work-obj$(VHDL_STD).cf $(SYNTH_WORKDIR)/%.json: $(VHDL_FILES) $(VERILOG_FILES) | $(SYNTH_WORKDIR) $(GHDL_WORKDIR)/work-obj$(VHDL_STD).cf
$(GHDL) make $(GHDL_FLAGS) $(SYNTH_ENTITY) $(GHDL) make $(GHDL_FLAGS) $(SYNTH_ENTITY)
$(YOSYS) -m $(GHDL_YOSYS_PLUGIN) -l $(SYNTH_WORKDIR)/yosys.log -p 'ghdl $(GHDL_FLAGS) $(SYNTH_ENTITY); read_verilog $(VERILOG_FILES); chformal -remove; synth_xilinx -nodsp -nosrl -flatten -top $*; write_json $@' $(YOSYS) -m $(GHDL_YOSYS_PLUGIN) -l $(SYNTH_WORKDIR)/yosys.log -p 'ghdl $(GHDL_FLAGS) -Werror -Wno-error=binding $(SYNTH_ENTITY); read_verilog $(VERILOG_FILES); chformal -remove; synth_xilinx -nodsp -nosrl -flatten -top $*; write_json $@'
$(SYNTH_WORKDIR)/%.fasm: $(SYNTH_WORKDIR)/%.json $(XDC) $(SYNTH_WORKDIR)/%.fasm: $(SYNTH_WORKDIR)/%.json $(XDC)
$(NEXTPNR) --xdc $(XDC) --json $< --chipdb /usr/share/nextpnr/xilinx-chipdb/$(PART).bin --fasm $@ $(NEXTPNR) --xdc $(XDC) --json $< --chipdb /usr/share/nextpnr/xilinx-chipdb/$(PART).bin --fasm $@

View file

@ -2,6 +2,8 @@ library ieee;
use ieee.std_logic_1164.all, use ieee.std_logic_1164.all,
ieee.numeric_std.all; ieee.numeric_std.all;
use work.util.flip_endianness;
entity arty_a7 is entity arty_a7 is
generic ( generic (
IS_SIMULATION : std_logic := '0' IS_SIMULATION : std_logic := '0'
@ -119,6 +121,7 @@ architecture a of arty_a7 is
signal pixel_source_src_ip_address : std_logic_vector(31 downto 0); signal pixel_source_src_ip_address : std_logic_vector(31 downto 0);
signal pixel_source_src_port : std_logic_vector(15 downto 0); signal pixel_source_src_port : std_logic_vector(15 downto 0);
signal pixel_source_length : std_logic_vector(15 downto 0);
signal pixel_source_valid : std_logic; signal pixel_source_valid : std_logic;
signal pixel_source_last : std_logic; signal pixel_source_last : std_logic;
signal pixel_source_data : std_logic_vector(31 downto 0); signal pixel_source_data : std_logic_vector(31 downto 0);
@ -192,6 +195,11 @@ architecture a of arty_a7 is
signal frame_number : unsigned(31 downto 0); signal frame_number : unsigned(31 downto 0);
signal prev_frame_number : unsigned(31 downto 0); signal prev_frame_number : unsigned(31 downto 0);
-- little-endian pixel sink data
signal pixel_sink_data_le : std_logic_vector(31 downto 0);
-- big-endian pixel source data
signal pixel_source_data_be : std_logic_vector(31 downto 0);
begin begin
leds_simple <= (others => '0'); leds_simple <= (others => '0');
led0 <= (others => '0'); led0 <= (others => '0');
@ -242,19 +250,20 @@ begin
pixel_sink_last => pixel_sink_last, pixel_sink_last => pixel_sink_last,
pixel_sink_last_be => pixel_sink_last_be, pixel_sink_last_be => pixel_sink_last_be,
pixel_sink_ready => pixel_sink_ready, pixel_sink_ready => pixel_sink_ready,
pixel_sink_data => pixel_sink_data, pixel_sink_data => pixel_sink_data_le,
-- source -- source
pixel_source_src_ip_address => pixel_source_src_ip_address, pixel_source_src_ip_address => pixel_source_src_ip_address,
pixel_source_src_port => pixel_source_src_port, pixel_source_src_port => pixel_source_src_port,
pixel_source_length => open, pixel_source_length => pixel_source_length,
pixel_source_valid => pixel_source_valid, pixel_source_valid => pixel_source_valid,
pixel_source_last => pixel_source_last, pixel_source_last => pixel_source_last,
pixel_source_last_be => open, pixel_source_last_be => open,
pixel_source_ready => '1', pixel_source_ready => '1',
pixel_source_data => pixel_source_data pixel_source_data => pixel_source_data
); );
pixel_sink_data_le <= flip_endianness(pixel_sink_data);
-- 800 MHz VCO -- 800 MHz VCO
-- 80 MHz system clock -- 80 MHz system clock
@ -335,12 +344,14 @@ begin
clk => sys_clk, clk => sys_clk,
reset => sys_reset, reset => sys_reset,
udp_length => pixel_source_length,
udp_valid => pixel_source_valid, udp_valid => pixel_source_valid,
udp_last => pixel_source_last, udp_last => pixel_source_last,
udp_data => pixel_source_data, udp_data => pixel_source_data_be,
frame_number => frame_number, frame_number => frame_number,
drivers => drivers drivers => drivers
); );
pixel_source_data_be <= flip_endianness(pixel_source_data);
end architecture; end architecture;

View file

@ -11,6 +11,7 @@ entity splink is
clk : in std_logic; clk : in std_logic;
reset : in std_logic; reset : in std_logic;
udp_length : in std_logic_vector(15 downto 0);
udp_valid : in std_logic; udp_valid : in std_logic;
udp_last : in std_logic; udp_last : in std_logic;
udp_data : in std_logic_vector(31 downto 0); udp_data : in std_logic_vector(31 downto 0);
@ -40,6 +41,7 @@ architecture a of splink is
signal current_frame: unsigned(31 downto 0); signal current_frame: unsigned(31 downto 0);
signal pixels_received: natural range 0 to MAX_STRAND_LEN-1; signal pixels_received: natural range 0 to MAX_STRAND_LEN-1;
signal run : std_logic;
signal clear_write_flags : std_logic; signal clear_write_flags : std_logic;
signal all_strands_written : std_logic; signal all_strands_written : std_logic;
@ -47,6 +49,8 @@ architecture a of splink is
-- "PIXL" -- "PIXL"
constant MAGIC_NUMBER : std_logic_vector(31 downto 0) := x"5049584c"; constant MAGIC_NUMBER : std_logic_vector(31 downto 0) := x"5049584c";
-- magic + frame num + strand num (4 bytes each)
constant HEADER_LEN : natural := 12;
type receive_state_t is (MAGIC, FRAME_NUM, STRAND_NUM, DATA, DROP); type receive_state_t is (MAGIC, FRAME_NUM, STRAND_NUM, DATA, DROP);
constant RESET_STATE : receive_state_t := MAGIC; constant RESET_STATE : receive_state_t := MAGIC;
@ -69,6 +73,7 @@ begin
port map ( port map (
n_reset => not reset, n_reset => not reset,
clk => clk, clk => clk,
run => run,
led_addr => led_data_arr(i).addr, led_addr => led_data_arr(i).addr,
@ -119,10 +124,12 @@ begin
begin begin
if rising_edge(clk) then if rising_edge(clk) then
clear_write_flags <= '0'; clear_write_flags <= '0';
run <= '0';
if all_strands_written then if all_strands_written then
frame_number <= current_frame; frame_number <= current_frame;
clear_write_flags <= '1'; clear_write_flags <= '1';
run <= '1';
end if; end if;
if reset then if reset then
@ -136,20 +143,24 @@ begin
case receive_state is case receive_state is
when MAGIC => when MAGIC =>
if udp_data = MAGIC_NUMBER then if udp_data /= MAGIC_NUMBER then
receive_state <= STRAND_NUM;
else
receive_state <= DROP; receive_state <= DROP;
else
if (unsigned(udp_length) - HEADER_LEN) / 4 > MAX_STRAND_LEN then
receive_state <= DROP;
else
num_pixels <= (to_integer(unsigned(udp_length)) - HEADER_LEN) / 4;
receive_state <= STRAND_NUM;
end if;
end if; end if;
when STRAND_NUM => when STRAND_NUM =>
-- TODO udp_length, range check with MAX_STRAND_LEN if unsigned(udp_data) >= NUM_STRANDS then
num_pixels <= MAX_STRAND_LEN; receive_state <= DROP;
else
-- FIXME bounds check active_strand <= to_integer(unsigned(udp_data));
active_strand <= to_integer(unsigned(udp_data)); receive_state <= FRAME_NUM;
end if;
receive_state <= FRAME_NUM;
when FRAME_NUM => when FRAME_NUM =>
if not some_strands_written then if not some_strands_written then

23
vhdl/util.vhdl Normal file
View file

@ -0,0 +1,23 @@
library ieee;
use ieee.std_logic_1164.all;
package util is
function flip_endianness(val : in std_logic_vector) return std_logic_vector;
end package;
package body util is
function flip_endianness(val : in std_logic_vector) return std_logic_vector is
constant BYTES : natural := val'length / 8;
variable ret : std_logic_vector(val'length-1 downto 0);
begin
assert val'length mod 8 = 0
report "length of vector not a multiple of 8"
severity failure;
for i in 0 to BYTES-1 loop
ret((BYTES-i)*8 - 1 downto (BYTES-i-1) * 8) := val((i+1)*8 - 1 downto i*8);
end loop;
return ret;
end function;
end package body;

@ -1 +1 @@
Subproject commit 0d1688f1840b8b5894b9f4cd027fcc1653dd3657 Subproject commit 0d4146d3a3abeb6a20f9228e61e58f95a71b340a