I've been tampering around with the VHDL for the data bus I/O and found something interesting. First I'll show you what works, then below what breaks the system.
What I am trying to do is a DRAM controller, with 4 registers - "data", "byte", "page" and "bank". The latter three are implemented in the CPLD, while the first one is done with a '245 that connects the system data bus with the DRAM data lines. Thus when accessing the data register, the CPLD must not interfere with the data bus itself.
The "usual" signals:
Code:
entity dramctrl is
Port ( data : inout STD_LOGIC_VECTOR (7 downto 0);
regsel : in STD_LOGIC_VECTOR (3 downto 0);
Nphi2 : in STD_LOGIC;
Nsel : in STD_LOGIC;
rNw : in STD_LOGIC;
Nres : in STD_LOGIC;
...
);
end dramctrl;
"regsel" is the lowest 4 address bits (might do some extensions later). "Nphi2" is the inverted phi2 and will internally be inverted again. "Nsel" is the active-low chip select.
Code:
signal dataRegister: std_logic;
...
dataRegister <= not(regsel(0) or regsel(1) or regsel(2) or regsel(3));
A helper signal for the data register address.
Code:
dataP: process(dataout, phi2, Nsel, rNw, dataRegister)
begin
-- removing any one of those if conditions (except phi2='1') break the system
-- removing Nsel='0' holds the complete system (pulls system data bus low all the time)
-- the others mangle the data
if (phi2 = '1'
and Nsel = '0'
and rNw = '1'
and dataRegister = '0'
) then
data <= dataout;
else
data <= "ZZZZZZZZ";
end if;
end process;
This process defines the "data" as "dataout" during phi2, when the chip is selected (Nsel) for a read access (rNw) and it is not the data register. Otherwise the data bus is set to high-Z.
dataout is defined as such:
Code:
-- read any of the registers
ReadReg : process(...)
begin
case regsel is
when "0001" =>
dataout <= byte;
when "0010" =>
dataout <= page;
when "0011" =>
dataout <= bank;
when others =>
-- this must be high-Z, all-zeros breaks (mangles data)
dataout <= "ZZZZZZZZ";
end case;
end process ReadReg;
The code above works fine. What is interesting is what breaks it:
1) setting the dataout not to high-Z but to all-zeros in process ReadReg breaks the system. Data passed to/from(?) DRAM is mangled. It seems the high-Z is not passed on to the "data" bus.
2) combining the two processes by moving the case statement into the dataP process:
Code:
-- dataP: process(...)
-- begin
-- if (phi2 = '1'
-- and Nsel = '0'
-- and rNw = '1'
-- and dataRegister = '0'
-- ) then
-- case regsel is
-- when "0001" =>
-- data <= byte;
-- when "0010" =>
-- data <= page;
-- when "0011" =>
-- data <= bank;
-- when others =>
-- data <= "ZZZZZZZZ";
-- end case;
-- else
-- data <= "ZZZZZZZZ";
-- end if;
-- end process;
This code is actually broken - at least for ISE. it uses 8 macrocells less than the working solution above, but again mangles the data being transferred to/from the DRAM.
What I find disturbing is that ISE does not give any indication or warning about what is going on here.
André