URL
https://opencores.org/ocsvn/pci_core/pci_core/trunk
Subversion Repositories pci_core
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/tags/alpha/vhdl_behav/Ms32pci.vhd
0,0 → 1,827
--===================================================================-- |
-- |
-- www.OpenCores.Org - June 2000 |
-- This model adheres to the GNU public license |
-- |
-- Design units : Master device for PCI Local Bus 33 MHz 32 bits |
-- (BoardLevel Simulation model) |
-- (Entity and architecture) |
-- |
-- File name : MS32PCI.vhd |
-- |
-- Purpose : The Master device is used to simulate a master |
-- device on the PCI-Bus |
-- |
-- Note : This model is modelled after the PCI protocol |
-- as described in Xilinx & Altera AppNotes |
-- |
-- Limitations : None known |
-- |
-- Errors : None known |
-- |
-- Library : PCI_Lib.vhd |
-- |
-- Dependencies : IEEE.Std_Logic_1164 |
-- |
-- Author : Ovidiu Lupas |
-- olupas@opencores.org |
-- |
-- Simulator : ModelSim EE version 5.2 on a Windows95 PC |
-- ActiveVHDL 3.1 on a Windows95 PC |
--===================================================================-- |
library ieee,work; |
use ieee.Std_Logic_1164.all; |
use work.Simulation.all; |
use std.textio.all; |
use work.PCI_Def.all; |
----------------------------------------------------------------------- |
-- ENTITY FOR MASTER PCI SIMULATION MODEL -- |
----------------------------------------------------------------------- |
entity MS32PCI is |
generic ( |
cmd_file : string := "PCI.CMD"; -- the commands file |
tdelay : Time := 2 ns; -- delay time parameter |
tsetup : Time := 7 ns; -- setup time to be checked |
thold : Time := 0 ns); -- hold time to be checked |
port ( |
-- Address, Data and Command buses (37) |
AD_Bus : inout STD_LOGIC_VECTOR (31 downto 0); |
C_BE_Bus : inout STD_LOGIC_VECTOR (3 downto 0); |
PAR : inout STD_LOGIC; |
-- Interface control signals (6) |
FRAME_N : inout STD_LOGIC; |
TRDY_N : in STD_LOGIC; |
IRDY_N : inout STD_LOGIC; |
STOP_N : in STD_LOGIC; |
DEVSEL_N : in STD_LOGIC; |
IDSEL : in STD_LOGIC; |
-- Error reporting signals (2) |
PERR_N : inout STD_LOGIC; |
SERR_N : inout STD_LOGIC; |
-- Arbitration signals (2) |
REQ_N : out STD_LOGIC; |
GNT_N : in STD_LOGIC; |
-- System signals (2) |
CLK : in STD_LOGIC; |
RST_N : in STD_LOGIC); |
end MS32PCI;--================== End of entity ======================-- |
----------------------------------------------------------------------- |
-- Architecture for Master device : PCI bus 33MHZ 32 bit configuration |
----------------------------------------------------------------------- |
architecture Behavior of MS32PCI is |
--------------------------------------------------------------------- |
-- Signals |
--------------------------------------------------------------------- |
signal parity_now : Std_Logic; -- internal variable (calculate parity) |
signal parity_read : Std_Logic; -- internal variable (parity at read) |
signal parity_flag : Boolean; -- internal variable (write ON/OFF on line PERR_N) |
signal PAR_READ_TEMP : Std_Logic; -- insert or no signal IRDY_N |
signal PAR_READ_FLAG : Std_Logic; -- insert or no signal IRDY_N |
--------------------------------------------------------------------- |
-- Variables |
--------------------------------------------------------------------- |
shared variable RESET : Integer; |
begin --======================= Architecture ========================-- |
--------------------------------------------------------------------- |
-- Process is used to initialize command |
--------------------------------------------------------------------- |
RSTproc : process(RST_N) |
begin |
if not RST_N'STABLE and RST_N ='0' then |
RESET := 1; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implements the parity generation and parity checking over the |
-- AD bus and C/BE bus. |
-- Also, generates the PERR_N signal, if the computed parity is not |
-- equal with PAR signal, when PAR signal is generated by target |
--------------------------------------------------------------------- |
ParGen : process(CLK) |
variable PERR_N_TEMP : Std_Logic; |
begin |
if not CLK'STABLE and CLK = '0' then |
PAR <= parity_now after tdelay; -- PAR ='1','0' or 'Z' |
PERR_N <= PERR_N_TEMP after tdelay ; |
SERR_N <= PERR_N_TEMP ; |
PAR_READ_TEMP <= parity_read ; |
|
if parity_flag = true then |
PAR_READ_FLAG <= '1'; |
else |
PAR_READ_FLAG <= '0'; |
end if; |
|
if PAR_READ_FLAG = '1' then -- |
if (PAR = PAR_READ_TEMP) then -- MASTER sets PERR_N |
PERR_N <= '1' after tdelay; |
else |
if PAR_READ_TEMP = 'Z' then |
PERR_N <= 'H' after tdelay; |
else |
PERR_N <= '0' after tdelay; |
end if; |
end if; |
else |
PERR_N <= 'H' after tdelay; |
end if; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- MAIN PROCESS FOR MASTER -- |
--------------------------------------------------------------------- |
MS32PCI_MAIN : process |
variable Data_array : Data_buffer; -- data array |
variable data_last_read : Boolean; |
variable irdy_start : Integer; -- variable is actualize |
variable irdy_loop : Integer; |
variable irdy_nr : Integer; -- by command WAITC |
variable irdy_insert : Boolean; -- assert or not IRDY_N |
------------------------------------------------------------------ |
-- Procedure is used to initialize MASTER and irdy_** variables -- |
------------------------------------------------------------------ |
procedure Init is |
begin |
RESET := 0; |
AD_Bus <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" ; -- Address and Data Bus |
C_BE_Bus <= "ZZZZ"; -- Command Bus |
PAR <= 'Z'; |
PERR_N <= 'Z'; |
REQ_N <= 'H'; |
SERR_N <= 'H'; |
irdy_start := 0; -- number of IRDY state |
irdy_nr := 0; |
irdy_loop := 255; |
parity_flag <= false; |
if irdy_loop = 0 or irdy_nr = 0 then |
irdy_insert := false; |
else |
irdy_insert := true; |
end if; |
end Init; |
------------------------------------------------------------------ |
-- This procedure calculate parity of signals address_data(31..0) |
-- and c_be(3..0) and return par_bit |
------------------------------------------------------------------ |
procedure PARITY( |
address_data : in STD_LOGIC_VECTOR(31 downto 0); |
c_be : in STD_LOGIC_VECTOR(3 downto 0); |
par_bit : inout STD_LOGIC) is |
begin |
par_bit := '0'; |
for I in 0 to 31 loop |
par_bit := par_bit xor address_data(I); |
end loop; |
|
for I in 0 to 3 loop |
par_bit := par_bit xor c_be(I); |
end loop; |
|
if (par_bit = 'X' or par_bit = 'U') then |
par_bit := 'Z'; |
end if; |
end PARITY; |
-------------------------------------------------------------------------- |
-- This procedure is used for READ_Bus and WRITE_Bus operation -- |
-------------------------------------------------------------------------- |
procedure READ_WRITE( |
address : in STD_LOGIC_VECTOR(31 downto 0); -- address |
data : in Data_buffer; -- data to write operation |
data_nr : in Integer; -- number of data DWORD(32 bit) |
bus_cmd : in STD_LOGIC_VECTOR(3 downto 0); -- bus command |
bus_sel : in Data_Enable; -- C/BE lines |
rd_wr : in STD_LOGIC) is -- select read or write operation |
variable data_number : Integer; -- number of data to read and write |
variable data_read : Std_Logic_Vector(31 downto 0); -- data read |
variable data_old : Std_Logic_Vector(31 downto 0); -- data read old |
variable stop : Boolean; -- internal variable (determined by STOP_N) |
variable str8 : string(1 to 8); |
variable Good2 : Boolean; |
variable nr_irdy : Integer; -- duration of IRDY pulse |
variable loop_irdy : Integer; -- position of IRDY pulse |
variable start_irdy : Integer; -- used for master-abord termination |
variable parity_temp : Std_Logic; -- internal variable |
variable trdy_stop : Integer; -- internal variable |
variable trdy_exit : Boolean; -- internal variable |
begin |
if GNT_N /= '1' then |
wait until FALLING_EDGE(CLK); -- start cycle |
end if; |
|
while (GNT_N /= '0' and GNT_N /= 'L') and (RESET = 0) loop |
wait until FALLING_EDGE(CLK); |
AD_Bus(31 downto 0) <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
C_BE_Bus(3 downto 0) <= "ZZZZ" after tdelay; |
FRAME_N <= 'Z';-- after tdelay; |
IRDY_N <= 'Z' after tdelay; |
parity_now <= 'Z' after tdelay; |
REQ_N <= '0' after tdelay; |
end loop; |
|
if (RESET = 0) then |
-- exit curent instruction if signal RST_N is active |
-- GM |
--- acces to the bus has been granted |
data_number := data_nr; -- number of DWORDs for transfer |
stop := false; -- |
start_irdy := 3; -- |
nr_irdy := irdy_nr; -- actualize internal variable |
loop_irdy := irdy_loop; -- --"-- |
irdy_insert := true; -- --"-- |
trdy_stop := 8; -- wait maximum 8 clock cycles for TRDY |
trdy_exit := false; |
|
if rd_wr = '1' then -- READ /WRITE CYCLE |
-------------------------------------------------------------------- |
-- BEGIN READ CYCLE -- |
-------------------------------------------------------------------- |
-- address phase |
AD_Bus(31 downto 0) <= address(31 downto 0) after tdelay; -- set address |
C_BE_Bus(3 downto 0) <= bus_cmd(3 downto 0) after tdelay; -- set command |
FRAME_N <= '0';-- after tdelay; |
IRDY_N <= '1' after tdelay; |
parity_flag <= false; |
parity_read <= 'Z' after tdelay; |
-- calculate parity of address cycle |
parity(address(31 downto 0), bus_cmd(3 downto 0), parity_temp); |
parity_now <= parity_temp; |
|
if GNT_N'Last_Event <= tsetup then -- GNT setup time violation ? |
report "GNT setup time violation" |
severity Warning; |
end if; |
wait until FALLING_EDGE(CLK); -- make turnarround cycle |
-- GM |
REQ_N <= '1'; |
-- END GM |
IRDY_N <= '0' after tdelay; |
|
AD_Bus(31 downto 0) <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
C_BE_Bus(3 downto 0) <= bus_sel(1) after tdelay; |
parity_now <= 'Z'; |
wait until FALLING_EDGE(CLK); -- end turnarround cycle |
|
-- wait for DEVSEL_N = '0' |
-- (implement MASTER-ABORT if TARGET is not responding) |
-- wait for the number of IRDY state |
while ((start_irdy > 0) and (DEVSEL_N = '1' or DEVSEL_N = 'H' or |
DEVSEL_N = 'Z' or DEVSEL_N = 'X') ) loop |
start_irdy := start_irdy -1; -- from the begining of read cycle |
AD_Bus(31 downto 0) <="ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
C_BE_Bus(3 downto 0) <= bus_sel(1) after tdelay; |
wait until FALLING_EDGE(CLK); |
end loop; |
--- exit cycle if RST_N or STOP_N are active |
if RESET =1 or STOP_N = '0' or STOP_N ='L' then |
stop := true; -- exit cycle |
end if; |
|
if DEVSEL_N'Last_Event <= tsetup then |
report "DEVSEL_N setup time violation" |
severity Warning; |
end if; |
|
--- inset IRDY_N if loop_irdy =1 and nr_irdy >1 |
if loop_irdy =1 then |
while (nr_irdy > 1) loop |
IRDY_N <='1' after tdelay; |
nr_irdy := nr_irdy -1 ; |
wait until FALLING_EDGE(CLK); |
end loop; |
IRDY_N <='0' after tdelay; |
end if; |
|
-- terminate cycle because DEVSEL_N is anactive |
-- (implement command MASTER-ABORT TERMINATION ) |
if start_irdy = 0 then -- terminate cycle |
stop := true; |
FRAME_N <='1'; -- after tdelay; |
end if; |
|
-- wait until FALLING_EDGE(CLK); |
-- repeat until all data are read or STOP_N ='0' |
while ((data_number > 0) and (stop = false)) loop -- read cycle |
parity_flag <= true; |
data_number := data_number -1; |
parity_flag <= true; |
data_read := data(data_nr - data_number); |
if data_number = 0 then |
C_BE_Bus(3 downto 0) <=bus_sel(data_nr) after tdelay; |
data_read := data(data_nr); |
else |
C_BE_Bus(3 downto 0) <=bus_sel(data_nr - data_number+1) after tdelay; |
data_read := data(data_nr - data_number); |
end if; |
|
parity_flag <= true; |
if data_number =0 then |
FRAME_N <='1';-- after tdelay; |
end if; |
|
-- exit cycle if RST_N or STOP_N are active |
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
irdy_insert := false; |
end if; |
|
if irdy_insert = true and (data_nr - data_number) = loop_irdy then |
-- insert IRDY ='1' if insert_trdy =true |
while nr_irdy > 1 loop |
nr_irdy := nr_irdy -1 ; |
IRDY_N <= '1' after tdelay; -- insert IRDY |
-- exit cycle if RST_N or STOP_N are active |
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
nr_irdy := 1; |
end if; |
wait until FALLING_EDGE(CLK); |
end loop; -- end loop nr_irdy |
end if; -- end if irdy_insert |
|
-- IRDY_N <= '0' after tdelay; |
if data_number = 0 then |
IRDY_N <= '0' after tdelay; |
end if; |
wait until RISING_EDGE(CLK); |
|
if TRDY_N'Last_Event <= tsetup then -- end of cycle |
report "TRDY_N setup time violation" |
severity Warning; |
end if; |
|
-- wait for TRDY_N = '0' (maxim 8 clock pulse) |
while TRDY_N = '1' and trdy_exit = false loop |
wait until RISING_EDGE(CLK); |
-- wait maxim 8 clock pulse if TRDY is asserted |
trdy_stop := trdy_stop -1; |
if trdy_stop = 0 then |
stop := true; |
report "Target is not responding " |
severity Warning; |
FRAME_N <= '1';-- after tdelay; |
IRDY_N <= '1' after tdelay; |
trdy_exit := true; |
end if; |
|
-- exit cycle if RST_N or STOP_N are active |
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
trdy_exit := true; |
end if; |
end loop; -- end loop TRDY_N=1 |
|
Vec2Hex (data_read,str8,Good2); |
report " EXPECTED DATA= "&str8 &""; -- display expected data |
|
Vec2Hex (AD_Bus,str8,Good2); |
report " READ DATA= "&str8 &""; -- display receive data |
|
if AD_Bus'Last_Event <= tsetup then -- end of cycle |
report "AD_BUS setup time violation" |
severity Warning; |
end if; |
|
if ((data_number >0) and (stop =false)) then |
wait until FALLING_EDGE(CLK); |
end if; |
|
wait for thold; |
if AD_Bus'Last_Event <= thold then -- end of cycle |
report "AD_Bus hold time violation" |
severity Warning; |
end if; |
end loop; -- end loop data_number |
|
if RESET =1 or STOP_N ='0' or STOP_N ='L' then |
AD_Bus(31 downto 0) <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
C_BE_Bus(3 downto 0) <= "ZZZZ" after tdelay; |
FRAME_N <= 'Z';-- after tdelay; |
IRDY_N <= 'Z' after tdelay; |
parity_now <= 'Z' after tdelay; |
REQ_N <= 'H' after tdelay; |
parity_flag <= false; |
end if; |
else |
-------------------------------------------------------------------- |
-- BEGIN WRITE CYCLE -- |
-------------------------------------------------------------------- |
-- adress phase |
parity_flag <= false; |
nr_irdy := nr_irdy; |
AD_Bus(31 downto 0) <= address(31 downto 0) after tdelay; -- set address |
C_BE_Bus(3 downto 0) <= bus_cmd(3 downto 0)after tdelay; -- set command |
FRAME_N <= '0'; -- after tdelay; |
IRDY_N <= '1' after tdelay; |
parity_read <= 'Z'; |
parity(address(31 downto 0), bus_cmd(3 downto 0), parity_temp); -- calculate parity of address cycle |
parity_now <= parity_temp after tdelay; |
wait until FALLING_EDGE(CLK); |
-- end adress phase |
|
REQ_N <='1'; |
|
parity_flag <= false; |
IRDY_N <= '0' after tdelay; |
-- wait for 1 ns; |
-- wait for DEVSEL_N = '0' |
-- (implement command MASTER-ABORT TERMINATION if TARGET not respond) |
while ((start_irdy > 0) and (DEVSEL_N ='H' or DEVSEL_N ='Z' or DEVSEL_N ='X') ) loop -- wait for the number of IRDY state |
start_irdy := start_irdy -1; -- from the begining of read cycle |
wait until FALLING_EDGE(CLK); |
end loop; |
|
-- if device not respond then exits the write command |
if start_irdy = 0 then -- terminate cycle |
stop := true; |
FRAME_N <= '1';-- after tdelay; |
end if; |
|
if DEVSEL_N'Last_Event <= tsetup then |
report "DEVSEL_N setup time violation" |
severity Warning; |
end if; |
|
while ((data_number >0) and (stop =false)) loop |
-- data phase |
data_number := data_number -1; |
AD_Bus(31 downto 0) <= data(data_nr - data_number) after tdelay; -- set DATA |
C_BE_Bus(3 downto 0) <= bus_sel(data_nr - data_number) after tdelay; -- set BE#s |
IRDY_N <= '0' after tdelay; |
parity(data(data_nr - data_number), bus_sel(data_nr - data_number), parity_temp); -- calculate parity |
parity_now <= parity_temp after tdelay; |
-- end data phase |
|
if data_number = 0 then |
FRAME_N <= '1';-- after tdelay; |
end if; |
|
-- exit cycle if RST_N,GNT_N or STOP_N are active |
if RESET = 1 or STOP_N= '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
end if; |
|
wait until RISING_EDGE(CLK); |
|
if TRDY_N'Last_Event <= tsetup then -- end of cycle |
report "TRDY_N setup time violation" |
severity Warning; |
end if; |
|
-- wait for TRDY_N ='0' |
while TRDY_N ='1' and trdy_exit = false loop |
wait until RISING_EDGE(CLK); |
-- wait maxim 8 clock pulse if TRDY is asserted |
trdy_stop := trdy_stop -1; |
if trdy_stop = 0 then |
stop := true; |
report "Target is not responding " |
severity Warning; |
FRAME_N <= '1';-- after tdelay; |
IRDY_N <= '1' after tdelay; |
trdy_exit := true; |
end if; |
|
-- exit cycle if RST_N,GNT_N or STOP_N are active |
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
trdy_exit := true; |
end if; |
end loop; -- end loop TRDY=1 |
|
if ((data_number > 0) and (stop = false)) then |
wait until FALLING_EDGE(CLK); -- synchronize with PCICLK |
end if; |
-- insert IRDY_N |
if irdy_insert = true and (data_nr -data_number) = loop_irdy |
and data_number >0 and (stop =false) then |
while nr_irdy > 1 loop |
IRDY_N <='1' after tdelay; |
nr_irdy := nr_irdy -1 ; |
if nr_irdy > 0 then |
if data_number > 0 then |
C_BE_Bus(3 downto 0) <=bus_sel(data_nr - data_number +1) after tdelay; -- set BE#s |
parity(data(data_nr - data_number), bus_sel(data_nr - data_number+1), parity_temp); -- calculate parity |
parity_now <= parity_temp after tdelay; |
end if; |
wait until FALLING_EDGE(CLK); |
end if; |
|
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
stop := true; -- exit cycle |
nr_irdy := 1; |
end if; |
end loop; -- end loop nr_irdy |
end if; |
report " WRITE DATA= "&str8 &""; -- display write data |
end loop; -- end loop start_irdy > 0 ... |
|
if RESET = 1 or STOP_N = '0' or STOP_N = 'L' then |
AD_Bus(31 downto 0) <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
C_BE_Bus(3 downto 0) <= "ZZZZ" after tdelay; |
FRAME_N <= 'Z';-- after tdelay; |
IRDY_N <= 'Z' after tdelay; |
parity_now <= 'Z' after tdelay; |
REQ_N <= 'H' after tdelay; |
parity_flag <= false; |
end if; |
end if; -- end rd_wr = '1' |
end if; -- if RST_N ='0' then |
end READ_WRITE; |
-------------------------------------------------------------------------- |
-- Procedure implement instruction WRSW -- |
-------------------------------------------------------------------------- |
-- Writes single DWORD to memory space! |
procedure WRSW( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "0111"; |
address(1 downto 0) := "00"; |
Vec2Hex (data(1),str8,Good2); |
Vec2Hex (address,str_8,Good2); |
report "Write single DWORD to memory space! Address : "&str_8; |
READ_WRITE(address,data,1,bus_cmd,bus_sel,'0'); |
end WRSW; |
-------------------------------------------------------------------------- |
-- Procedure implement instruction RDSW -- |
-------------------------------------------------------------------------- |
-- Reads single DWORD from memory space! |
procedure RDSW( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "0110"; |
address(1 downto 0) := "00"; |
Vec2Hex (address,str_8,Good2); |
report "Read single DWORD from memory space! Address : "&str_8 ; |
READ_WRITE(address,data,1,bus_cmd,bus_sel,'1'); |
end RDSW; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction WRMW -- |
-------------------------------------------------------------------------- |
-- Writes multiple DWORDs to memory space - burst mode |
procedure WRMW( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "1111"; |
address(1 downto 0) := "10"; |
Vec2Hex (address,str_8,Good2); |
report "Write multiple DWORDs to memory space! Address : "&str_8 ; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'0'); |
end WRMW; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction RDMW -- |
-------------------------------------------------------------------------- |
-- Reads multiple DWORDs from memory space - burst mode |
procedure RDMW( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "1100"; |
address(1 downto 0) := "10"; |
Vec2Hex (address,str_8,Good2); |
report "Read multiple DWORDs from memory space! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'1'); |
end RDMW; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction RDML -- |
-------------------------------------------------------------------------- |
-- Reads multiple DWORDs from memory space! |
procedure RDML( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd: STD_LOGIC_VECTOR(3 downto 0); |
variable read_data: Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "1110"; |
address(1 downto 0) := "00"; |
Vec2Hex (address,str_8,Good2); |
report "Reads multiple DWORDs from memory space! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'1'); |
end RDML; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction WCFG -- |
-------------------------------------------------------------------------- |
-- writes configuration |
procedure WCFG( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd :="1011"; |
address(1 downto 0) :="00"; -- linear incrementing |
Vec2Hex (address,str_8,Good2); |
report "Configuration write! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'0'); |
end WCFG; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction RCFG -- |
-------------------------------------------------------------------------- |
-- reads configuration |
procedure RCFG( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd :="1010"; |
address(1 downto 0) :="00"; |
Vec2Hex (address,str_8,Good2); |
report "Configuration read ! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'1'); |
end RCFG; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction WRIO -- |
-------------------------------------------------------------------------- |
-- writes data to IO port |
procedure WRIO( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd := "0011"; |
address(1 downto 0) := "00"; |
Vec2Hex (address,str_8,Good2); |
report "Write DWORD to I/O space! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'0'); |
end WRIO; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction RDIO -- |
-------------------------------------------------------------------------- |
-- reads data from IO port |
procedure RDIO( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable read_data : Data_buffer; |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
begin |
bus_cmd :="0010"; |
address(1 downto 0) :="00"; |
Vec2Hex (address,str_8,Good2); |
report "Read DWORD from memory space! Address : "&str_8; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'1'); |
end RDIO; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction WAIT -- |
-------------------------------------------------------------------------- |
-- waits |
procedure CWAT( |
data : in Data_buffer; |
address : inout STD_LOGIC_VECTOR(31 downto 0); |
data_number : in Integer; |
bus_sel : in Data_Enable) is |
variable bus_cmd : STD_LOGIC_VECTOR(3 downto 0); |
variable str8,str_8 : string(1 to 8); |
variable Good2 : Boolean; |
variable byte7_6,byte5,byte4,byte3_2,byte1,byte0 : Integer; |
variable Char7_6,Char5,Char4,Char3_2,Char1,Char0 : Std_Logic_Vector(7 downto 0); |
begin |
Char7_6 := data(1)(31 downto 24); |
irdy_loop := Byte2Int(Char7_6) ; |
Char5 := "0000" & data(1)(23 downto 20); |
irdy_nr := Byte2Int(Char5) + 1; |
Char4 := "0000" & data(1)(19 downto 16); |
irdy_start := Byte2Int(Char4); |
bus_cmd := "0001"; |
if irdy_loop = 0 or irdy_nr = 0 then |
irdy_insert := false; |
else |
irdy_insert := true; |
end if; |
READ_WRITE(address,data,data_number,bus_cmd,bus_sel,'0'); |
end CWAT; |
-------------------------------------------------------------------------- |
-- Procedure implements instruction EXIT -- |
-------------------------------------------------------------------------- |
-- ends the Master's activity by placing in HighZ all the lines |
procedure ABRT is |
begin |
wait until FALLING_EDGE(CLK); -- synchro cycle |
Init; |
wait; |
end ABRT; |
-------------------------------------------------------------------------- |
-- Procedure implements the commands file parser and sequencer -- |
-------------------------------------------------------------------------- |
procedure Main_case is |
variable Commands : CommandArray(1 to 100); |
variable NumCommands : Natural; |
variable Good : Boolean; |
constant HeaderMsg : String := "Main process:"; |
constant MsgSeverity : Severity_Level := Failure; |
variable ErrFlag : Boolean; |
variable PC : Integer; |
begin |
-- Read/Parse the commands file |
FileParser (cmd_file,Commands,NumCommands,ErrFlag); |
data_last_read := FALSE; |
if ErrFlag then |
report HeaderMsg&"Errors found in COMMAND file. Execute halts!!!" |
severity Warning; |
else |
PC := 0; |
wait until RST_N = '1'; |
while PC < NumCommands Loop |
if RESET = 1 then |
RESET := 0; |
PC := 0; |
end if; |
while RST_N = '0' loop -- RESET signal is active |
PC := 0; -- if RST_N ='0' restart simulation |
REQ_N <= 'H'; -- request is tri-stated |
wait until Rising_Edge(CLK); -- synchro wait |
end loop; |
if STOP_N = '0' then |
report HeaderMsg&"Wait until signal STOP_N ='0' !"; |
wait until STOP_N = '1'; |
end if; |
REQ_N <= '0'; |
|
PC := PC + 1; |
case Commands(pc).command is |
when "WRSW" => |
WRSW(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "RDSW" => |
RDSW(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "WRMW" => |
WRMW(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "RDMW" => |
RDMW(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "RDML" => |
RDML(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "WCFG" => |
WCFG(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "RCFG" => |
RCFG(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "WRIO" => |
WRIO(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "RDIO" => |
RDIO(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "CWAT" => |
CWAT(Commands(pc).data,Commands(PC).addr,Commands(pc).data_nr,Commands(pc).Enable); |
when "ABRT" => ABRT; |
when others => null; |
end case; |
end loop; |
end if; |
end Main_Case; |
--------------------------------------------------------------------- |
-- MS32PCI_MAIN : process begins |
--------------------------------------------------------------------- |
begin |
Init; |
Main_case; |
end process; |
end Behavior; --================= End of architecture ===============-- |
----------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas June 09, 2000 New model |
----------------------------------------------------------------------- |
|
/tags/alpha/vhdl_behav/Pci_lib.vhd
0,0 → 1,793
--===================================================================-- |
-- |
-- www.OpenCores.Org - June 2000 |
-- This model adheres to the GNU public license |
-- |
-- Design units : Functions and procedures used in models |
-- |
-- File name : PCI_LIB.vhd |
-- |
-- Purpose : type conversion functions, read commands file |
-- procedures |
-- |
-- Limitations : None known |
-- |
-- Errors : None known |
-- |
-- Library : PCI_Lib.vhd |
-- |
-- Dependencies : IEEE.Std_Logic_1164 |
-- |
-- Author : Ovidiu Lupas |
-- olupas@opencores.org |
-- |
-- Simulator : ModelSim EE version 5.2 on a Windows95 PC |
-- ActiveVHDL 3.1 on a Windows95 PC |
--===================================================================-- |
----------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas June 09, 2000 New model |
----------------------------------------------------------------------- |
library IEEE; |
use IEEE.Std_Logic_1164.all; |
-- |
package Simulation is |
-- Definition of the CommandType record array which is used to record |
-- the commands from the .cmd file |
type Data_buffer is array(1 to 256) of Std_Logic_Vector(31 downto 0); |
type Data_Enable is array(1 to 256) of Std_Logic_Vector(3 downto 0); |
|
type CommandType is |
record |
command : string(1 to 4); |
addr : Std_Logic_Vector(31 downto 0); |
data : Data_buffer; |
data_nr : Integer; |
enable : Data_Enable; |
end record; |
-- Definition of the CommandArray type type which can be used for |
-- the commands present in .cmd file |
type CommandArray is array(positive range <>) of CommandType; |
end Simulation; --========== End of package Simulation =============-- |
-- |
library IEEE,STD,work; |
library work; |
use work.Simulation.all; |
use IEEE.Std_Logic_1164.all; |
use STD.textio.all; |
-- |
package PCI_Def is |
-------------------------------------------------------------------- |
-- convert a character to a value from 0 to 15 |
-------------------------------------------------------------------- |
function digit_value( |
C : Character) |
return integer; |
-------------------------------------------------------------------- |
-- Converts unsigned Std_LOGIC_Vector to Integer, leftmost bit is MSB |
-- Error message for unknowns (U, X, W, Z, -), converted to 0 |
-- Verifies whether vector is too long (> 16 bits) |
-------------------------------------------------------------------- |
function Vec2Int ( |
Invector : in Std_Logic_Vector(15 downto 0)) |
return Integer; |
-------------------------------------------------------------------- |
-- Converts unsigned Std_Logic_Vector to Integer, leftmost bit is MSB |
-- Error message for unknowns (U, X, W, Z, -), converted to 0 |
-- Verifies whether vector is too long (> 16 bits) |
-------------------------------------------------------------------- |
function Byte2Int ( |
Invector : in Std_Logic_Vector(7 downto 0)) |
return Integer; |
-------------------------------------------------------------------- |
-- Converts unsigned Std_Logic_Vector to Integer, leftmost bit is MSB |
-- Error message for unknowns (U, X, W, Z, -), converted to 0 |
-- Verifies whether vector is too long (> 16 bits) |
-------------------------------------------------------------------- |
procedure Hex2Bit ( |
C : in Character; |
Vector : out Std_Logic_Vector(3 downto 0); |
Good : out Boolean); |
-------------------------------------------------------------------- |
-- Converts Hex characters to binary representation |
-- Asserts that no unknown value exists at the time of conversion. |
-------------------------------------------------------------------- |
procedure Bit2Hex ( |
Vector : in Std_Logic_Vector(3 downto 0); |
C : out Character; |
Good : out Boolean); |
-------------------------------------------------------------------- |
-- Converts bit_vector into a hex string |
-- Asserts that no unknown value exists at the time of conversion. |
-------------------------------------------------------------------- |
procedure Vec2Hex ( |
Value : in Std_Logic_Vector(31 downto 0); |
result : out String(1 to 8); |
Good : out Boolean); |
-------------------------------------------------------------------- |
-- read a number from the line |
-- use this if you have hex numbers that are not in VHDL pound-sign format |
-------------------------------------------------------------------- |
procedure Read ( |
L : inout Line; |
value : out Integer; |
radix : in Positive); |
-------------------------------------------------------------------- |
-- reads a hex value and returns a bit_vector value |
-------------------------------------------------------------------- |
procedure ReadHex ( |
L : inout Line; |
Value : out Std_Logic_Vector; |
Good : out Boolean; |
Enable: out Std_Logic_Vector); |
-------------------------------------------------------------------- |
-- Implements the parsing of the cmd file, which specifies the tasks |
-- that are applied to the processor. |
-------------------------------------------------------------------- |
procedure FileParser ( |
constant file_name : in String; |
variable Commands : inout CommandArray; |
variable NumCommands : out Natural; |
variable ErrFlag : inout Boolean); |
end PCI_Def; --============== End of package header =================-- |
-- |
library IEEE; |
use IEEE.Std_Logic_1164.all; |
library std; |
use std.textio.all; |
-- |
package body PCI_Def is |
-------------------------------------------------------------------- |
-- convert a character to a value from 0 to 15 |
-------------------------------------------------------------------- |
function digit_value ( |
C : Character) |
return integer is |
constant not_digit : integer := -999; |
begin |
if (C ='X') and (C ='x') then |
return 15; |
end if; |
if (C >= '0') and (C <= '9') then |
return (Character'pos(C) - Character'pos('0')); |
elsif (C >= 'a') and (C <= 'f') then |
return (character'pos(c) - character'pos('a') + 10); |
elsif (C >= 'A') and (C <= 'F') then |
return (character'pos(c) - character'pos('A') + 10); |
else |
return not_digit; |
end if; |
end digit_value; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
function Vec2Int ( |
InVector : in Std_Logic_Vector(15 downto 0)) |
return Integer is |
constant HeaderMsg : String := "To_Integer:"; |
constant MsgSeverity : Severity_Level := Warning; |
variable Value : Integer := 0; |
begin |
if InVector = "UUUUUUUUUUUUUUUU" then |
report HeaderMsg&"The input vector is of type 'U'. Converted to 0" |
severity MsgSeverity; |
elsif InVector = "XXXXXXXXXXXXXXXX" then |
report HeaderMsg&"The input vector is of type 'X'. Converted to 0" |
severity MsgSeverity; |
elsif InVector = "WWWWWWWWWWWWWWWW" then |
report HeaderMsg&"The input vector is of type 'W'. Converted to 0" |
severity MsgSeverity; |
elsif InVector = "ZZZZZZZZZZZZZZZZ" then |
report HeaderMsg&"The input vector is of type 'Z'. Converted to 0" |
severity MsgSeverity; |
else |
for i in 0 to 15 loop |
if (InVector(i) = '1') then |
Value := Value + (2**I); |
end if; |
end loop; |
end if; |
return Value; |
end Vec2Int; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
function Byte2Int ( |
InVector : in Std_Logic_Vector(7 downto 0)) |
return Integer is |
constant HeaderMsg : String := "To_Integer:"; |
constant MsgSeverity : Severity_Level := Warning; |
variable Value : Integer := 0; |
begin |
for i in 0 to 7 loop |
if (InVector(i) = '1') then |
Value := Value + (2**I); |
end if; |
end loop; |
return Value; |
end Byte2Int; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure Hex2Bit ( |
C : in Character; |
Vector : out Std_Logic_Vector(3 downto 0); |
Good : out Boolean) is |
variable Good1 : Boolean := false; |
constant HeaderMsg : String := "Hex2Bit:"; |
constant MsgSeverity : Severity_Level := Error; |
begin |
Good := false; |
case C is |
when '0' => Vector := "0000"; Good1 := true; |
when '1' => Vector := "0001"; Good1 := true; |
when '2' => Vector := "0010"; Good1 := true; |
when '3' => Vector := "0011"; Good1 := true; |
when '4' => Vector := "0100"; Good1 := true; |
when '5' => Vector := "0101"; Good1 := true; |
when '6' => Vector := "0110"; Good1 := true; |
when '7' => Vector := "0111"; Good1 := true; |
when '8' => Vector := "1000"; Good1 := true; |
when '9' => Vector := "1001"; Good1 := true; |
when 'A'|'a' => Vector := "1010"; Good1 := true; |
when 'B'|'b' => Vector := "1011"; Good1 := true; |
when 'C'|'c' => Vector := "1100"; Good1 := true; |
when 'D'|'d' => Vector := "1101"; Good1 := true; |
when 'E'|'e' => Vector := "1110"; Good1 := true; |
when 'F'|'f' => Vector := "1111"; Good1 := true; |
-- extended for std_LOGIC -- |
when 'U'|'u' => Vector := "UUUU"; Good1 := true; |
when 'X'|'x' => Vector := "1111"; Good1 := true; |
when 'Z'|'z' => Vector := "ZZZZ"; Good1 := true; |
when 'W'|'w' => Vector := "WWWW"; Good1 := true; |
when 'L'|'l' => Vector := "LLLL"; Good1 := true; |
when 'H'|'h' => Vector := "HHHH"; Good1 := true; |
when '-' => Vector := "----"; Good1 := true; |
when others => Good1 := false; |
end case; |
if not Good1 then |
Vector := "0000"; |
report HeaderMsg&"Expected a Hex character (0-F)" |
severity MsgSeverity; |
end if; |
Good := Good1; |
end Hex2Bit; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure Bit2Hex ( |
Vector : Std_Logic_Vector(3 downto 0); |
C : out Character; |
Good : out Boolean) is |
variable Good1 : Boolean := false; |
constant HeaderMsg : String := "Bit2Hex: "; |
constant MsgSeverity : Severity_Level := Error; |
begin |
Good := false; |
case Vector is |
when x"0" => C := '0'; Good1 := true; |
when x"1" => C := '1'; Good1 := true; |
when x"2" => C := '2'; Good1 := true; |
when x"3" => C := '3'; Good1 := true; |
when x"4" => C := '4'; Good1 := true; |
when x"5" => C := '5'; Good1 := true; |
when x"6" => C := '6'; Good1 := true; |
when x"7" => C := '7'; Good1 := true; |
when x"8" => C := '8'; Good1 := true; |
when x"9" => C := '9'; Good1 := true; |
when x"A" => C := 'A'; Good1 := true; |
when x"B" => C := 'B'; Good1 := true; |
when x"C" => C := 'C'; Good1 := true; |
when x"D" => C := 'D'; Good1 := true; |
when x"E" => C := 'E'; Good1 := true; |
when x"F" => C := 'F'; Good1 := true; |
when "ZZZZ" => C := 'Z'; Good1 := true; |
when others => Good1 := false; |
end case; |
if not Good1 then |
C := '0'; |
report HeaderMsg&"Expected a Hex character (0-F)" |
severity MsgSeverity; |
end if; |
Good := Good1; |
end Bit2Hex; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure Vec2Hex ( |
Value : in Std_Logic_Vector(31 downto 0); |
Result : out String(1 to 8); |
GOOD : out BOOLEAN) is |
variable OK : Boolean; |
variable C : Character; |
constant NE : Integer := value'length/4; -- number of Hex chars |
variable BV : Std_Logic_Vector(value'length-1 downto 0) := Value; |
variable Res : String(1 to 8); |
constant HeaderMsg : String := "Vec2Hex: "; |
constant MsgSeverity : Severity_Level := Error; |
begin |
if Value'length mod 4 /= 0 then -- Testing if Vector is mod 4 |
Good := false; |
report HeaderMsg&"The length of input vector is not modulo 4!" |
severity MsgSeverity; |
return; |
end if; |
Bit2Hex(BV(3 downto 0), C, OK); -- Conversion of the 4 LSB bits |
if not OK then |
Good := false; |
return; |
end if; |
Res := C & Res(2 to NE); -- Places first Char in Result |
for i in 1 to NE-1 loop |
Bit2Hex(BV(4*i+3 downto 4*i), C, OK); -- Converts next Char |
if not OK then |
Good := false; |
return; |
end if; |
Res := Res(1 to i) & C & Res(i+2 to NE); |
end loop; |
for i in 0 to NE-1 loop |
Result (1+i) := Res (NE-i); |
end loop; |
Good := true; |
end Vec2Hex; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure Read ( |
L : inout line; |
Value : out integer; |
Radix : in positive) is |
constant not_digit : integer := -999; |
variable Digit : integer; |
variable Result : integer := 0; |
variable Pos : integer; |
begin |
-- calculate the value |
if (L'length <=0 ) then |
for i in Pos to L'right loop |
digit := digit_value(L(i)); |
exit when (Digit = not_digit) or (digit >= radix); |
Result := Result * Radix + digit; |
Pos := Pos + 1; |
end loop; |
Value := Result; |
end if; |
end Read; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure ReadHex ( |
L : inout Line; |
Value : out Std_Logic_Vector; |
Good : out Boolean; |
Enable : out Std_Logic_Vector) is |
variable OK : Boolean; |
variable C : Character; |
constant NE : Integer := value'length/4; |
variable BV : Std_Logic_Vector(value'length-1 downto 0); |
variable TEMP : Std_Logic_Vector(value'length-1 downto 0); |
variable S : String(1 to NE-1); |
constant HeaderMsg : String := "Vec2Hex"; |
constant MsgSeverity : Severity_Level := Warning; |
begin |
Enable(3 downto 0) :="0000"; |
if Value'length mod 4 /= 0 then -- Testing if Vector is mod 4 |
Good := false; |
report HeaderMsg&"The length of input vector is not modulo 4!" |
severity MsgSeverity; |
return; |
end if; |
loop |
read(L, C, OK); -- Finds the first Hex Char |
exit when (((C /= ' ') and (C /= CR) and (C /= HT)) or |
(L'length = 0)); |
end loop; |
Hex2Bit(C, BV( 3 downto 0), OK); -- Converts first Hex Char to 4 Bits |
if C ='X' or C ='x' then |
Enable(3) :='1'; |
end if; |
|
if not OK then |
Good := false; |
return; |
end if; |
read(L, S, OK); -- Reads the next three Hex Chars |
if not OK then |
Good := false; |
return; |
end if; |
for i in 1 to NE-1 loop |
if s(i) ='X' or s(i) ='x' then |
if i=1 then |
Enable(3):='1'; |
end if; |
if i=2 or i=3 then |
Enable(2):='1'; |
end if; |
if i=4 or i=5 then |
Enable(1):='1'; |
end if; |
if i=6 or i=7 then |
Enable(0):='1'; |
end if; |
end if; |
Hex2Bit(s(i), BV(4*i+3 downto 4*i), OK); -- Converts to BitVector |
if not OK then |
Good := false; |
return; |
end if; |
end loop; |
Good := true; |
|
-- for byte |
if (value'length = 8 ) then |
for i in 0 to 3 loop |
TEMP(i) := BV(value'length-4+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+4) := BV(value'length-8+i); |
end loop; |
end if; |
|
-- for word |
if (value'length = 16 ) then |
for i in 0 to 3 loop |
TEMP(i) := BV(value'length-4+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+4) := BV(value'length-8+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+8) := BV(value'length-12+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+12) := BV(value'length-16+i); |
end loop; |
end if; |
|
-- for DWORD |
if (value'length =32 ) then |
for i in 0 to 3 loop |
TEMP(i) := BV(value'length-4+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+4) := BV(value'length-8+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+8) := BV(value'length-12+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+12) := BV(value'length-16+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+16) := BV(value'length-20+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+20) := BV(value'length-24+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+24) := BV(value'length-28+i); |
end loop; |
for i in 0 to 3 loop |
TEMP(i+28) := BV(value'length-32+i); |
end loop; |
end if; |
|
Value := TEMP; |
end ReadHex; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
procedure FileParser ( |
constant file_name : in String ; |
variable Commands : inout CommandArray; |
variable NumCommands : out Natural; |
variable ErrFlag : inout Boolean) is |
File CmdFile : text; |
constant HeaderMsg : String := "FileParser:"; |
constant MsgSeverity : Severity_Level := Error; |
variable L : Line := NULL; |
variable Linenum : Natural := 0; |
variable LblNum : Natural := 0; |
variable CmdNum : Natural := 0; |
variable EndOfFile : Boolean := false; |
variable Good : Boolean := false; |
variable Int : Integer; |
variable Tm : Time; |
variable C : Character; |
variable Addr : Std_Logic_Vector(31 downto 0); |
variable Data : Std_Logic_Vector(31 downto 0); |
variable Enable : Std_Logic_Vector(3 downto 0); |
variable Vect_count : Std_Logic_Vector(7 downto 0); |
variable Data_word : Std_Logic_Vector(15 downto 0); |
variable Data_byte : Std_Logic_Vector(7 downto 0); |
variable str4 : string(1 to 4); |
variable count_nr : Integer; |
variable count : Integer; |
begin |
ErrFlag := false; |
FILE_OPEN(CmdFile,file_name,READ_MODE); |
loop |
readline(CmdFile,L); |
EndOfFile := endfile(CmdFile); |
CmdNum := CmdNum + 1; |
LineNum := LineNum + 1; |
read(L, str4, Good); |
if not Good then |
CmdNum := CmdNum-1; |
else |
case str4 is |
when "WRSW" => -- write single word command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid WRSW command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_byte,Good,Enable); |
count_nr := Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "WRSW"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in WRSW command "; |
end if; |
end loop; |
end if; |
|
when "RDSW" => -- read single word command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid RDSW command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "RDSW"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in RDSW command "; |
end if; |
end loop; |
end if; |
|
when "WRMW" => -- write multiple words command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid WRMW command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "WRMW"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in WRMW command "; |
end if; |
end loop; |
end if; |
|
when "RDMW" => -- read multiple words command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid RDMW command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_Byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "RDMW"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in RDMW command "; |
end if; |
end loop; |
end if; |
|
when "RDML" => -- read multiple words command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid RDML command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_Byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "RDML"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in RDML command "; |
end if; |
end loop; |
end if; |
|
when "WCFG" => -- write to configuration space command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid WCFG command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "WCFG"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in WCFG command "; |
end if; |
end loop; |
end if; |
|
when "RCFG" => -- read from configuration space command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid RCFG command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_Byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good =true) then |
count := count + 1; |
commands(CmdNum).command := "RCFG"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in RCFG command "; |
end if; |
end loop; |
end if; |
|
when "WRIO" => -- write to I/O space command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid WRIO command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good = true) then |
count := count + 1; |
commands(CmdNum).command := "WRIO"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in WRIO command "; |
end if; |
end loop; |
end if; |
|
when "RDIO" => -- read from I/O space command |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid RDIO command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
Good := true; |
readhex(L,Data_Byte,Good,Enable); |
count_nr :=Byte2Int(Data_Byte); |
count := 0; |
for I in 0 to count_nr-1 loop |
readhex(L,Data,Good,Enable); |
if (Good = true) then |
count := count + 1; |
commands(CmdNum).command := "RDIO"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(count) := Data; |
commands(CmdNum).data_nr := count_nr; |
commands(CmdNum).enable(count) := Enable; |
else |
report HeaderMsg&"Invalid DATA in RDIO command "; |
end if; |
end loop; |
end if; |
|
when "CWAT" => |
readhex(L,Addr,Good,Enable); |
if not Good then |
report HeaderMsg&"Invalid CWAT command in :"&file_name&", line #"& integer'image(LineNum) &", "&"Address parameter should be 8 hex characters" |
severity MsgSeverity; |
ErrFlag := true; |
else |
count_nr :=0; |
readhex(L,Data,Good,Enable); |
if (Good = true) then |
count :=count +1; |
commands(CmdNum).command := "WAIT"; |
commands(CmdNum).addr := Addr; |
commands(CmdNum).data(1) := Data; |
commands(CmdNum).data_nr := 1; |
commands(CmdNum).enable(1) := Enable; |
else |
report HeaderMsg&"Invalid DATA in CWAT command "; |
end if; |
end if; |
|
when "ABRT" => |
count :=count + 1; |
commands(CmdNum).command := "ABRT"; |
commands(CmdNum).addr := "00000000000000000000000000000000"; |
commands(CmdNum).data(1) := "00000000000000000000000000000000"; |
commands(CmdNum).data_nr := 1; |
commands(CmdNum).enable(1) := Enable; |
|
when others => |
CmdNum := CmdNum -1; |
if str4(1 to 2)/= "##" then |
report HeaderMsg & "Invalid command in file: "&file_name&", line #"& integer'image(LineNum) &", "& "Unknown command : "& str4 & l(l'left to l'right) |
severity error; |
ErrFlag := true; |
end if; |
end case; |
end if; |
NumCommands := CmdNum; |
Exit when EndOfFile; |
end loop; |
end FileParser; |
-------------------------------------------------------------------- |
-------------------------------------------------------------------- |
end PCI_Def; --================ End of package body ================-- |
/tags/alpha/vhdl_behav/Test_pci.vhd
0,0 → 1,226
--===================================================================-- |
-- |
-- www.OpenCores.Org - January 2000 |
-- This model adheres to the GNU public license |
-- |
-- Design units : TestBench for PCI devices. |
-- |
-- File name : Test_PCI.vhd |
-- |
-- Purpose : Implements the test bench for PCI 33 MHz, 32 bit devices. |
-- It is included one master device and two target devices. |
-- |
-- There can be used more than one target devices in a |
-- design, every device being identified by the three |
-- base addresses in generic. |
-- |
-- |
-- Library : PCI_Lib |
-- |
-- Dependencies : IEEE.Std_Logic_1164 |
-- |
-- Limitations : None known |
-- |
-- Errors : None known |
-- |
-- Author : Ovidiu Lupas |
-- olupas@opencores.org |
-- |
-- Simulator : ModelSim EE version 5.2 on a Windows95 PC |
-- ActiveVHDL 3.1 on a Windows95 PC |
--===================================================================-- |
----------------------------------------------------------------------- |
-- Entity for PCI bus Arbiter and CLK generator |
----------------------------------------------------------------------- |
library ieee,work; |
use ieee.Std_Logic_1164.all; |
use work.Simulation.all; |
use work.PCI_Def.all; |
----------------------------------------------------------------------- |
----------------------------------------------------------------------- |
entity ClkGen is |
generic ( tperiod : Time := 30 ns ); |
port ( |
REQ_N : in Std_Logic; |
GNT_N : out Std_Logic := '1'; |
RST_N : out Std_Logic; |
CLK : out Std_Logic); -- System clock |
end ClkGen; --=================== End of entity =====================-- |
--========================== Architecture ===========================-- |
architecture BEHAV_ClkGen of ClkGen is |
begin--======================== Architecture =================================-- |
--------------------------------------------------------------------- |
-- Provide the external clock signal to the processor |
--------------------------------------------------------------------- |
ClkDriver : process |
variable clktmp: std_logic := '0'; |
begin |
CLK <= clktmp; |
clktmp := not clktmp; |
wait for tperiod/2; |
end process ClkDriver; |
--------------------------------------------------------------------- |
-- Simulates an external PCI-bus arbiter, which always grants the |
-- access to the bus :) |
--------------------------------------------------------------------- |
Arbiter : process(REQ_N) |
begin |
if Falling_Edge(REQ_N) then |
GNT_N <= '0' after 10 ns; |
elsif Rising_Edge(REQ_N) then |
GNT_N <= '1' after 10 ns; |
end if; |
end process Arbiter; |
--------------------------------------------------------------------- |
-- Provides the reset signal |
--------------------------------------------------------------------- |
RstGen: process |
begin |
RST_N <= '0'; |
wait for 100 ns; |
RST_N <= '1'; |
wait for 400 ns; |
end process; |
end BEHAV_ClkGen; --============== End of architecture ==============-- |
----------------------------------------------------------------------- |
-- TestBench |
----------------------------------------------------------------------- |
library ieee,work,std; |
use ieee.std_logic_1164.all; |
use work.ClkGen; |
----------------------------------------------------------------------- |
----------------------------------------------------------------------- |
entity TESTPCI is |
end TESTPCI; |
--========================== Architecture ===========================-- |
architecture stimulus of TESTPCI is |
--------------------------------------------------------------------- |
-- Signal declaration |
--------------------------------------------------------------------- |
signal AD_Bus : Std_Logic_Vector (31 downto 0); |
signal C_BE_Bus : Std_Logic_Vector (3 downto 0); |
signal PAR : Std_Logic; |
signal FRAME_N : Std_Logic; |
signal TRDY_N : Std_Logic; |
signal IRDY_N : Std_Logic; |
signal STOP_N : Std_Logic; |
signal DEVSEL_N : Std_Logic; |
signal IDSEL : Std_Logic; |
signal SEL1 : Std_Logic; |
signal SEL2 : Std_Logic; |
signal PERR_N : Std_Logic; |
signal SERR_N : Std_Logic; |
signal REQ_N : Std_Logic; |
signal GNT_N : Std_Logic; |
signal CLK : Std_Logic; |
signal RST_N : Std_Logic; |
--------------------------------------------------------------------- |
-- Component declarations |
--------------------------------------------------------------------- |
component ClkGen |
generic ( tperiod : Time := 30 ns ); |
port ( |
REQ_N : in Std_Logic; |
GNT_N : out Std_Logic; |
RST_N : out Std_Logic; |
CLK : out Std_Logic); -- System clock |
end component; |
--------------------------------------------------------------------- |
--------------------------------------------------------------------- |
component MS32PCI |
generic ( |
cmd_file : string(1 to 7); |
tdelay : Time; |
tsetup : Time; |
thold : Time); |
port ( |
-- Address, Data and Command buses (37) |
AD_Bus : inout STD_LOGIC_VECTOR (31 downto 0); |
C_BE_Bus : inout STD_LOGIC_VECTOR (3 downto 0); |
PAR : inout STD_LOGIC; |
-- Interface control signals (6) |
FRAME_N : inout STD_LOGIC; |
TRDY_N : in STD_LOGIC; |
IRDY_N : inout STD_LOGIC; |
STOP_N : in STD_LOGIC; |
DEVSEL_N : in STD_LOGIC; |
IDSEL : in STD_LOGIC; -- in |
-- Error reporting signals (2) |
PERR_N : inout STD_LOGIC; |
SERR_N : inout STD_LOGIC; |
-- Arbitration signals (2) |
REQ_N : out STD_LOGIC; |
GNT_N : in STD_LOGIC; -- in |
-- System signals (2) |
CLK : in STD_LOGIC; |
RST_N : in STD_LOGIC); --in |
end component; |
--------------------------------------------------------------------- |
--------------------------------------------------------------------- |
component TG32PCI |
generic ( |
devtype : string(1 to 4); |
tdelay : Time; |
tsetup : Time; |
thold : Time; |
bamem : Std_Logic_Vector(31 downto 0); -- hex value |
baio : Std_Logic_Vector(31 downto 0); -- hex value |
bacfg : Std_Logic_Vector(31 downto 0));-- hex value |
port ( |
-- Address, Data and Command buses (37) |
AD_Bus : inout Std_Logic_Vector (31 downto 0); |
C_BE_Bus : in Std_Logic_Vector (3 downto 0); |
PAR : inout Std_Logic; |
-- Interface control signals (6) |
FRAME_N : in Std_Logic; |
TRDY_N : inout Std_Logic; |
IRDY_N : in Std_Logic; |
STOP_N : out Std_Logic; |
DEVSEL_N : inout Std_Logic; |
IDSEL : in Std_Logic; |
-- Error reporting signals (2) |
PERR_N : inout Std_Logic; |
SERR_N : inout Std_Logic; |
-- System signals (2) |
CLK : in Std_Logic; |
RST_N : in Std_Logic); |
end component; |
begin --====================== Architecture =========================-- |
--------------------------------------------------------------------- |
-- Component instantiation |
--------------------------------------------------------------------- |
UUT1: MS32PCI |
generic map ( |
"PCI.CMD",0 ns, 7 ns, 5 ns) |
port map ( |
AD_Bus,C_BE_Bus,PAR,FRAME_N,TRDY_N,IRDY_N,STOP_N,DEVSEL_N, |
IDSEL,PERR_N,SERR_N,REQ_N,GNT_N,CLK,RST_N); |
SEL1 <= AD_Bus(16); |
UUT2: TG32PCI |
generic map ( |
"Fast",0 ns,0 ns,0 ns,x"00005000",x"00000800",x"00010CF0") |
port map ( |
AD_Bus => AD_Bus,C_BE_Bus => C_BE_Bus,PAR => PAR, |
FRAME_N => FRAME_N,TRDY_N => TRDY_N,IRDY_N => IRDY_N, |
STOP_N => STOP_N,DEVSEL_N => DEVSEL_N,IDSEL => SEL1, |
PERR_N => PERR_N,SERR_N => SERR_N,CLK => CLK,RST_N => RST_N); |
SEL2 <= AD_Bus(17); |
UUT3: TG32PCI |
generic map ( |
"Medi",0 ns,7 ns,0 ns,x"00006000",x"00001800",x"00020CF0") |
port map ( |
AD_Bus => AD_Bus,C_BE_Bus => C_BE_Bus,PAR => PAR, |
FRAME_N => FRAME_N,TRDY_N => TRDY_N,IRDY_N => IRDY_N, |
STOP_N => STOP_N,DEVSEL_N => DEVSEL_N,IDSEL => SEL2, |
PERR_N => PERR_N,SERR_N => SERR_N,CLK => CLK,RST_N => RST_N); |
GEN: ClkGen port map ( |
REQ_N,GNT_N,RST_N,CLK); |
--------------------------------------------------------------------- |
end stimulus; --=============== End of architecture =================-- |
----------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas June 09, 2000 New model |
----------------------------------------------------------------------- |
|
/tags/alpha/vhdl_behav/Tg32pci.vhd
0,0 → 1,1283
--===================================================================-- |
-- |
-- www.OpenCores.Org - January 2000 |
-- This model adheres to the GNU public license |
-- |
-- Design units : Target device for PCI Local Bus 33 MHz 32 bits |
-- (BoardLevel Simulation model) |
-- (Entity and architecture) |
-- |
-- File name : Tg32PCI.vhd |
-- |
-- Purpose : The Target device is used to simulate a target |
-- device on the PCI-Bus |
-- |
-- Note : This model is modelled after the PCI protocol |
-- as described in Xilinx & Altera AppNotes |
-- |
-- There can be used more than one target devices in a |
-- design, every device being identified by the three |
-- base addresses in generic. |
-- |
-- Limitations : None known |
-- |
-- Errors : None known |
-- |
-- Library : PCI_Lib.vhd |
-- |
-- Dependencies : IEEE.Std_Logic_1164 |
-- |
-- Author : Ovidiu Lupas |
-- olupas@opencores.org |
-- |
-- Simulator : ModelSim EE version 5.2 on a Windows95 PC |
-- ActiveVHDL 3.1 on a Windows95 PC |
--===================================================================-- |
----------------------------------------------------------------------- |
-- Entity for Target device in a PCI bus 33 MHZ 32 bit configuration |
----------------------------------------------------------------------- |
library ieee,work; |
use ieee.Std_Logic_1164.all; |
use work.Simulation.all; |
use work.PCI_Def.all; |
----------------------------------------------------------------------- |
----------------------------------------------------------------------- |
entity Target32PCI is |
generic ( |
devtype : string(1 to 4); -- type of the device (Fast, Medi, Slow) |
tdelay : Time; -- delay time parameter when the device will change |
-- data on AD_Bus (referenced to CLK signal) |
tsetup : Time; |
thold : Time; |
bamem : Std_Logic_Vector(31 downto 0); -- base address for memory |
baio : Std_Logic_Vector(31 downto 0); -- base address for I/O port |
bacfg : Std_Logic_Vector(31 downto 0)); -- base address for cfg space |
port ( |
-- Address, Data and Command buses (37) |
AD_Bus : inout Std_Logic_Vector (31 downto 0); -- Address and Data Bus |
C_BE_Bus : in Std_Logic_Vector (3 downto 0); -- Command Bus |
PAR : inout Std_Logic; -- |
-- Interface control signals (6) |
FRAME_N : in Std_Logic; |
TRDY_N : inout Std_Logic; |
IRDY_N : in Std_Logic; |
STOP_N : out Std_Logic; |
DEVSEL_N : inout Std_Logic; |
IDSEL : in Std_Logic; |
-- Error reporting signals (2) |
PERR_N : inout Std_Logic; |
SERR_N : inout Std_Logic; |
-- System signals (2) |
CLK : in Std_Logic; |
RST_N : in Std_Logic); |
end Target32PCI;--================ End of entity ====================-- |
----------------------------------------------------------------------- |
-- Architecture for Target device PCI bus 33MHZ 32 bit configuration |
----------------------------------------------------------------------- |
architecture Behavior of Target32PCI is |
--------------------------------------------------------------------- |
-- Definition of Memory type, |
--------------------------------------------------------------------- |
type MEMORY is array(0 to 255) of Std_Logic_Vector(31 downto 0); |
--------------------------------------------------------------------- |
-- Local declarations |
--------------------------------------------------------------------- |
shared variable addr : Std_Logic_Vector (31 downto 0); -- Address |
shared variable busaddr : Integer; -- address present on bus |
shared variable cfgaddr : Integer; -- current configuration register address |
shared variable memaddr : Integer; -- current memory address |
shared variable ioaddr : Integer; -- current I/O port address |
shared variable IOmem : Memory; -- IOport registers |
shared variable Cfgmem : Memory; -- Configuration registers |
shared variable Mem : Memory; -- memory locations |
shared variable trdywaits : Boolean := false; -- wait enable |
shared variable trdy_st,trdy_nr,trdy_loop : Integer := 0; |
--------------------------------------------------------------------- |
-- Signals |
--------------------------------------------------------------------- |
signal cmd : Std_Logic_Vector (3 downto 0); -- Command bus |
signal Busy : Std_Logic := '0'; |
signal IORead : Std_Logic := '0'; |
signal IOWrite : Std_Logic := '0'; |
signal MemRead : Std_Logic := '0'; |
signal MemWrite : Std_Logic := '0'; |
signal WaitWrite : Std_Logic := '0'; |
signal CfgRead : Std_Logic := '0'; |
signal CfgWrite : Std_Logic := '0'; |
signal FrameEv : Std_Logic := '0'; |
signal CmdBusReady : Std_Logic := '0'; |
signal TrnArnd : Std_Logic := '0'; |
signal DevAddr : Std_Logic := '0'; |
signal ResFin : Std_Logic := '0'; |
signal Waits : Std_Logic := '0'; |
signal Init : Std_Logic := '0'; |
begin--======================== Architecture ========================-- |
--------------------------------------------------------------------- |
-- Initialize the memory contents with zeroes |
--------------------------------------------------------------------- |
Initialize : process |
begin |
for i in 0 to 255 loop |
IOmem(i) := x"00000000"; |
Mem(i) := x"00000000"; |
Cfgmem(i) := x"00000000"; |
end loop; |
wait; |
end process; |
--------------------------------------------------------------------- |
-- Implements the parity generation and parity checking over the |
-- AD bus and C/BE bus. |
-- Also, generates the PERR_N signal, if the computed parity is not |
-- equal with PAR signal, when PAR signal is generated by master |
--------------------------------------------------------------------- |
Parity : process(CLK,RST_N) |
variable parbit : Std_Logic; |
variable lastpar : Std_Logic; |
variable errbit : Std_Logic; |
variable pargen : Boolean := false; |
variable errgen : Boolean := false; |
variable cmdbus : Std_Logic_Vector(3 downto 0); |
variable addrbus : Std_Logic_Vector(31 downto 0); |
begin |
if (Falling_Edge(RST_N) or RST_N = '0') then |
PAR <= 'Z'; |
PERR_N <= 'Z'; |
elsif (CLK'Event and CLK = '1') then -- parity computation on every cycle |
addrbus := AD_Bus; |
cmdbus := C_BE_Bus; |
lastpar := parbit; |
parbit := '0'; |
if addrbus /= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" then |
for I in 0 to 31 loop |
parbit := parbit xor addrbus(i); |
end loop; |
for I in 0 to 3 loop |
parbit := parbit xor cmdbus(I); |
end loop; |
else |
parbit := 'Z'; |
end if; |
if PAR = lastpar then -- PERR computation on every cycle |
errbit := '1'; |
elsif PAR /= lastpar then |
errbit := '0'; |
elsif PAR = 'Z' then |
errbit := 'H'; |
end if; |
if ((IORead = '1' or MemRead = '1' or CfgRead = '1') and DevAddr = '1') then |
pargen := true; |
else |
pargen := false; |
end if; |
elsif (CLK'Event and CLK = '0' and DevAddr = '1') then -- parity generation if necessary |
if errgen = true then |
PERR_N <= errbit; |
else |
PERR_N <= 'H'; |
end if; |
if pargen = true then |
PAR <= parbit; |
errgen := false; |
else |
PAR <= 'Z'; |
errgen := true; |
end if; |
elsif (CLK'Event and CLK = '0' and DevAddr = '0') then --not the selected device |
PAR <= 'Z'; -- by the address |
PERR_N <= 'H'; |
SERR_N <= 'Z'; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implements the command decoding, to receive commands from master |
--------------------------------------------------------------------- |
Decode : process(CLK,FRAME_N,Busy,DevAddr,cmdBusReady,RST_N) |
variable counter : Integer; |
variable devdel : Boolean := false; |
begin |
if (Falling_Edge(RST_N) or RST_N = '0') then |
DEVSEL_N <= 'Z'; |
STOP_N <= 'Z'; |
Busy <= '0'; |
elsif (Frame_N'Event and Frame_N = '0') then -- the target device is awakened by |
FrameEv <= '1'; -- falling_edge of FRAME signal |
counter := 0; |
elsif (Busy'Event and Busy = '0') then |
IOWrite <= '0'; |
MemWrite <= '0'; |
CfgWrite <= '0'; |
WaitWrite <= '0'; |
IORead <= '0'; |
MemRead <= '0'; |
CfgRead <= '0'; |
elsif (Busy'Event and Busy = '1') then |
if ( IOWrite = '1' or MemWrite = '1' or CfgWrite = '1' or WaitWrite = '1') then |
report "Target device is selected for write operations!" |
severity Note; |
if devtype = "Fast" then |
DEVSEL_N <= '0' after 8 ns; |
Stop_N <= '1' after 10 ns; |
devdel := false; |
else |
devdel := true; |
counter := 0; |
end if; |
elsif ( IORead = '1' or MemRead = '1' or CfgRead = '1') then |
report "Target device is selected for read operations!" |
severity Note; |
if devtype = "Fast" then |
DEVSEL_N <= '0' after 8 ns; |
Stop_N <= '1' after 10 ns; |
devdel := false; |
else |
devdel := true; |
counter := 0; |
end if; |
end if; |
elsif (DevAddr'Event and DevAddr = '0') then |
Busy <= '0'; |
elsif (cmdBusReady'Event and cmdBusReady = '1') then |
TrnArnd <= '0'; |
elsif (CLK'Event and CLK = '0') then |
if Busy = '0' and DevAddr = '1' then -- deselect |
DEVSEL_N <= 'H'; |
STOP_N <= '1'; |
elsif DevAddr = '0' then -- deselect device |
DEVSEL_N <= 'Z'; |
STOP_N <= 'Z'; |
end if; |
elsif (CLK'Event and CLK = '1') then |
if ResFin = '1' then -- memory reserved mode command |
if MemWrite = '1' then -- master writes to target memory |
if TRDY_N = '0' and IRDY_N = '0' then |
Busy <= '0'; |
ResFin <= '0'; |
end if; |
elsif MemRead = '1' then -- master reads from target memory |
if TrnArnd = '0' and TRDY_N = '0' and IRDY_N = '0' then |
Busy <= '0'; |
ResFin <= '0'; |
end if; |
end if; |
end if; |
if devdel = true then |
if devtype = "Medi" then |
if counter = 0 then |
DEVSEL_N <= '0' after 8 ns; |
Stop_N <= '1' after 10 ns; |
devdel := false; |
end if; |
elsif devtype = "Slow" then |
if counter = 1 then |
DEVSEL_N <= '0' after 8 ns; |
Stop_N <= '1' after 10 ns; |
devdel := false; |
else |
counter := counter + 1; |
end if; |
end if; |
end if; |
if FRAME_N = '1' then -- end of cycle |
assert (IRDY_N = '0') |
report "Target device : FRAME signal deassertion error. IRDY is not asserted." |
severity Error; |
if TRDY_N = '0' and IRDY_N = '0' then -- finish the current cycle |
Busy <= '0'; |
end if; |
elsif FrameEv = '1' then -- decoding |
FrameEv <= '0'; |
assert (FRAME_N'Last_Event >= tsetup) |
report "Target device : Frame setup time violation in decode cycle!" |
severity warning; |
assert (AD_Bus'Last_Event >= tsetup) |
report "Target device : Address setup time violation in decode cycle!" |
severity warning; |
assert (C_BE_Bus'Last_Event >= tsetup) |
report "Target device : Command setup time violation in decode cycle!" |
severity warning; |
addr := AD_Bus; |
case C_BE_Bus is -- decoding the command bus |
when "0001" => -- Special Cycle! Used to transfer from master device the |
-- wait states parameters |
if (addr(31 downto 8) = bacfg(31 downto 8) and IDSEL ='1') then |
WaitWrite <= '1'; |
DevAddr <= '1'; |
Busy <= '1'; |
trdywaits := true; |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
trdywaits := false; |
end if; |
cfgaddr := Byte2Int(addr(7 downto 0)); |
when "0010" => -- I/O Read! Master reads from target device. |
if addr(31 downto 8) = baio(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
IORead <= '1'; |
TrnArnd <= '1'; |
ioaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "0011" => -- I/O Write! Master writes to target device. |
if addr(31 downto 8) = baio(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
IOWrite <= '1'; |
ioaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "1100" => -- Memory Read! Master reads from target device. |
if addr(31 downto 8) = bamem(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
MemRead <= '1'; |
TrnArnd <= '1'; |
if addr(1 downto 0) = "01" then -- reserved mode |
ResFin <= '1'; |
elsif addr(1 downto 0) = "11" then -- reserved mode |
ResFin <= '1'; |
end if; |
memaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "1110" => -- Memory Read Line! Master reads from target device. |
if addr(31 downto 8) = bamem(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
MemRead <= '1'; |
TrnArnd <= '1'; |
if addr(1 downto 0) = "01" then -- reserved mode |
ResFin <= '1'; |
elsif addr(1 downto 0) = "11" then -- reserved mode |
ResFin <= '1'; |
end if; |
memaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "1111" => -- Memory Write! Master writes to target device. |
if addr(31 downto 8) = bamem(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
MemWrite <= '1'; |
if addr(1 downto 0) = "01" then -- reserved mode |
ResFin <= '1'; |
elsif addr(1 downto 0) = "11" then -- reserved mode |
ResFin <= '1'; |
end if; |
memaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "0110" => -- Memory Read! Master reads from target device. |
if addr(31 downto 8) = bamem(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
MemRead <= '1'; |
TrnArnd <= '1'; |
if addr(1 downto 0) = "01" then -- reserved mode |
ResFin <= '1'; |
elsif addr(1 downto 0) = "11" then -- reserved mode |
ResFin <= '1'; |
end if; |
memaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "0111" => -- Memory Write! Master writes to target device. |
if addr(31 downto 8) = bamem(31 downto 8) then |
DevAddr <= '1'; |
Busy <= '1'; |
MemWrite <= '1'; |
if addr(1 downto 0) = "01" then -- reserved mode |
ResFin <= '1'; |
elsif addr(1 downto 0) = "11" then -- reserved mode |
ResFin <= '1'; |
end if; |
memaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "1010" => -- Configuration Read! Master reads from target device. |
if (addr(31 downto 8) = bacfg(31 downto 8) and IDSEL = '1') then |
if addr(1 downto 0) = "01" then |
report "Target device: Type 1 configuration access on bus! Ignored." |
severity Note; |
elsif addr(1 downto 0) = "00" then |
CfgRead <= '1'; |
TrnArnd <= '1'; |
DevAddr <= '1'; |
Busy <= '1'; |
end if; |
cfgaddr := Byte2Int(addr(7 downto 0)); |
else -- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "1011" => -- Configuration Write! Master writes to target device. |
if (addr(31 downto 8) = bacfg(31 downto 8) and IDSEL = '1') then |
if addr(1 downto 0) = "01" then |
report "Target device: Type 1 configuration access on bus! Ignored." |
severity Note; |
elsif addr(1 downto 0) = "00" then |
CfgWrite <= '1'; |
DevAddr <= '1'; |
Busy <= '1'; |
end if; |
cfgaddr := Byte2Int(addr(7 downto 0)); |
else |
-- this device is not the addressed one, |
DevAddr <= '0'; -- so it is not responding |
end if; |
when "0100" => |
report "Target device: Reserved Command detected on C/BE bus! Target will not respond." |
severity Warning; |
when "0101" => |
report "Target device: Reserved Command detected on C/BE bus! Target will not respond." |
severity Warning; |
when "1000" => |
report "Target device: Reserved Command detected on C/BE bus! Target will not respond." |
severity Warning; |
when "1001" => |
report "Target device: Reserved Command detected on C/BE bus! Target will not respond." |
severity Warning; |
when "ZZZZ" => null; |
when others => |
report "Target device: Unknown or invalid command on C/BE bus! Ignored." |
severity Error; |
end case; |
end if; |
-- elsif (Frame_N'Event and Frame_N = '1') then |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implementation of Write command. |
-- Master writes to Target device. |
--------------------------------------------------------------------- |
WriteProc : process(CLK,RST_N) |
variable waitreg : Std_Logic_Vector(15 downto 0) := x"0000"; |
variable Char3_2,Char1,Char0 : Std_Logic_Vector(7 downto 0) := x"00"; |
begin |
if (CLK'Event and CLK = '1' and ((IRDY_N = '0' and TRDY_N = '0') or FRAME_N = '1')) then |
assert (AD_Bus'Last_Event >= tsetup) |
report "Target device : Data setup time violation in decode cycle!" |
severity warning; |
assert (C_BE_Bus'Last_Event >= tsetup) |
report "Target device : Byte Enables setup time violation in decode cycle!" |
severity warning; |
if (WaitWrite = '1') then |
Char3_2 := AD_Bus(15 downto 8); |
Char1 := "0000" & AD_Bus(7 downto 4); |
Char0 := "0000" & AD_Bus(3 downto 0); |
trdy_loop := Byte2Int(Char3_2) ; |
trdy_nr := Byte2Int(Char1); -- + 1; |
trdy_st := Byte2Int(Char0); |
elsif IOWrite = '1' then |
-- Master writes to target I/O space |
case addr(1 downto 0) is |
when "00" => |
if C_BE_Bus = "0000" then |
IOmem(ioaddr) := AD_Bus; |
elsif C_BE_Bus = "1000" then |
IOmem(ioaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "0100" then |
IOmem(ioaddr)(31 downto 24) := AD_Bus(31 downto 24); |
IOmem(ioaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1100" then |
IOmem(ioaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0010" then |
IOmem(ioaddr)(31 downto 16) := AD_Bus(31 downto 16); |
IOmem(ioaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1010" then |
IOmem(ioaddr)(23 downto 16) := AD_Bus(23 downto 16); |
IOmem(ioaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0110" then |
IOmem(ioaddr)(31 downto 24) := AD_Bus(31 downto 24); |
IOmem(ioaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1110" then |
IOmem(ioaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus(0) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "01" => |
if C_BE_Bus = "0001" then |
IOmem(ioaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "1001" then |
IOmem(ioaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "0101" then |
IOmem(ioaddr)(31 downto 24) := AD_Bus(31 downto 24); |
IOmem(ioaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1101" then |
IOmem(ioaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus(1) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "10" => |
if C_BE_Bus = "0011" then |
IOmem(ioaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "1011" then |
IOmem(ioaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus(2) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "11" => |
if C_BE_Bus = "0111" then |
IOmem(ioaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus(3) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when others => |
null; |
end case; |
ioaddr := ioaddr + 1; |
elsif MemWrite = '1' then |
-- Master writes to target memory space |
case addr(1 downto 0) is |
when "00" => -- linear incrementing mode |
if C_BE_Bus = "0000" then |
Mem(memaddr) := AD_Bus; |
elsif C_BE_Bus = "0001" then |
Mem(memaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "0010" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0011" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "0100" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0101" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "0110" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0111" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus = "1000" then |
Mem(memaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "1001" then |
Mem(memaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "1010" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1011" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus = "1100" then |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1101" then |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1110" then |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
memaddr := memaddr + 1; |
when "01" => -- reserved mode (disconnect after first data phase) |
if C_BE_Bus = "0000" then |
Mem(memaddr) := AD_Bus; |
elsif C_BE_Bus = "0001" then |
Mem(memaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "0010" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0011" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "0100" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0101" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "0110" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0111" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus = "1000" then |
Mem(memaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "1001" then |
Mem(memaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "1010" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1011" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus = "1100" then |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1101" then |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1110" then |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "10" => -- cacheline wrap mode |
if C_BE_Bus = "0000" then |
Mem(memaddr) := AD_Bus; |
elsif C_BE_Bus = "0001" then |
Mem(memaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "0010" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0011" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "0100" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0101" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "0110" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0111" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus = "1000" then |
Mem(memaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "1001" then |
Mem(memaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "1010" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1011" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus = "1100" then |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1101" then |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1110" then |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
memaddr := memaddr + 1; |
when "11" => -- reserved mode (disconnect after first data phase) |
if C_BE_Bus = "0000" then |
Mem(memaddr) := AD_Bus; |
elsif C_BE_Bus = "0001" then |
Mem(memaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "0010" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0011" then |
Mem(memaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "0100" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0101" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "0110" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0111" then |
Mem(memaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus = "1000" then |
Mem(memaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "1001" then |
Mem(memaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "1010" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1011" then |
Mem(memaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus = "1100" then |
Mem(memaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1101" then |
Mem(memaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1110" then |
Mem(memaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when others => |
null; |
end case; |
elsif CfgWrite = '1' then |
-- Master writes to target configuration space |
if C_BE_Bus = "0000" then |
Cfgmem(cfgaddr) := AD_Bus; |
elsif C_BE_Bus = "0001" then |
Cfgmem(cfgaddr)(31 downto 8) := AD_Bus(31 downto 8); |
elsif C_BE_Bus = "0010" then |
Cfgmem(cfgaddr)(31 downto 16) := AD_Bus(31 downto 16); |
Cfgmem(cfgaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0011" then |
Cfgmem(cfgaddr)(31 downto 16) := AD_Bus(31 downto 16); |
elsif C_BE_Bus = "0100" then |
Cfgmem(cfgaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Cfgmem(cfgaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "0101" then |
Cfgmem(cfgaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Cfgmem(cfgaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "0110" then |
Cfgmem(cfgaddr)(31 downto 24) := AD_Bus(31 downto 24); |
Cfgmem(cfgaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "0111" then |
Cfgmem(cfgaddr)(31 downto 24) := AD_Bus(31 downto 24); |
elsif C_BE_Bus = "1000" then |
Cfgmem(cfgaddr)(23 downto 0) := AD_Bus(23 downto 0); |
elsif C_BE_Bus = "1001" then |
Cfgmem(cfgaddr)(23 downto 8) := AD_Bus(23 downto 8); |
elsif C_BE_Bus = "1010" then |
Cfgmem(cfgaddr)(23 downto 16) := AD_Bus(23 downto 16); |
Cfgmem(cfgaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1011" then |
Cfgmem(cfgaddr)(23 downto 16) := AD_Bus(23 downto 16); |
elsif C_BE_Bus = "1100" then |
Cfgmem(cfgaddr)(15 downto 0) := AD_Bus(15 downto 0); |
elsif C_BE_Bus = "1101" then |
Cfgmem(cfgaddr)(15 downto 8) := AD_Bus(15 downto 8); |
elsif C_BE_Bus = "1110" then |
Cfgmem(cfgaddr)(7 downto 0) := AD_Bus(7 downto 0); |
elsif C_BE_Bus = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
cfgaddr := cfgaddr + 1; |
end if; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implementation of Read command. |
-- Master read from Target device. |
--------------------------------------------------------------------- |
ReadProc : process(RST_N,CLK,cmdBusReady,IORead,IOWrite,MemRead,MemWrite,CfgRead,CfgWrite) |
variable first : Boolean := true; |
begin |
if (Falling_Edge(RST_N) or RST_N = '0') then |
AD_Bus <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
elsif (CLK'Event and CLK = '0') then |
cmdBusReady <= '0'; |
if (first = true or TrnArnd ='1') then |
-- Initialize the AD_Bus to avoid bus conflict |
AD_Bus <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; |
first := false; |
elsif Init = '1' then |
Init <= '0'; |
AD_Bus <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" after tdelay; |
end if; |
elsif IORead'Event and IORead = '0' then |
Init <= '1'; |
elsif MemRead'Event and MemRead = '0' then |
Init <= '1'; |
elsif CfgRead'Event and CfgRead = '0' then |
Init <= '1'; |
elsif (CLK'Event and CLK = '1' and IRDY_N = '0') then |
if (IORead = '1' or MemRead = '1' or CfgRead = '1') then |
cmd <= C_BE_Bus; -- read the byte enable command |
cmdBusReady <= '1'; |
end if; |
elsif (cmdBusReady'Event and cmdBusReady = '0' and TRDY_N = '0') then |
if IORead = '1' then |
-- Master reads from target I/O space |
case addr(1 downto 0) is |
when "00" => |
if cmd = "0000" then |
AD_Bus <= IOmem(ioaddr) after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= IOmem(ioaddr)(23 downto 0) after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= IOmem(ioaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 0) <= IOmem(ioaddr)(15 downto 0) after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= IOmem(ioaddr)(15 downto 0) after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= IOmem(ioaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= IOmem(ioaddr)(7 downto 0) after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= IOmem(ioaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= IOmem(ioaddr)(7 downto 0) after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= IOmem(ioaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= IOmem(ioaddr)(7 downto 0) after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= IOmem(ioaddr)(7 downto 0) after tdelay; |
elsif cmd(0) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "01" => |
if cmd = "0001" then |
AD_Bus(31 downto 8) <= IOmem(ioaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= IOmem(ioaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= IOmem(ioaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= IOmem(ioaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= IOmem(ioaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd(1) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "10" => |
if cmd = "0011" then |
AD_Bus(31 downto 16) <= IOmem(ioaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= IOmem(ioaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd(2) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "11" => |
if cmd = "0111" then |
AD_Bus(31 downto 24) <= IOmem(ioaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd(3) = '1' then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when others => |
null; |
end case; |
ioaddr := ioaddr + 1; |
elsif MemRead = '1' then |
-- Master reads from target memory space |
case addr(1 downto 0) is |
when "00" => -- linear incrementing mode |
if cmd = "0000" then |
AD_Bus <= Mem(memaddr) after tdelay; |
elsif cmd = "0001" then |
AD_Bus(31 downto 8) <= Mem(memaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
elsif cmd = "0011" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "0111" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= Mem(memaddr)(23 downto 0) after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= Mem(memaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
memaddr := memaddr + 1; |
when "01" => -- reserved mode (disconnect after first data phase) |
if cmd = "0000" then |
AD_Bus <= Mem(memaddr) after tdelay; |
elsif cmd = "0001" then |
AD_Bus(31 downto 8) <= Mem(memaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
elsif cmd = "0011" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "0111" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= Mem(memaddr)(23 downto 0) after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= Mem(memaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when "10" => -- cacheline wrap mode |
if cmd = "0000" then |
AD_Bus <= Mem(memaddr) after tdelay; |
elsif cmd = "0001" then |
AD_Bus(31 downto 8) <= Mem(memaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
elsif cmd = "0011" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "0111" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= Mem(memaddr)(23 downto 0) after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= Mem(memaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
memaddr := memaddr + 1; |
when "11" => -- reserved mode (disconnect after first data phase) |
if cmd = "0000" then |
AD_Bus <= Mem(memaddr) after tdelay; |
elsif cmd = "0001" then |
AD_Bus(31 downto 8) <= Mem(memaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
elsif cmd = "0011" then |
AD_Bus(31 downto 16) <= Mem(memaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "0111" then |
AD_Bus(31 downto 24) <= Mem(memaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= Mem(memaddr)(23 downto 0) after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= Mem(memaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Mem(memaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= Mem(memaddr)(15 downto 0) after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= Mem(memaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Mem(memaddr)(7 downto 0) after tdelay; |
elsif cmd = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
when others => |
null; |
end case; |
elsif CfgRead = '1' then |
-- Master reads from target configuration space |
if cmd = "0000" then |
AD_Bus <= Cfgmem(cfgaddr) after tdelay; |
elsif cmd = "0001" then |
AD_Bus(31 downto 8) <= Cfgmem(cfgaddr)(31 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0010" then |
AD_Bus(31 downto 16) <= Cfgmem(cfgaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Cfgmem(cfgaddr)(7 downto 0) after tdelay; |
elsif cmd = "0011" then |
AD_Bus(31 downto 16) <= Cfgmem(cfgaddr)(31 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "0100" then |
AD_Bus(31 downto 24) <= Cfgmem(cfgaddr)(31 downto 24) after tdelay; |
AD_Bus(15 downto 0) <= Cfgmem(cfgaddr)(15 downto 0) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
elsif cmd = "0101" then |
AD_Bus(31 downto 24) <= Cfgmem(cfgaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 16) <= "11111111" after tdelay; |
AD_Bus(15 downto 8) <= Cfgmem(cfgaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "0110" then |
AD_Bus(31 downto 24) <= Cfgmem(cfgaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 8) <= "1111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Cfgmem(cfgaddr)(7 downto 0) after tdelay; |
elsif cmd = "0111" then |
AD_Bus(31 downto 24) <= Cfgmem(cfgaddr)(31 downto 24) after tdelay; |
AD_Bus(23 downto 0) <= "111111111111111111111111" after tdelay; |
elsif cmd = "1000" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 0) <= Cfgmem(cfgaddr)(23 downto 0) after tdelay; |
elsif cmd = "1001" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 8) <= Cfgmem(cfgaddr)(23 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1010" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Cfgmem(cfgaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 8) <= "11111111" after tdelay; |
AD_Bus(7 downto 0) <= Cfgmem(cfgaddr)(7 downto 0) after tdelay; |
elsif cmd = "1011" then |
AD_Bus(31 downto 24) <= "11111111" after tdelay; |
AD_Bus(23 downto 16) <= Cfgmem(cfgaddr)(23 downto 16) after tdelay; |
AD_Bus(15 downto 0) <= "1111111111111111" after tdelay; |
elsif cmd = "1100" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 0) <= Cfgmem(cfgaddr)(15 downto 0) after tdelay; |
elsif cmd = "1101" then |
AD_Bus(31 downto 16) <= "1111111111111111" after tdelay; |
AD_Bus(15 downto 8) <= Cfgmem(cfgaddr)(15 downto 8) after tdelay; |
AD_Bus(7 downto 0) <= "11111111" after tdelay; |
elsif cmd = "1110" then |
AD_Bus(31 downto 8) <= "111111111111111111111111" after tdelay; |
AD_Bus(7 downto 0) <= Cfgmem(cfgaddr)(7 downto 0) after tdelay; |
elsif cmd = "1111" then |
report "Target device: Byte Enable word not valid !" |
severity Error; |
end if; |
cfgaddr := cfgaddr + 1; |
end if; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implements the wait states process. |
-- Target generates wait states accordingly to wait states parameters |
-- received from master during Special Cycle. |
-- Master reads the parameters from commands file. |
--------------------------------------------------------------------- |
WaitProc : process(CLK,FRAME_N,RST_N) |
variable counter : Integer; |
variable waitcnt : Integer; |
variable start : Boolean; |
begin |
if (Falling_Edge(RST_N) or RST_N = '0') then |
TRDY_N <= 'Z'; |
elsif (FRAME_N'Event and FRAME_N = '0') then |
counter := 0; |
start := true; |
TRDY_N <= '1'; |
elsif (CLK'Event and CLK = '0') then |
if (Busy = '0' and DevAddr = '0') then -- deselect device |
TRDY_N <= 'H'; |
elsif (Busy = '0' and DevAddr = '1') then -- deselect signal |
TRDY_N <= '1'; |
end if; |
if (DevAddr = '1' and TrnArnd = '0' and DEVSEL_N = '0') then |
if (counter >= trdy_st and start = true and TRDY_N = '1') then |
-- finish waitstates at start |
TRDY_N <= '0'; |
start := false; |
elsif (counter = trdy_loop and TRDY_N = '0') then |
-- random waitstates |
TRDY_N <= '1'; |
waits <= '1'; |
waitcnt := 1; |
elsif (waitcnt = trdy_nr and waits = '1') then |
-- finish random waitstates |
waits <= '0'; |
TRDY_N <= '0'; |
elsif waits = '1' then -- count random waitstates |
waitcnt := waitcnt + 1; |
end if; |
end if; |
counter := counter + 1; |
end if; |
end process; |
--------------------------------------------------------------------- |
-- Implements the assertion process for IRDY_N, FRAME_N, and IDSEL |
-- signals. |
--------------------------------------------------------------------- |
AsrtProc : process(CLK,FRAME_N,IRDY_N,IDSEL,AD_Bus) |
variable irdevs : Boolean := false; |
variable idsevs : Boolean := false; |
variable counter : Integer; |
begin |
if Rising_Edge(CLK) and FRAME_N = '0' and IRDY_N = '1' then |
counter := counter + 1; |
if counter >= 8 then |
report"Target device:IRDY is not asserted within 8 clocks from FRAME assertion!" |
severity warning; |
end if; |
end if; |
if AD_Bus'Event then |
assert(CLK'Last_Event <= thold) |
report"Target device: Address or Data hold time violation!" |
severity warning; |
end if; |
if Rising_Edge(CLK) and DevAddr = '1' then |
if irdevs = true then |
irdevs := false; |
assert(IRDY_N'Last_Event >= tsetup) |
report"Target device: IRDY setup time violation in current data transfer!" |
severity warning; |
end if; |
if idsevs = true then |
idsevs := false; |
assert(IDSEL'Last_Event >= tsetup) |
report"Target device: IDSEL setup time violation!" |
severity warning; |
end if; |
if FRAME_N = '0' and IRDY_N = '1' then |
counter := counter + 1 ; |
end if; |
assert (counter <= 8) |
report"Target device: IRDY has not been asserted within 8 clocks from FRAME assertion!" |
severity warning; |
elsif Falling_Edge(FRAME_N) then |
counter := 0; |
elsif Rising_Edge(FRAME_N) then |
assert(CLK'Last_Event <= thold) |
report"Target device: FRAME hold time violation in current data transfer!" |
severity warning; |
elsif Falling_Edge(IRDY_N) and DevAddr = '1' then |
irdevs := true; |
elsif Rising_Edge(IRDY_N) and DevAddr = '1' then |
assert(CLK'Last_Event <= thold) |
report"Target device: IRDY hold time violation in current data transfer!" |
severity warning; |
elsif Rising_Edge(IDSEL) and DevAddr = '1' then |
idsevs := true; |
elsif Falling_Edge(IDSEL) and DevAddr = '1' then |
assert(CLK'Last_Event <= thold) |
report"Target device: IDSEL hold time violation!" |
severity warning; |
end if; |
end process; |
end Behavior; --================ End of architecture ================-- |
----------------------------------------------------------------------- |
-- Revision list |
-- Version Author Date Changes |
-- |
-- 0.1 Ovidiu Lupas June 09, 2000 New model |
----------------------------------------------------------------------- |
|
/tags/alpha/vhdl_behav/PCI.CMD
0,0 → 1,59
## CONFIGURE THE FIRST TARGET DEVICE |
## WAIT ADDRESS DATA |
CWAT 00010CF0 0710FF00 |
## I/O WRITE DWORD ADDRESS NR. DATA |
WRIO 00000850 01 AABBCCDD |
## |
## I/O READ DWORD ADDRESS NR. DATA |
RDIO 00000850 01 AAXXCCDD |
## |
## I/O WRITE DWORD ADDRESS NR. DATA |
WRIO 00000864 04 AABBCCDD EE00AABB CCDDEE00 AABBCCDD |
## |
## I/O READ DWORD ADDRESS NR. DATA |
RDIO 00000864 04 XXBBXXDD EEXXAABB CCDDXX00 XXBBXXDD |
## |
## CONFIGURE THE SECOND TARGET DEVICE |
## WAIT ADDRESS DATA |
CWAT 00020CF0 0710FF00 |
## I/O WRITE DWORD ADDRESS NR. DATA |
WRIO 00001850 01 AABBCCDD |
## |
## I/O READ DWORD ADDRESS NR. DATA |
RDIO 00001850 01 AABBCCDD |
## |
## I/O WRITE DWORD ADDRESS NR. DATA |
WRIO 00001860 03 AABBCCDD EE00AABB CCDDEE00 |
## |
## I/O READ DWORD ADDRESS NR. DATA |
RDIO 00001860 03 AABBCCDD EE00AABB CCDDEE00 |
## |
## MEMORY WRITE DWORD ADDRESS NR. DATA |
WRSW 00005001 01 55AA66BB |
## |
## MEMORY READ DWORD ADDRESS NR. DATA |
RDSW 00005001 01 55AA66BB |
## |
## MEMORY MULTIPLE WRITE ADDRESS NR. DATA |
WRMW 00005000 02 66AA55BB CCDDBBEE |
## |
## MEMORY MULTIPLE READ ADDRESS NR. DATA |
RDMW 00005000 02 XXAAXXBB CCDDXXEE |
## |
## MEMORY MULTIPLE WRITE ADDRESS NR. DATA |
WRMW 00006010 04 66AA55BB CCDDBBEE 33664455 00000001 |
## |
## MEMORY MULTIPLE READ ADDRESS NR. DATA |
RDMW 00006010 04 XXAAXXBB CCDDXXEE 33XX4455 00000001 |
## |
## MEMORY READ LINE ADDRESS NR. DATA |
## RDML 00005000 04 00000000 00000000 00000000 00000000 |
## |
## CONFIG WRITE DWORD ADDRESS NR. DATA |
WCFG 00010CF8 01 20000001 |
## |
## CONFIG READ DWORD ADDRESS NR. DATA |
RCFG 00010CF8 01 20000001 |
## |
## EXIT |
ABRT |
tags/alpha/vhdl_behav/PCI.CMD
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property