-1
\$\begingroup\$

I am currently working on a redesign of one of my older PCBs. On this PCB there is a HEF4046BT used as a PLL. I needed to exchange the CPLD, which is used as a frequency divider between the ports COMP_IN and VCO_OUT. After the change, the PLL could not lock in anymore. The pulse length of the square waves is all over the place on VCO_OUT, as well as on VCO_IN. The code used in the CPLD is the same as beforehand. I tried to translate it from AHDL to VHDL.

old AHDL:

% Signal for SYNC PLL % % Divider by 71 (VCO of the HEF4046 is set to 72 kHz) % sync_cnt.clock = VCO_OUT; sync_cnt.sclr = sync_reset; sync_reset = (sync_cnt.q[6] & sync_cnt.q[2] & sync_cnt.q[1] & sync_cnt.q[0]); PLL_SSIG = !VCO_OUT & sync_cnt.q[0] & (PLL_FAST # (sync_cnt.q[1] & sync_cnt.q[2])); %Pulse shortening% % Divider by 2 for output signal symmetry % syncp_ff.clk = sync_reset; syncp_ff.d = !syncp_ff.q; VCO_IN = !syncp_ff.q; % -> Thus, the reference signal for the PLL is 0.5 kHz % TEST1 = sync_cnt.q[0]; 

new VHDL:

-- ============================================================ -- PLL synchronization -- * C_REG: 7‑bit counter in VCO_OUT domain with synchronous clear -- * SYNCP: divide-by-2, toggled synchronously in the VCO_OUT domain -- * PLL_LOGIC: combinational logic / outputs / next-state generation + reset creation -- Target: 72 kHz --> 0.5 kHz ⇒ overall divide-by 144 ⇒ N = 72 -- Terminal count: 71 (0b1000111), reset pulse exactly 1 VCO_OUT cycle -- ============================================================ -- 1) Counter register: synchronous clear via SYNC_C_RESET or global SRESETN C_REG : process(VCO_OUT) begin if rising_edge(VCO_OUT) then if (SRESETN = '0') then C <= (others => '0') after 2 ns; elsif (SYNC_C_RESET = '1') then C <= (others => '0') after 2 ns; else C <= C_NEXT after 2 ns; end if; end if; end process C_REG; -- 2) SYNCP: toggle synchronously in the VCO_OUT domain (no derived clock) SYNCP_REG : process(VCO_OUT) begin if rising_edge(VCO_OUT) then if (SRESETN = '0') then SYNCP <= '0' after 2 ns; elsif (SYNC_C_RESET = '1') then -- toggle only on the reset pulse SYNCP <= SYNCP_NEXT after 2 ns; end if; end if; end process SYNCP_REG; -- 3) Combinational logic (VCO domain) incl. outputs & next values PLL_LOGIC : process(C, SYNCP, PLL_FAST, VCO_OUT) variable term_hit : std_logic; begin -- Terminal count: C = 71 (0b1000111) => N = 72 => overall divide-by 144 if ( C = "1000111") then term_hit := '1'; else term_hit := '0'; end if; -- Reset pulse of exactly 1 VCO_OUT clock cycle SYNC_C_RESET <= term_hit after 2 ns; -- Next values C_NEXT <= C + 1 after 2 ns; -- increment counter SYNCP_NEXT <= not SYNCP after 2 ns; -- divide-by-2 (toggle on reset pulse) -- Outputs PLL_SSIG <= (not VCO_OUT and C(0) and (PLL_FAST or (C(1) and C(2)))) after 2 ns; VCO_IN <= not SYNCP after 2 ns; TEST1 <= C(0) after 2 ns; TEST2 <= SYNC_C_RESET after 2 ns; end process PLL_LOGIC; 

Some odd things I saw was that I was using the PC2 output for the feedback. In the datasheet: "Recommended operating conditions" is stated that for the phase-locked loop operation the V_DD input is minimum of 5V. The PLL was always powered by 3.3V, now and in the past, but it worked fine.

Right now, the PLL is connected as shown in the picture.

enter image description here

On the reference input, a clean reference signal with 500Hz/1000Hz/1500Hz (tuneable) is used as an input. Between VCO_IN and VCO_OUT is the CPLD as a frequency divider. I also already tried to trim the loop filter consisting of C714 and R710, but I had no success with that.

Maybe someone can provide some support on this topic or provide some ideas.

Old CPLD: Altera MAX II Series EPM7032AETC44-4N - New CPLD: Xilinx XC9572XL-5PC44C

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Why was the question edited to remove the "old" VHDL code? With the question containing only the "new" VHDL code doesn't seem to make sense and might have invalidated the answer already given. \$\endgroup\$ Commented Nov 13 at 12:52

1 Answer 1

1
\$\begingroup\$

You are mixing simulation style VHDL and behavioural VHDL. There should be no need for all the delays to be made explicit : the synthesis tool will output code which has these delays for checking. Your input code, like the AHDL should just be behavioural code.

And because of the way VHDL works, a synchronous process with C <= C+1 will increment on the next active clock edge, and the synthesis tool will generate the correct logic. The update in a synchronous behavioural VHDL process occurs in "delta time" which is very small and non-zero.

So your VHDL code can be a lot more concise .

Actually I expect you have substituted an old-style 4000 series CMOS device for a modern 74HC4046 device - the old 4000 series CMOS runs very slow at 5 volts and is going to be extremely slow at 3.3 volts. It will run OK at 12 to 15 volts.... The 74HC series uses a lower voltage and faster CMOS process so they will operate sensibly at 3.3 volts.

\$\endgroup\$
1
  • \$\begingroup\$ thank you for your comment. First, you are correct, the 2 ns was just for simulation, it should not alter the running CPLD, if I am correct. Is this delta time 0 physically? I thought it was only a simulator-hierarchy thing. If not, how can I change the code to avoid that? \$\endgroup\$ Commented Nov 3 at 12:17

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.