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
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user