📄 epp_dwidth.vhd
字号:
-- change data width from 8-bit to 8-bit, 16-bit or 32-bit
-- by Erenst Jamro
--//////////////////////////////////////////////////////////////////////
--//// Copyright (C) 2003 Authors ////
--//// ////
--//// This source file may be used and distributed without ////
--/// restriction provided that this copyright statement is not ////
--//// removed from the file and that any derivative work contains ////
--//// the original copyright notice and the associated disclaimer. ////
--//// ////
--//// This source file 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 source 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. ////
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity epp_dwidth is
generic(dwidth: integer:= 32;
use_seqAddr: integer:= 1); -- assume that the read or write is sequancial
port (clk, arst: in std_logic;
-- common logic
seqAddr: in std_logic; -- the next read /writes will be sequencial- use always seqAddr when transfering data unless use_seqAddr<=0
rnw: in std_logic; -- read not write
buf_valid: out std_logic; -- valid data write buffer - do not change the address and rnw
-- 8-bit data interface
adr8: in std_logic_vector(0 to 31);
stb8: in std_logic;
ack8: out std_logic;
din8: in std_logic_vector(0 to 7);
dout8: out std_logic_vector(0 to 7);
-- dwidth data interface
adr: out std_logic_vector(0 to 31);
stb: out std_logic;
ack: in std_logic;
be: out std_logic_vector(0 to dwidth/8-1);
din: in std_logic_vector(0 to dwidth-1);
dout: out std_logic_vector(0 to dwidth-1));
end epp_dwidth;
architecture arch of epp_dwidth is
constant width8: integer:= 8/dwidth; -- 1 when dwidth=8 else '0'
signal ack8i, stbi: std_logic; -- internal ack8
signal buf_rd: std_logic_vector(8 to dwidth-1+width8); -- internal buffer (except the MSB which is read directly)
signal be_wr: std_logic_vector(0 to dwidth/8-2+width8); -- valid bytes is the buffer (the MSB is directly copied from din8 to dout
signal be_rd: std_logic; -- the read buffer is valid (all Bytes exept the MSB which is read directly)
begin
g1: if use_seqAddr>0 and dwidth>8 generate
ack8<= ack8i;
g16: if dwidth=16 generate
-- write buffer for the MSB
process(arst, clk) begin
if arst='1' then dout(0 to 7)<= (others=>'0'); be_wr(0)<='0';
elsif clk'event and clk='1' then
if ack='1' then
be_wr(0)<= '0';
elsif ack8i='1' and rnw='0' and adr8(31)='0' then
dout(0 to 7)<= din8;
be_wr(0)<= '1';
end if;
end if;
end process;
dout(8 to 15)<= din8;
-- read buffer
process(arst, clk) begin
if arst='1' then buf_rd<= (others=>'0'); be_rd<= '0';
elsif clk'event and clk='1' then
if ack='1' then
buf_rd<= din(8 to 15);
end if;
if seqAddr='0' then
be_rd<= '0'; -- not longer valid
elsif ack='1' and rnw='1' then
be_rd<= '1';
elsif ack8i='1' and adr8(31)='1' then
be_rd<='0';
end if;
end if;
end process;
dout8<= din(0 to 7) when adr8(31)='0' else buf_rd;
stbi<= be_wr(0) when seqAddr='0' else -- finish the cycle without the full transfer or
'0' when stb8='0' else -- direct copy of the one byte (therefore stb8 must be '1')
not adr8(31) or not be_rd when rnw='1' else -- read the MSB (or the start of reading)
adr8(31); -- write the LSB
be(0)<= be_wr(0) when rnw='0' else -- when write
not adr8(31); -- read
be(1)<= '1' when rnw='1' else -- read
adr8(31) and stb8; -- write
ack8i<= ack when rnw='1' and adr8(31)='0' else -- direct read
stb8 and be_rd when rnw='1' else -- read from the buffer (LSB)
stb8 when adr8(31)='0' else -- the MSB write to buffer
ack; -- the direck write to the LSB
buf_valid<= be_wr(0);
adr(0 to 30)<= adr8(0 to 30);
adr(31)<= '0' when be_wr(0)='1' else adr8(31);
end generate; -- dwidth=16
----------------------------------------------------------------------------------
g32: if dwidth=32 generate
-- write buffer (not for the LSB)
process(arst, clk) begin
if arst='1' then dout(0 to 23)<= (others=>'0'); be_wr(0 to 2)<="000";
elsif clk'event and clk='1' then
if ack='1' then
be_wr(0 to 2)<= "000";
elsif ack8i='1' and rnw='0' then
if adr8(30 to 31)= "00" then
dout(0 to 7)<= din8;
be_wr(0)<= '1';
elsif adr8(30 to 31)= "01" then
dout(8 to 15)<= din8;
be_wr(1)<= '1';
elsif adr8(30 to 31)= "10" then
dout(16 to 23)<= din8;
be_wr(2)<= '1';
end if;
end if;
end if;
end process;
dout(24 to 31)<= din8;
-- read buffer be_rd(1)<= the MSBs read bytes are valid
process(arst, clk) begin
if arst='1' then buf_rd<= (others=>'0'); be_rd<= '0';
elsif clk'event and clk='1' then
if ack='1' then
buf_rd<= din(8 to 31);
end if;
if seqAddr='0' then
be_rd<= '0';
elsif ack='1' and rnw='1' then
be_rd<= '1';
elsif ack8i='1' and adr8(30 to 31)="11" then -- the last read
be_rd<='0';
end if;
end if;
end process;
dout8<= din(0 to 7) when adr8(30 to 31)="00" else
buf_rd(8 to 15) when adr8(30 to 31)="01" else
buf_rd(16 to 23) when adr8(30 to 31)="10" else
buf_rd(24 to 31);
stbi<= be_wr(0) or be_wr(1) or be_wr(2) when seqAddr='0' else -- finish the cycle without the full transfer or
'0' when stb8='0' else -- direct copy of the one byte (therefore stb8 must be '1')
( (not adr8(30)) and (not adr8(31))) or not be_rd when rnw='1' else -- read the MSB or the start of reading
'1' when adr8(30 to 31)= "11" else '0'; -- write the LSB
be(0)<= be_wr(0) when rnw='0' else -- when write
'1' when adr8(30 to 31)="00" else '0'; -- read
be(1)<= be_wr(1) when rnw='0' else -- when write
'1' when adr8(30)='0' else '0'; -- read
be(2)<= be_wr(2) when rnw='0' else -- when write
'1' when adr8(30 to 31)/="11" else '0'; -- read
be(3)<= '1' when rnw='1' else -- read
'1' when adr8(30 to 31)="11" else '0'; -- direct write
ack8i<= ack when rnw='1' and adr8(30 to 31)="00" else -- direct read
stb8 and be_rd when rnw='1' else -- read from the buffer (3 LSBs)
stb8 when adr8(30 to 31)/="11" else -- (not the LSB) write to buffer
ack; -- the direct write to the LSB
buf_valid<= be_wr(0) or be_wr(1) or be_wr(2);
adr(0 to 29)<= adr8(0 to 29);
adr(30 to 31)<= "00" when be_wr(0)='1' else
"01" when be_wr(1)='1' else
"10" when be_wr(1)='1' else
adr8(30 to 31);
end generate;
end generate;
--------------------------------------------------------------------------------------------------------------
g0: if use_seqAddr<=0 and dwidth>8 generate -- combinational logic
stbi<= stb8;
ack8<= ack;
buf_valid<= '0';
adr<= adr8;
g16: if dwidth=16 generate
dout(0 to 7)<= din8;
dout(8 to 15)<= din8;
dout8<= din(0 to 7) when adr8(31)='0' else din(8 to 15);
be(0)<= not adr8(31);
be(1)<= adr8(31);
end generate;
g32: if dwidth=32 generate
dout(0 to 7)<= din8;
dout(8 to 15)<= din8;
dout(16 to 23)<= din8;
dout(24 to 31)<= din8;
dout8<= din(0 to 7) when adr8(30 to 31)="00" else
din(8 to 15) when adr8(30 to 31)="01" else
din(16 to 23) when adr8(30 to 31)="10" else
din(24 to 31);
be(0)<= '1' when adr8(30 to 31)="00" else '0';
be(1)<= '1' when adr8(30 to 31)="01" else '0';
be(2)<= '1' when adr8(30 to 31)="10" else '0';
be(3)<= '1' when adr8(30 to 31)="11" else '0';
end generate;
end generate;
-- direct copy
g8: if dwidth=8 generate
stbi<= stb8;
ack8<= ack;
adr<= adr8;
buf_valid<= '0';
dout(0 to 7)<= din8;
dout8<= din;
be(0)<= '1';
end generate;
-- Additional flip-flop on stbi to reduce delay path
process(clk, arst) begin
if arst='1' then stb<='0';
elsif clk'event and clk='1' then
stb<= stbi and not ack;
end if;
end process;
end arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -