head	1.2;
access;
symbols;
locks; strict;
comment	@# @;


1.2
date	2003.11.20.05.07.57;	author tantos;	state Exp;
branches;
next	1.1;

1.1
date	2001.04.25.15.05.30;	author tantos;	state Exp;
branches;
next	;


desc
@@


1.2
log
@Large update to new version of wb_tk. Major changes:
- Xilinx support added
- Altera support is poor: though it's there I haven't tested or even compiled it for quite some time
- Behavioral models are added
- Async master is completely new: it's much more complicated but actually works
- Cores are tested in real HW (x2s300e)
- wb_out_reg currently lacks byte-select support
- wb_in_reg is added as a trivial input register
@
text
@--
--  Wishbone bus toolkit.
--
--  (c) Copyright Andras Tantos <andras_tantos@@yahoo.com> 2001/03/31
--  This code is distributed under the terms and conditions of the GNU General Public Lince.
--
--
-- ELEMENTS:
--   wb_out_reg: Wishbone bus compatible output register.

-------------------------------------------------------------------------------
--
--  wb_out_reg
--
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

library wb_tk;
use wb_tk.technology.all;

entity wb_out_reg is
	generic (
		reg_width : positive := 8;
		dat_width: positive := 8;
		offset: integer := 0
	);
	port (
		clk_i: in std_logic;
		rst_i: in std_logic;
		rst_val: std_logic_vector(reg_width-1 downto 0) := (others => '0');

		cyc_i: in std_logic := '1';
		stb_i: in std_logic;
		sel_i: in std_logic_vector (max2((dat_width/8)-1,0) downto 0) := (others => '1');
		we_i: in std_logic;
		ack_o: out std_logic;
		ack_oi: in std_logic := '-';
		adr_i: in std_logic_vector (size2bits((reg_width+offset+dat_width-1)/dat_width)-1 downto 0) := (others => '0');
		dat_i: in std_logic_vector (dat_width-1 downto 0);
		dat_oi: in std_logic_vector (dat_width-1 downto 0) := (others => '-');
		dat_o: out std_logic_vector (dat_width-1 downto 0);
		q: out std_logic_vector (reg_width-1 downto 0)
	);
end wb_out_reg;

architecture wb_out_reg of wb_out_reg is
	signal content : std_logic_vector (reg_width-1 downto 0);
	signal word_en: std_logic_vector ((reg_width / dat_width)-1 downto 0);
begin
    -- address demux
    adr_demux: process (adr_i)
    begin
        word_en <= (others => '0');
        word_en(to_integer(adr_i)) <= '1';
    end process;

	-- output bus handling with logic
	gen_dat_o: process(
		dat_oi, we_i, stb_i, content, word_en, cyc_i, sel_i
	)
		variable rd_sel: std_logic;
		variable dat_idx: integer;
	begin
        rd_sel := cyc_i and stb_i and not we_i;
		
		-- The default is the input, we'll override it if we need to
		for i in dat_o'RANGE loop
	        dat_o(i) <= dat_oi(i);
		end loop;
		for i in content'RANGE loop
		    dat_idx := (i+offset) mod dat_width;
			if (
--			    (sel_i((i/8) mod (dat_width/8)) = '1') and
			    (word_en(i/dat_width) = '1') and
			    (rd_sel = '1')
			) then
--				dat_o(dat_idx) <= (dat_oi(dat_idx) and not rd_sel) or (content(i) and rd_sel);
				dat_o(dat_idx) <= content(i);
			end if;
		end loop;
	end process;
--    dat_o <= dat_oi;

	-- this item never generates any wait-states
	ack_o <= stb_i or ack_oi;

	reg: process
		variable dat_idx: integer;
	begin
		wait until clk_i'EVENT and clk_i='1';
		if (rst_i = '1') then
			content <= rst_val;
		else
			if (stb_i = '1' and cyc_i = '1' and we_i = '1') then
				for i in content'RANGE loop
				    dat_idx := (i+offset) mod dat_width;
					if (
--					    (sel_i((i/8) mod (dat_width/8)) = '1') and
					    (word_en(i/dat_width) = '1')
					) then
						content(i) <=  dat_i(dat_idx);
					end if;
				end loop;
			end if;
		end if;
	end process;
	q <= content;
end wb_out_reg;
@


1.1
log
@Major reorganization and some new elements added.
@
text
@d26 2
a27 2
		width : positive := 8;
		bus_width: positive := 8;
d33 1
a33 1
		rst_val: std_logic_vector(width-1 downto 0) := (others => '0');
d35 1
a35 1
        cyc_i: in std_logic := '1';
d37 1
a37 1
        sel_i: in std_logic_vector ((bus_width/8)-1 downto 0) := (others => '1');
d41 5
a45 5
		adr_i: in std_logic_vector (size2bits((width+offset+bus_width-1)/bus_width)-1 downto 0) := (others => '0');
		dat_i: in std_logic_vector (bus_width-1 downto 0);
		dat_oi: in std_logic_vector (bus_width-1 downto 0) := (others => '-');
		dat_o: out std_logic_vector (bus_width-1 downto 0);
		q: out std_logic_vector (width-1 downto 0)
d50 2
a51 1
	signal content : std_logic_vector (width-1 downto 0);
d53 7
d61 3
a63 1
	gen_dat_o: process is
d65 1
a65 2
	    variable adr: integer;
	    variable reg_i: integer;
d67 15
a81 9
		wait on dat_oi, we_i, stb_i, content, adr_i, cyc_i, sel_i;
		rd_sel := cyc_i and stb_i and not we_i;
	    for i in dat_i'RANGE loop
	        adr := CONV_INTEGER(adr_i);
	        reg_i := i-offset+adr*bus_width;
	        if ((reg_i >= 0) and (reg_i < width) and (sel_i(i/8) = '1')) then
				dat_o(i) <= (dat_oi(i) and not rd_sel) or (content(reg_i) and rd_sel);
			else
				dat_o(i) <= dat_oi(i);
d85 1
d87 1
a87 1
	-- this item never generates any wait-states	
d89 3
a91 4
	
	reg: process is
	    variable adr: integer;
	    variable reg_i: integer;
d96 1
a96 1
		else 
d98 8
a105 6
			    for i in dat_i'RANGE loop
			        adr := CONV_INTEGER(adr_i);
			        reg_i := i-offset+adr*bus_width;
			        if ((reg_i >= 0) and (reg_i < width) and (sel_i(i/8) = '1')) then
				        content(reg_i) <=  dat_i(i);
				    end if;
@

