0
votes

I am completely new to programming CPLDs and I want to program a latch + counter in Xilinx ISE Project Navigator using VHDL language. This is how it must work and it MUST be only this way: this kind of device gets 2 clock signals. When one of them gets from HIGH to LOW state, data input bits get transferred to outputs and they get latched. When the 2nd clock gets from LOW to HIGH state, the output bits get incremented by 1. Unfortunately my code doesn't want to work....

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all; 

entity counter8bit is  
  port(CLKDA, CLKLD : in  std_logic;  
        D : in std_logic_vector(7 downto 0); 
        Q : out std_logic_vector(7 downto 0));  
end counter8bit; 
architecture archi of counter8bit is 
  signal tmp: std_logic_vector(7 downto 0); 
  begin  
    process (CLKDA, CLKLD, D) 
      begin 
        if (CLKLD'event and CLKLD='0') then 
          tmp <= D; 
        elsif (CLKDA'event and CLKDA='1') then  
          tmp <= tmp + 1; 
        end if; 

    end process; 
    Q <= tmp; 
end archi; 

Is there any other way around to achieve this?? Please for replies. Any kind of help/suggestions will be strongly appreciated. Many thanks in advance!!

1
It looks like you are trying to create a counter with asynchronous load, but where the load is edge sensitive. This is an unusual requirement, and as you've found out, you can't have a signal clocked by two different clocks. Perhaps you could explain a bit more background on where and how the counter will be used, to see if anyone can come up with an alternative.scary_jeff
You can only describe hardware that exists in the CPLD. Or in other words, there must be a mapable solution. A CPLD has no double clocked flip-flops or latches.Paebbels
Yeah this must work only this way. Too bad it can't accept 2 clock signals since that's why I wanted to especially use it for.... But as long as I have heard, there can be created multiple processes to take 2 separate clock signals. Is that true?? If so, how to do it?? I was wondering about making latch + counter as 2 separate things that would take 2 different clock signals and after that maybe ORing or XORing outputs out of them, as long as the result remains the same that would be great. Would that work??user3161354
You can have as many processes and clock signals as you like, but you can't have edges of two different clocks altering one signal. Again if you might explain the scenario in a bit more breadth, someone may be able to help come up with an alternative idea. This will sound a little rude, but it seems unlikely that you absolutely must do something that the entire rest of the world of FPGA and CPLD design has managed to avoid needing, or has at least worked around in some way.scary_jeff
If this helps in any way this kind of device is supposed to latch and increment EPROM address pins. The CLKLD latches address pins to EPROM and the 2nd clock pin called CLKDA is actually /READ signal (shared with /OE EPROM pin) that once the byte from memory gets read, the next address of EPROM gets incremented automatically. In case you're concerned, there were memories that worked like that and I want to make replica out of it, so this means they had to be implemented somehow but I have no idea how. This means there has to be some other way around to do thatuser3161354

1 Answers

0
votes

Based on the added comments on what the counter is for, I came up with the following idea. Whether it would work in reality is hard to decide, because I would need a proper timing diagram for the EPROM interface. Importantly, there could be clock domain crossing issues depending on what restrictions there are on how the two clock signals are asserted; if there can be a falling edge of CLKLD close to a rising edge of CLKDA, the design may not work reliably.

signal new_start_address : std_logic := '0';
signal start_address : std_logic_vector(D'range) := (others => '0');

...

process (CLKLD, CLKDA)  
begin
  if (CLKDA = '1') then
    new_start_address <= '0';
  elsif (falling_edge(CLKLD)) then
    start_address <= D;
    new_start_address <= '1';
  end if;
end process;

process (CLKDA)  
begin
  if (rising_edge(CLKDA)) then
    if (new_start_address = '1') then
      tmp <= start_address;
    else
      tmp <= tmp + 1;
    end if;
  end if;
end process;

I'm not completely clear on the interface, but it could be that the line tmp <= start_address; should become tmp <= start_address + 1;

You may also need to replace your assignment of Q with:

Q <= start_address when new_start_address = '1' else tmp;

Again, it's hard to know for sure without a timing diagram.