diff --git a/lib/VGA_ctrl/src/align.vhd b/lib/VGA_ctrl/src/align.vhd new file mode 100644 index 0000000..d45bcd0 --- /dev/null +++ b/lib/VGA_ctrl/src/align.vhd @@ -0,0 +1,169 @@ +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +use work.utils_pkg.all; -- Imports the standard textio package. + +ENTITY align IS + Generic + ( + data_width : natural := 32; + aggregate_size : natural := 8; + allow_partial_valid : boolean := false + ); + Port + ( + rst : in STD_LOGIC; + clk : in STD_LOGIC; + ce : in STD_LOGIC; + eb : in STD_LOGIC; + offset : in unsigned(NextExpBaseTwo(data_width/aggregate_size)-1 downto 0); + din_last_vld : in STD_LOGIC; + din_vld : in STD_LOGIC; + din : in unsigned(data_width-1 downto 0); + dout_vld : out STD_LOGIC; + dout : out unsigned(data_width-1 downto 0); + dout_be : out unsigned(data_width/aggregate_size-1 downto 0) + + ); +END align; + +ARCHITECTURE behavior OF align IS + + signal shift_dout : unsigned(data_width-1 downto 0); + signal shift_vld : std_logic; + + signal reg0_vld : std_logic; + signal reg0 : unsigned(data_width-1 downto 0); + + signal reg : unsigned(data_width-1 downto 0); + signal reg_vld : std_logic; + signal reg_be : unsigned(data_width/aggregate_size-1 downto 0); + + signal data_vld : std_logic; + signal shift_din_vld : std_logic; + signal last_vld : unsigned(NextExpBaseTwo(data_width/aggregate_size)-1 downto 0); + + type byte_en_rom_t is array (0 to 2*data_width/aggregate_size-1) of unsigned (data_width/aggregate_size-1 downto 0); + + function gen_byte_en_rom(N : natural) return byte_en_rom_t is + variable k : integer; + variable result : byte_en_rom_t; + begin + + k:=0; + + result(k) := (others => '1'); + k := k + 1; + + for i in 1 to N-1 loop + result(k) := (N-1 downto i => '1') & (i-1 downto 0 => '0'); + k := k + 1; + end loop; + + result(k) := (others => '1'); + k := k + 1; + + for i in 1 to N-1 loop + result(k) := (N-1 downto i => '0') & (i-1 downto 0 => '1'); + k := k + 1; + end loop; + + return result; + end gen_byte_en_rom; + + signal byte_en_rom : byte_en_rom_t := gen_byte_en_rom(data_width/aggregate_size); + signal byte_en : unsigned (data_width/aggregate_size-1 downto 0); + +-------------------------------------------------------------------------- +begin + + byte_en <= byte_en_rom(to_integer(not eb & offset)); + dout <= reg; + dout_be <= reg_be; + dout_vld <= data_vld; + shift_din_vld <= din_vld; + +inst_shifter : entity work.shifter + GENERIC MAP + ( + data_width => data_width, + aggregate_size => aggregate_size, + do_pipelined => true + ) + PORT MAP + ( + rst => rst, + clk => clk, + ce => ce, + sa => to_integer(offset), + din_vld => shift_din_vld, + din => din, + dout_vld => shift_vld, + dout => shift_dout + + ); + +proc_data_valid: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + reg0_vld <= '0'; + data_vld <= '0'; + last_vld <= (others => '0'); + elsif ce = '1' then + last_vld <= last_vld(last_vld'left-1 downto 0) & din_last_vld; + reg0_vld <= shift_vld; + if offset /= (NextExpBaseTwo(data_width/aggregate_size)-1 downto 0 => '0') and not allow_partial_valid then + data_vld <= reg_vld and (shift_vld and not last_vld(last_vld'left)); + else + data_vld <= shift_vld or last_vld(last_vld'left); + end if; + end if; + end if; + end process; + +proc_align: + process(clk) + begin + if rising_edge(clk) then + if ce = '1' then + if shift_vld = '1' then + reg0 <= shift_dout; + end if; + end if; + end if; + end process; + +proc_blit_dst_combine: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + reg_be <= (others => '0'); + reg_vld <= '0'; + elsif ce = '1' then + if reg0_vld = '1' or shift_vld = '1' then + reg_vld <= not last_vld(last_vld'left); + reg <= reg0; + if reg_vld = '0' or last_vld(last_vld'left) = '1' then + reg_be <= not byte_en and (data_width/aggregate_size-1 downto 0 => reg0_vld); + else + reg_be <= not byte_en; + end if; + if shift_vld = '1' then + for i in 0 to data_width/aggregate_size-1 loop + if byte_en(i) = '1' then + reg_be(i) <= '1'; + reg(aggregate_size*(i+1)-1 downto aggregate_size*i) <= shift_dout(aggregate_size*(i+1)-1 downto aggregate_size*i); + end if; + end loop; + end if; + end if; + end if; + end if; + end process; + +-------------------------------------------------------------------------- +end behavior; diff --git a/lib/VGA_ctrl/src/shifter.vhd b/lib/VGA_ctrl/src/shifter.vhd new file mode 100644 index 0000000..fb57b6f --- /dev/null +++ b/lib/VGA_ctrl/src/shifter.vhd @@ -0,0 +1,133 @@ +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +use std.textio.all; -- Imports the standard textio package. + +use work.utils_pkg.all; -- Imports the standard textio package. + +ENTITY shifter IS + Generic + ( + data_width : natural := 32; + aggregate_size : natural := 8; + positive_shift_left : boolean := true; + do_pipelined : boolean := true + ); + Port + ( + rst : in STD_LOGIC; + clk : in STD_LOGIC; + ce : in STD_LOGIC; + sa : in integer; + din_vld : in STD_LOGIC; + din : in unsigned(data_width-1 downto 0); + dout_vld : out STD_LOGIC; + dout : out unsigned(data_width-1 downto 0) + + ); +END shifter; + +ARCHITECTURE behavior OF shifter IS + + constant num_rounds : natural := NextExpBaseTwo(data_width/aggregate_size); + subtype sa_rnd_t is signed(num_rounds-1 downto 0); + subtype word_t is unsigned(data_width-1 downto 0); + type word_array_t is array (0 to num_rounds) of word_t; + + signal rot_data : word_array_t; + signal sa_rnd : sa_rnd_t; + + type sa_rnd_array_t is array (0 to num_rounds) of sa_rnd_t; + signal sa_rnd_pipe : sa_rnd_array_t; + signal dout_vld_pipe : unsigned(0 to num_rounds); + +-------------------------------------------------------------------------- +function rol_stage(x : unsigned; en : std_logic; stage_num : natural; size : natural) return unsigned is + variable result : unsigned(x'range); + constant sa : natural := (2**stage_num) * size; + begin + if en = '1' then + result := x(x'left-sa downto 0) & x(x'left downto x'length-sa); + else + result := x; + end if; + return result; + +end rol_stage; + + +function ror_stage(x : unsigned; en : std_logic; stage_num : natural; size : natural) return unsigned is + variable result : unsigned(x'range); + constant sa : natural := (2**stage_num) * size; + begin + if en = '1' then + result := x(sa-1 downto 0) & x(x'left downto sa); + else + result := x; + end if; + return result; + +end ror_stage; + +-------------------------------------------------------------------------- +begin + +-------------------------------------------------------------------------- +gen_non_pipelined: +if do_pipelined = false generate +begin + + rot_data(0) <= din; + +gen_rotate: + for stage in 0 to num_rounds-1 generate + begin + rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd(stage), stage, aggregate_size) when positive_shift_left else + ror_stage(rot_data(stage), sa_rnd(stage), stage, aggregate_size); + end generate; + + sa_rnd <= to_signed(sa, num_rounds); + dout <= rot_data(num_rounds); + dout_vld <= din_vld; + +end generate; + +-------------------------------------------------------------------------- +gen_pipelined: +if do_pipelined = true generate +begin + + rot_data(0) <= din; + sa_rnd_pipe(0) <= to_signed(sa, num_rounds); + dout_vld_pipe(0) <= din_vld; + +gen_rotate: + for stage in 0 to num_rounds-1 generate + begin + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + dout_vld_pipe(stage+1) <= '0'; + elsif ce = '1' then + dout_vld_pipe(stage+1) <= dout_vld_pipe(stage); + if dout_vld_pipe(stage) = '1' then + sa_rnd_pipe(stage+1) <= sa_rnd_pipe(stage); + if positive_shift_left then + rot_data(stage+1) <= rol_stage(rot_data(stage), sa_rnd_pipe(stage)(stage), stage, aggregate_size); + else + rot_data(stage+1) <= ror_stage(rot_data(stage), sa_rnd_pipe(stage)(stage), stage, aggregate_size); + end if; + end if; + end if; + end if; + end process; + end generate; + + dout <= rot_data(num_rounds); + dout_vld <= dout_vld_pipe(num_rounds); + +end generate; + +-------------------------------------------------------------------------- +end behavior;