From 77e58cfbded14951c5b96255ce4539e2482cd4ee Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 27 Apr 2013 17:46:49 +0000 Subject: [PATCH] Initial revision Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@956 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/VGA_ctrl/src/align_out.vhd | 241 ++++++++++++++++++++++++++++ lib/VGA_ctrl/src/align_types.vhd | 34 ++++ lib/VGA_ctrl/src/tb_align_out.vhd | 256 ++++++++++++++++++++++++++++++ 3 files changed, 531 insertions(+) create mode 100644 lib/VGA_ctrl/src/align_out.vhd create mode 100644 lib/VGA_ctrl/src/align_types.vhd create mode 100644 lib/VGA_ctrl/src/tb_align_out.vhd diff --git a/lib/VGA_ctrl/src/align_out.vhd b/lib/VGA_ctrl/src/align_out.vhd new file mode 100644 index 0000000..ac83cb6 --- /dev/null +++ b/lib/VGA_ctrl/src/align_out.vhd @@ -0,0 +1,241 @@ +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +use work.utils_pkg.all; +use work.align_types.all; + +ENTITY align_out IS + Generic + ( + data_width : natural := 32; + addr_width : natural := 32; + byte_size : natural := 8 + ); + Port + ( + rst : in STD_LOGIC; + clk : in STD_LOGIC; + cmd_rdy : out STD_LOGIC; + cmd_vld : in STD_LOGIC; + cmd_in : in align_cmd_in_t; + din_rdy : out 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/byte_size-1 downto 0); + dout_re : in STD_LOGIC; + addr_out : out unsigned(addr_width-1 downto 0) + + ); +END align_out; + +ARCHITECTURE behavior OF align_out IS + + type byte_en_rom_t is array (0 to 2*data_width/byte_size-1) of unsigned (data_width/byte_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; + + constant out_addr_step : natural := data_width/byte_size; + constant out_addr_nlsb : natural := NextExpBaseTwo(out_addr_step); + signal byte_en_rom : byte_en_rom_t := gen_byte_en_rom(out_addr_step); + signal cmd_stb : std_logic; + signal shift_dout : unsigned(data_width-1 downto 0); + signal shift_vld : std_logic; + signal reg0 : unsigned(data_width-1 downto 0); + signal reg : unsigned(data_width-1 downto 0); + signal reg0_vld : std_logic; + signal reg_vld : std_logic; + signal comb_be : unsigned (out_addr_step-1 downto 0); + signal byte_en : unsigned (out_addr_step-1 downto 0); + signal saddr_reg : unsigned(addr_width-1 downto 0); + signal eb_reg : std_logic; + + signal shift_sa : integer; + + type addr_alt_t is record + offset : unsigned(out_addr_nlsb-1 downto 0); + addr : unsigned(addr_width-1 downto 0); + remain : unsigned(addr_width-1 downto 0); + busy : std_logic; + last : std_logic; + end record; + + signal addr_alt : addr_alt_t; + -- output FIFO + signal fifo_din : unsigned(addr_width+data_width+out_addr_step-1 downto 0); + signal fifo_dout : unsigned(addr_width+data_width+out_addr_step-1 downto 0); + signal fifo_re : std_logic; + signal fifo_we : std_logic; + signal fifo_full : std_logic; + signal fifo_empty : std_logic; + signal fifo_rdy : std_logic; + signal fifo_dout_vld : std_logic; + signal rdy : std_logic; + +-------------------------------------------------------------------------- +begin + + cmd_stb <= not addr_alt.busy and cmd_vld; + + + cmd_rdy <= not addr_alt.busy; + + dout_be <= fifo_dout(addr_width+data_width+out_addr_step-1 downto addr_width+data_width); + addr_out <= fifo_dout(addr_width+data_width-1 downto data_width); + dout <= fifo_dout(data_width-1 downto 0); + + rdy <= fifo_rdy and addr_alt.busy; + dout_vld <= fifo_dout_vld; + din_rdy <= rdy; + +--------------------------------------------------------------------------- +-- Address generation +--------------------------------------------------------------------------- + byte_en <= byte_en_rom(to_integer(not eb_reg & addr_alt.addr(out_addr_nlsb-1 downto 0))) when addr_alt.last = '0' + else byte_en_rom(to_integer(eb_reg & addr_alt.remain(out_addr_nlsb-1 downto 0))); + + addr_alt.last <= '1' when (addr_alt.remain < out_addr_step) else '0'; + +prproc_addr_alt: + process(clk) + variable addr_next : unsigned(addr_width-1 downto 0); + variable remain_next : unsigned(addr_width-1 downto 0); + begin + if rising_edge(clk) then + if addr_alt.addr(out_addr_nlsb-1 downto 0) /= (out_addr_nlsb-1 downto 0 => '0') then + addr_next := addr_alt.addr + (to_unsigned(out_addr_step, out_addr_nlsb) - addr_alt.addr(out_addr_nlsb-1 downto 0)); + remain_next := addr_alt.remain - (to_unsigned(out_addr_step, out_addr_nlsb) - saddr_reg(out_addr_nlsb-1 downto 0)); + else + addr_next := addr_alt.addr + to_unsigned(out_addr_step, addr_width); + remain_next := addr_alt.remain - to_unsigned(out_addr_step, addr_width); + end if; + if rst = '1' then + addr_alt.busy <= '0'; + elsif cmd_stb = '1' then + addr_alt.offset <= cmd_in.addr_start(out_addr_nlsb-1 downto 0); + addr_alt.addr <= cmd_in.addr_start; + addr_alt.remain <= cmd_in.num_bytes; + addr_alt.busy <= '1'; + saddr_reg <= cmd_in.addr_start; + eb_reg <= cmd_in.eb; + elsif rdy = '1' then + if addr_alt.last = '1' then + addr_alt.busy <= '0'; + end if; + if reg_vld = '1' then + addr_alt.addr <= addr_next; + if remain_next = out_addr_step then + addr_alt.busy <= '0'; + else + addr_alt.remain <= remain_next; + end if; + end if; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- Data generation +--------------------------------------------------------------------------- +inst_shifter : entity work.align_shifter + GENERIC MAP + ( + data_width => data_width, + aggregate_size => byte_size, + do_pipelined => true + ) + PORT MAP + ( + rst => rst, + clk => clk, + ce => rdy, + sa => shift_sa, + din_vld => din_vld, + din => din, + dout_vld => shift_vld, + dout => shift_dout + + ); + + shift_sa <= to_integer(addr_alt.offset); + +proc_combine: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + reg_vld <= '0'; + elsif rdy = '1' then + reg_vld <= shift_vld; + reg0_vld <= shift_vld; + if reg0_vld = '1' then + reg <= reg0; + end if; + if shift_vld = '1' then + reg0 <= shift_dout; + for i in 0 to data_width/byte_size-1 loop + if comb_be(i) = '1' then + reg(byte_size*(i+1)-1 downto byte_size*i) <= shift_dout(byte_size*(i+1)-1 downto byte_size*i); + end if; + end loop; + end if; + end if; + end if; + end process; + comb_be <= byte_en_rom(to_integer(not eb_reg & addr_alt.offset)); + +-- Output FIFO +inst_fifo: entity work.fifo_sync + GENERIC MAP + ( + addr_width => 4, + data_width => fifo_din'length, + do_last_read_update => true + ) + PORT MAP + ( + rst => rst, + clk => clk, + we => fifo_we, + re => fifo_re, + fifo_full => fifo_full, + fifo_empty => fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => fifo_din, + data_r => fifo_dout + ); + fifo_rdy <= not fifo_full; + fifo_din <= byte_en & addr_alt.addr(addr_width-1 downto out_addr_nlsb) & (out_addr_nlsb-1 downto 0 => '0') & reg; + fifo_we <= (reg_vld or addr_alt.last) and rdy; + fifo_dout_vld <= not fifo_empty; + fifo_re <= dout_re; + +-------------------------------------------------------------------------- +end behavior; diff --git a/lib/VGA_ctrl/src/align_types.vhd b/lib/VGA_ctrl/src/align_types.vhd new file mode 100644 index 0000000..ef7680c --- /dev/null +++ b/lib/VGA_ctrl/src/align_types.vhd @@ -0,0 +1,34 @@ +-- Package File Template +-- +-- Purpose: This package defines supplemental types, subtypes, +-- constants, and functions + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.MATH_REAL.ALL; + +package align_types is + + -- Constants + + -- Types + type align_cmd_in_t is record + eb : std_logic; + addr_start : unsigned(31 downto 0); + num_bytes : unsigned(31 downto 0); + addr_step : natural; + num_bytes_per_word : natural; + end record; + + -- Functions + +end align_types; + + +package body align_types is + +end align_types; + + diff --git a/lib/VGA_ctrl/src/tb_align_out.vhd b/lib/VGA_ctrl/src/tb_align_out.vhd new file mode 100644 index 0000000..e1e2963 --- /dev/null +++ b/lib/VGA_ctrl/src/tb_align_out.vhd @@ -0,0 +1,256 @@ +------------------------------------------------------------------------- +-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL +-- This file: testbench for system test using Xilinx ML-402 + +-- Copyright (C) 2007 J. Ahrensfeld + +-- This library is free software; you can redistribute it and/or +-- modify it under the terms of the GNU Lesser General Public +-- License as published by the Free Software Foundation; either +-- version 2.1 of the License, or (at your option) any later version. + +-- This library is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +-- Lesser General Public License for more details. + +-- You should have received a copy of the GNU Lesser General Public +-- License along with this library; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-- For questions and ideas, please contact the author at jens@jayfield.org + +----------------------------------------------------------------------- + +LIBRARY ieee; +use IEEE.STD_LOGIC_1164.ALL; +USE ieee.numeric_std.ALL; + +use work.align_types.all; + +ENTITY tb_align_out IS +END tb_align_out; + +ARCHITECTURE behavior OF tb_align_out IS + + constant CLK_PERIOD : time := 10 ns; + signal CLK_O : std_logic := '1'; + signal RST_O : std_logic := '1'; + + signal cmd_rdy : std_logic; + signal cmd_vld : std_logic := '0'; + signal cmd_in : align_cmd_in_t; + + signal din : unsigned(31 downto 0) := (others => '-'); + signal din_rdy : std_logic; + signal din_vld : std_logic := '0'; + + signal dout_vld : std_logic; + signal dout_re : std_logic := '0'; + signal dout : unsigned(31 downto 0); + signal dout_be : unsigned(3 downto 0); + + signal addr_out : unsigned(31 downto 0); + + signal read_reg : unsigned(31 downto 0) := (others => '-'); + +BEGIN + +inst_align_out : entity work.align_out + GENERIC MAP + ( + data_width => 32, + addr_width => 32, + byte_size => 8 + ) + PORT MAP + ( + rst => RST_O, + clk => CLK_O, + cmd_rdy => cmd_rdy, + cmd_vld => cmd_vld, + cmd_in => cmd_in, + din_rdy => din_rdy, + din_vld => din_vld, + din => din, + dout_vld => dout_vld, + dout => dout, + dout_be => dout_be, + dout_re => dout_re, + addr_out => addr_out + + ); + + +CLK_GEN: process + begin + wait for CLK_PERIOD/2; + CLK_O <= not CLK_O; + end process; + +READ_GEN: process + begin + wait for CLK_PERIOD/2; + dout_re <= '1'; + wait for CLK_PERIOD/2; + dout_re <= '0'; + wait for 12*CLK_PERIOD/2; + end process; + +-- Master +STIMULUS: + process + begin + + wait for 6*CLK_PERIOD; + RST_O <= '0'; + wait for 60*CLK_PERIOD; + wait until rising_edge(CLK_O) and dout_vld = '0'; + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + + ------------------------------------------------ + cmd_in.eb <= '1'; + cmd_in.addr_start <= X"8000_0002"; + cmd_in.addr_step <= 2; + cmd_in.num_bytes_per_word <= 4; + cmd_in.num_bytes <= to_unsigned(32, cmd_in.num_bytes'length); + + -- Trigger transaction + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + cmd_vld <= '1'; + wait until rising_edge(CLK_O); + cmd_vld <= '0'; + + wait until rising_edge(CLK_O) and din_rdy = '1'; + + din <= X"1111_0000"; + din_vld <= '1'; + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + + din_vld <= '0'; + wait for 8*CLK_PERIOD; + wait until rising_edge(CLK_O) and din_rdy = '1'; + din_vld <= '1'; + + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + din_vld <= '0'; + + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + + ------------------------------------------------ + cmd_in.eb <= '1'; + cmd_in.addr_start <= X"8000_0000"; + cmd_in.addr_step <= 2; + cmd_in.num_bytes_per_word <= 4; + cmd_in.num_bytes <= to_unsigned(32, cmd_in.num_bytes'length); + + -- Trigger transaction + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + cmd_vld <= '1'; + wait until rising_edge(CLK_O); + cmd_vld <= '0'; + + wait until rising_edge(CLK_O) and din_rdy = '1'; + + din <= X"1111_0000"; + din_vld <= '1'; + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + + din_vld <= '0'; + wait for 8*CLK_PERIOD; + wait until rising_edge(CLK_O) and din_rdy = '1'; + din_vld <= '1'; + + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + din_vld <= '0'; + + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + + ------------------------------------------------ + cmd_in.eb <= '1'; + cmd_in.addr_start <= X"8000_0003"; + cmd_in.addr_step <= 2; + cmd_in.num_bytes_per_word <= 4; + cmd_in.num_bytes <= to_unsigned(32, cmd_in.num_bytes'length); + + -- Trigger transaction + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + cmd_vld <= '1'; + wait until rising_edge(CLK_O); + cmd_vld <= '0'; + + wait until rising_edge(CLK_O) and din_rdy = '1'; + + din <= X"1111_0000"; + din_vld <= '1'; + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + + din_vld <= '0'; + wait for 8*CLK_PERIOD; + wait until rising_edge(CLK_O) and din_rdy = '1'; + din_vld <= '1'; + + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + din_vld <= '0'; + + wait for 10*CLK_PERIOD; + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + wait until rising_edge(CLK_O) and dout_vld = '0'; + + ------------------------------------------------ + cmd_in.eb <= '1'; + cmd_in.addr_start <= X"8000_0000"; + cmd_in.addr_step <= 2; + cmd_in.num_bytes_per_word <= 2; + cmd_in.num_bytes <= to_unsigned(2, cmd_in.num_bytes'length); + + -- Trigger transaction + wait until rising_edge(CLK_O) and cmd_rdy = '1'; + cmd_vld <= '1'; + wait until rising_edge(CLK_O); + cmd_vld <= '0'; + + wait until rising_edge(CLK_O) and din_rdy = '1'; + + din <= X"1111_0000"; + din_vld <= '1'; + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + + din_vld <= '0'; + wait for 8*CLK_PERIOD; + wait until rising_edge(CLK_O) and din_rdy = '1'; + din_vld <= '1'; + + for i in 0 to 16/4-1 loop + wait until rising_edge(CLK_O) and din_rdy = '1'; + din <= din + X"1111_1111"; + end loop; + din_vld <= '0'; + wait; + + end process; + +END;