Getting started with Xilinx CPLD's & FPGA's

Topics relating to PALs, CPLDs, FPGAs, and other PLDs used for the support or creation of 65-family processors, both hardware and HDL.
ElEctric_EyE
Posts: 3260
Joined: 02 Mar 2009
Location: OH, USA

Post by ElEctric_EyE »

HiassofT wrote:
Having an FD8CP would help a lot (there seems to be only an FDCP in the xilinx library...
Hiassoft, thanks for posting, but you only see a FD8CP in your library? What device are you using?...

I think I may have made abit of progress INIT'ing a FD8CE....

I was right clicking on the FD8CE, which is an 8-bit D Flip Flop w/ clear enable controlling the ROMBANK A14-A18 (using 5 of 8 bits) in my PWA project, and selected "Object Properties". Then chose "NEW", then "Attribute Name": INIT. It then prompts you for a string by default. And I tried many selections, and many value entries. This is what has not worked in ISE 10.1, schematic entry.

I posted on the Xilinx forums a couple days ago and got no response. sniff, sniff, heh.
Probably means my question is self evident, which got me searching the ISE10.1's help index.

...This morning (11/8/10), I actually read the Help, and searched for "Initialize flip flops and latches".
It describes how to initialize flip flops and latches using a constraints file.
I successfully made one this morning, but can't test it till tomorrow!

(11/9/10) Making a constraints file worked! It gives you the choice to assign 1 or 0 to each bit of any flip flop or latch in the design on powerup.
HiassofT
Posts: 36
Joined: 02 Sep 2010
Location: Salzburg, Austria
Contact:

Post by HiassofT »

ElEctric_EyE wrote:
HiassofT wrote:
Having an FD8CP would help a lot (there seems to be only an FDCP in the xilinx library...
Hiassoft, thanks for posting, but you only see a FD8CP in your library? What device are you using?...
Ah, no. I'm using ISE 12.3 and checked the "CPLD Libraries Guide" (cpld_all_scm.pdf). It lists, amongst others, FDCE, FD4/8/16CE and FDCP, but no FD4/8/16CPs.

I also have to say that I haven't used the schematic entry feature yet, I prefer VHDL :-)

Some 5 or 6 years ago I had a similar problem, I wanted to init registers on a Lattice Mach4A5, using ispLever 4 or so, but couldn't get it to work. I'm not sure what went wrong, the datasheet explicitly mentioned asynchronous reset/preset plus powerup logic in the macrocell description. Maybe I did something wrong, maybe ispLever had some bug (I wouldn't rule that out, I already ran into several ispLever oddities before).

So I added a powerup/reset input to my logic and implemented it like this:

Code: Select all

if (powerup == '0') then
    register <= init_value;
else
    if (rising_edge(clk)) then
        register <= databus;
    end if;
end if;
So the init-logic is contained in the VHDL code and I had no problems synthesizing the code for Lattice Mach4 and Xilinx XC95xx/XC95xxXL CPLDs.

so long,

Hias
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

fachat wrote:
BigDumbDinosaur wrote:

Code: Select all

entity RB65 is
...
A more readable version of his VHDL.
I am pretty sure I tried something like this in a Xilinx CPLD (9572), to define a bidirectional in/out port. But the pins were always pulled low, so I had to remove the read feature and make that port write-only.

Might have been an error in my code though.
Wow, finally I confirmed that this code actually work on the Xilinx XC95108 CPLD :-) I don't know what I did different the other times before, but now I have this code in a CPLD-based device (not a CPU - note it sends data when r/-w is high):

Code: Select all

	datain <= data when (phi2 = '1');
	data <= dataout when (phi2 = '1' and Nsel = '0' and rNw = '1')
					else "ZZZZZZZZ";
with data being the inout port signal, and datain and dataout the internal input (write) and output (read) data busses.

Maybe just the compiler wasn't intelligent enough on my earlier tries to detect this logic or whatever. I did separate the two internal busses (read bus "datain" and write bus "dataout" this time though)

Thanks Ruud!

André
nichtsnutz
Posts: 9
Joined: 03 Feb 2010

Post by nichtsnutz »

Hello all,
Quote:

Code: Select all

 datain <= data when (phi2 = '1'); 
I think it is not desired to write a when condition for the input side.The CPLDs I have worked with (Xilinx/Altera) route the I/O Pin directly into the switch matrix.
Also most of them do not have an enable on the input side buffer in the io cell.I do not want to tristate the input into the switchmatrix.Only the output to the pin.I use a clockenable on the datain signal to selective clock datain into registers.

I just write:

Code: Select all

data <= dataout when ( condition ) else (others => 'Z');
-- Always read the input,it does not hurt!
datain <= data;
EDIT: Also a drawback of the original code is,that it could create a latch under some circumstances.The signal data is transfered into datain when phi2 = '1' but it does not say what will happen to datain when phi2 is not = '1'.The VHDL semantic is that the signal should hold its state so maybe a latch will be synthesised.But I have not try this out.

Greetings,
Vassilis
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

Yes, thanks for your comment. I know about the latching, I just was happy that I actually managed to make it work at all. I'll gradually be moving back to my original solution to find out what the real problem is/was - and in the process I'll be optimizing as well.

I'll keep you posted

André
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

Quote:
I just write:

Code: Select all

data <= dataout when ( condition ) else (others => 'Z');
-- Always read the input,it does not hurt!
datain <= data;
EDIT: Also a drawback of the original code is,that it could create a latch under some circumstances.The signal data is transfered into datain when phi2 = '1' but it does not say what will happen to datain when phi2 is not = '1'.The VHDL semantic is that the signal should hold its state so maybe a latch will be synthesised.But I have not try this out.
Yes, you are absolutely right. ISE gives a warning that it creates a latch for the datain signal ("Found 8-bit latch for signal <datain>") when there is a condition on the input. Removing my original "when (phi2 = '1')" thus saves 8 macrocells.

André
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

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: Select all

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: Select all

	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: Select all

	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: Select all

	-- 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: Select all

--	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é
nichtsnutz
Posts: 9
Joined: 03 Feb 2010

Post by nichtsnutz »

Hello fachat,

first I would like to point out that I am a self educated hobbyist in all this and not a specialist! I have only tried to get an SRAM working an I am also not completely ready with it.There are many possibilities to write a state machine...

For my designs with tristates I try to keep the tristate buffer in only one place in the toplevel entity.If I understand right,in your design this is the signal "data".

This is the only signal I would tristate:

Code: Select all

data   <= dataout when (data_en = '1') else (others => 'Z'); 
datain <= data; 
To control the tristate buffer in the i/o cells I would introduce a data enable signal data_en.This way you do not need to use the tristate 'Z' signal state anyway else in your code.

Code: Select all


  -- This should synthesize a pure combinatorial circuit.

 dataP: process(phi2, Nsel, rNw, dataRegister) 
   begin 
    if (phi2 = '1' and Nsel = '0' and rNw = '1' and dataRegister = '0') then 
      data_en = '1'; 
    else 
      data_en = '0'; 
    end if; 
   end process; 

Now, dataout is an internal signal that need not be tristated.I would just write:

Code: Select all


  -- 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 => dataout <= (others => '0'); 
         end case; 
   end process ReadReg; 

Why would you tristate dataout ? Tristates only exist in the i/o cells on the output side.Old FPGAs had also internal tristates ( BUFT components) but modern components and design only uses tristates at the output buffer.The synthesis tool tries to rewrite internal tristates with multiplexers,so I think something similar would happen here,because there is only one physical tristate buffer and this is occupied by the data signal,so the dataout has no tristate.Maybe the tool tries to put the dataout also on output io cells and uses the input side into the switchmatrix ? I do not know what happens!

So,if I want to read data into the CPLD I set the data_en to '0' to tristate the output buffer and I am reading the data with datain.
If I want to write data out of the CPLD I set data_en to '1' and output the dataout signal.Internal I do split the data and I am keeping the data split into datain and dataout.I try to have only one process to control the data_en depending on conditions I define elsewhere and I only use the tristate signal 'Z' at only one place in the top level design.

I do not know your exact design, a LS245 is just a buffer and not a register.Of course you have to control the oe of the 245 also from the CPLD!?

This is really a topic that is also interesting for me,hope to have some more time to try things out myself on my CPLD/FPGA board.

Greetings,
Vassilis
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

nichtsnutz wrote:
Why would you tristate dataout ?
That is a good question and indeed I do not know why I should - except that it does not work without it. But I only educated myself on that, I'm not doing this as a professional either.

This is what I have now:

Code: Select all

	data <= dataout when (dataout_en = '1') else (others => 'Z'); 
	
	dataP: process(dataout, phi2, Nsel, rNw, dataRegister)
	begin
	 if (phi2 = '1' 
		and Nsel = '0' 
		and rNw = '1' 
		and dataRegister = '0'
		) then
		dataout_en <= '1';
	 else
		dataout_en <= '0';
	 end if;
	end process;

	-- read any of the registers

	ReadReg : process(phi2, muxInt, Nsel, dataRegister, rNw, regsel, byte, page, bank)

		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";
					--dataout <= (others => '0'); 

			end case;
	end process ReadReg;

As you can see this is what you suggested, except for the others clause in the ReadReg process. If I don't tri-state dataout, the CPLD pulls the data bus low when the data register (regsel="0000") is selected.

I'm currently using ISE WebPack 11.1. I'll try it with 12.4 hopefully soon (12.3 failed for me as it did not detect the Linux libusb driver for the parallel programming cable, I hope 12.4 fixes that)

André
nichtsnutz
Posts: 9
Joined: 03 Feb 2010

Post by nichtsnutz »

Hello Andre,

Ok,so there must be something else wrong!? If you tristate the dataout then you get something like :

Code: Select all


   data <= "ZZZZZZZZ" when (dataout_en = '1') else (others => 'Z'); 

This would always tristate data independent of the status of the dataout_en signal.
So I would try to find out why the data is enabled where it should not.There are some more combinations of the regsel signal that are not being used but can enable the data.
Maybe some of these combinations cause the problem ?

Also I have not understood this external register.You wrote from a 245 which is a bidirectional tristate buffer.When is that enabled ?

Getting tristate buffer working reliable with a CPLD/FPGA is a topic I am also very interested in because you need it always when interfacing with other components.

Greetings,
Vassilis
kc5tja
Posts: 1706
Joined: 04 Jan 2003

Post by kc5tja »

This is looking more and more like a bug in the synthesis tool.
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

As a reference, I just updated my web page with the board and full VHDL. See http://www.6502.org/users/andre/csa/ramdisk/index.html for my current CPLD-based RAM-disk, using 30 pin SIMM modules I had laying around. It is based on an older pure TTL design, but moved almost everything into the CPLD.

The "bypass" buffer mentioned above is the 74LS245 that bypasses the CPLD when the data register is accessed, which transfers the data between system bus and DRAM data bus.

André
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

The same problem also occurs with ISE WebPack 12.4 :-(

André
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Post by BigEd »

Hi André
You mention "the same problem" but I'm not sure exactly what that is. Anyhow... I think this is a case where one must be aware of what the implementation can do, and also (maybe) use some standard idioms.

Only external interface signals can be tristate, and they should be tristated with a simple expression. Your

Code: Select all

data <= dataout when (dataout_en = '1') else (others => 'Z'); 
should be fine.

Then, there should be no other Z in your design. And yet you have this code, with a comment:

Code: Select all

-- read any of the registers 
ReadReg : process(phi2, muxInt, Nsel, dataRegister, rNw, regsel, byte, page, bank) 
   begin 
      case regsel is 
         [snip]
         when others => 
            -- this must be high-Z, all-zeros breaks (mangles data) 
            dataout <= "ZZZZZZZZ"; 
            --dataout <= (others => '0'); 
      end case; 
end process ReadReg; 
that all-zeros is broken, which is highly suspicious. Because you have internal Zs, I wouldn't be surprised to see this code synthesise poorly. In this case you should be in don't-care territory - zeros or all ones should work equally well. So what does "mangles data" mean here - what did you see? If you put a specific bit pattern in for this case, when does it appear?

In hardware terms, the first statement - the one-liner - is the tristate driver, and the big ReadReg process is the multiplexer which drives it - if you see the wrong data then you need to check that this mux is described correctly. (Actually it looks like nichtsnutz has already said all this...)

Cheers
Ed
fachat
Posts: 1123
Joined: 05 Jul 2005
Location: near Heidelberg, Germany
Contact:

Post by fachat »

Hi Ed,

I've been tinkering around a bit more with that board.
BigEd wrote:
Hi André
You mention "the same problem" but I'm not sure exactly what that is.
The problem is that the CPLD pulls the CPU data bus low at inappropriate times. The board is selected in a 16 byte address space, and one of the addresses is not served by the CPLD, but by a '245 buffer. So once that single address is selected, the CPLD pulls low the data bus.
(Edit: the version posted here only uses 3 addresses in the CPLD and has all the others but the one for the '245 unused - I checked that only this single address for the '245 is affected by setting this to Z and all others addresses to all-zeros and it's still working)
Quote:
Only external interface signals can be tristate, and they should be tristated with a simple expression. Your

Code: Select all

data <= dataout when (dataout_en = '1') else (others => 'Z'); 
should be fine.

Then, there should be no other Z in your design. And yet you have this code, with a comment:

Code: Select all

-- read any of the registers 
ReadReg : process(phi2, muxInt, Nsel, dataRegister, rNw, regsel, byte, page, bank) 
   begin 
      case regsel is 
         [snip]
         when others => 
            -- this must be high-Z, all-zeros breaks (mangles data) 
            dataout <= "ZZZZZZZZ"; 
            --dataout <= (others => '0'); 
      end case; 
end process ReadReg; 
that all-zeros is broken, which is highly suspicious.
In the meantime I also tried all-ones, and this actually works out ok (similar to the Zs)! So it seems there is some kind of open-collector going on internally. This also justifies my "pulls the databus low" from above.

I tried some patterns in that dataout assignment, and only when a bit is set to zero here, the data bus is pulled low. one and Z are ok.
Quote:
Because you have internal Zs, I wouldn't be surprised to see this code synthesise poorly.
Yes, there is an extra set of cells used when the value is set to Z. But when I set the value to all-ones, I get the same lower number of cells used as with all-zeros, but it works.
Quote:
In this case you should be in don't-care territory - zeros or all ones should work equally well.
That's what I thought and that's why I am asking here, because my observations say otherwise. Might really be something wrong, or I am missing an important point, after all I'm new to CPLDs.
Quote:
So what does "mangles data" mean here - what did you see? If you put a specific bit pattern in for this case, when does it appear?
see above, thanks for the hint!
Quote:
In hardware terms, the first statement - the one-liner - is the tristate driver, and the big ReadReg process is the multiplexer which drives it - if you see the wrong data then you need to check that this mux is described correctly. (Actually it looks like nichtsnutz has already said all this...)
And here I need some help. How would I check that? I tried to generate a schematics in ISE Webpack, but did not see anything suspicious, but I am not sure if I can read that.

Many thanks for your help!
André
Post Reply