Modelsim vs. Synplify Pro frustrations

M

Marty Ryba

I've had some curious symptoms with a big pile of code (not all mine) that I'd appreciate the community's inputs regarding (if it's frustrated me, it's probably frustrated the rest of you at some time).

I'm having problems getting consistent behavior in a Modelsim test bench (it did work at some time, but now it seems to generally fail). When I fix it to work in the test bench, then it bombs in synthesis (Modelsim 5.8d, Synplify Pro 8.8.x).

The signal of interest is a tri-state buffer that holds outbound data just prior to it getting copied into the (tri-state) PCI bus. There was some code to handle alternating between DMA and PIO, but I'm mostly focused on PIO (I'm actually trying to rip out the unused DMA logic without breaking things). So, there's a number of distributed units that may need to drive a readback of various registers in a register map. The vendor's code has structures like the following:

signal pci_data_out_p : std_logic_vector(63 downto 0);

read_ver_E_core_id_reg : process(pci_lclk_i, main_rst_h)
begin
if (rising_edge(pci_lclk_i) and (main_rst_h = '0') and
(laddr_latched(7 downto 0) = COREID_OFFSET) and (LRD1WR0 = DIR_READ) and
(reg_access_req = '1')) then
pci_data_out_p(7 downto 0)<="00000010"; -- minor revision -002
pci_data_out_p(23 downto 8)<="0010110011100000"; -- major revision - (G11488 , 0x2CE0 - XC2V4000)
pci_data_out_p(63 downto 24)<=(others => '0'); -- must do this or the compiler will complain
else
pci_data_out_p <= (others => 'Z'); -- default: drive bus to high Z.
end if;
end process;

As you can see, some signals are implied synchronous are in the one test and not in the sensitivity list (apparently this is preferred syntax in the latest VHDL-200x proposals); Synplify generally complains about missing signals in the sensitivity list, but seems to have "done the right thing" in synthesizing the chip (the vendor generally uses ISE 9.x, but wrote code to support both). However, after working for a while, this seems to no longer work in Modelsim (pci_data_out_p transitions back to high-Z on the falling edge, and thus the copy to the actual PCI_DATA pins returns high-Z in the test bench). I didn't quite like this construct anyway given the missing pieces of the sensitivity list. So, I'm trying something like this:

-- **************************************************************************
-- Group reading of registers together to get Modelsim and Synplify to
-- to play nice together
-- **************************************************************************
read_ver_E_reg : process(pci_lclk_i)
begin
if rising_edge(pci_lclk_i) then
if (main_rst_h = '0') and (LRD1WR0 = DIR_READ) and (reg_access_req = '1') then
case laddr_latched(7 downto 0) is
when DAC_CTRL_OFFSET =>
pci_data_out_p(7 downto 0) <= dac_ctrl_regval;
pci_data_out_p(63 downto 8) <= (others => '0');
when SYNCCTRL_OFFSET =>
pci_data_out_p(10 downto 0) <= sync_regval_rb;
pci_data_out_p(63 downto 11)<= (others => '0');
when COREID_OFFSET =>
pci_data_out_p(7 downto 0) <= X"02"; -- minor revision - 02
pci_data_out_p(23 downto 8) <= X"0100"; -- major revision - 100; T10_C1_image00_xx
pci_data_out_p(63 downto 24)<=(others => '0');
when others => pci_data_out_p(63 downto 0) <= (others => 'Z');
end case;
else
pci_data_out_p <= (others => 'Z'); -- do I need this?
end if;
else
pci_data_out_p <= (others => 'Z'); -- and this too? This seems to break Modelsim
end if;
end process;

The challenge has been to get the bits right so that Modelsim doesn't prematurely transition the signal back to high-Z before it can be latched over to the output, and get it to synthesize without tri-state mismatches or dreaded "Found combinatorial loop" warnings (they sound too dire to ignore). Any hints for a relative newbie on the "right way" to do it? Oh by the way, several modules below this code contain similar logic for "their" registers.

Thanks in advance for your sage advice,
Marty
martin (dot) ryba (at) verizon (dot) net
 
K

Kim Enkovaara

Marty said:
(it did work at some time, but now it seems to generally fail). When I
fix it to work in the test bench, then it bombs in synthesis (Modelsim
5.8d, Synplify Pro 8.8.x).

Just a hint on the tools. Please use something else than Synplify 8.8,
it was a horrible release with many synthesis bugs (might have been
fixed in the patches). But there are newer versions available, even
8.9 beta was more stable than 8.8.

--Kim
 
T

Tricky

However, after working for a while, this seems to no longer work in Modelsim (pci_data_out_p transitions back to high-Z on the falling edge, and thus the copy to the actual PCI_DATA >pins returns high-Z in the test bench). I didn't quite like this construct anyway given the missing pieces of the sensitivity list. So, I'm trying something like this:

Modelsim appears to be working fine. The sensitivity list only applies
in simulation. The "problem" appears to be the else clause on the same
level as the clock, and the lack of the other signals in the
sensitivity list.
read_ver_E_core_id_reg : process(pci_lclk_i, main_rst_h)
begin
if (rising_edge(pci_lclk_i) and (main_rst_h = '0') and
(laddr_latched(7 downto 0) = COREID_OFFSET) and (LRD1WR0 = DIR_READ) and
(reg_access_req = '1')) then
pci_data_out_p(7 downto 0)<="00000010"; -- minor revision -002
pci_data_out_p(23 downto 8)<="0010110011100000"; -- major revision - (G11488 , 0x2CE0 - XC2V4000)
pci_data_out_p(63 downto 24)<=(others => '0'); -- must do this or the compiler will complain
else
pci_data_out_p <= (others => 'Z'); -- default: drive bus to high Z.
end if;
end process;

The sensitivity list tells the simulator (modelsim) when to trigger a
process. This means the process will evaluate every time the clock
changes, and in the case of the falling edge, the only possible
outcome is to set the "pci_data_out_p" to all 'Z'. As for the
synthesis, Im not surprised this is falling down either, as the
template you have given (with the else on the same level as the clock)
isnt really a standard template, so its trying to make some horrible
logic out of the clock and the other various signals that are not (but
should be) in the sensitivity list, because the synthesizer doesnt
care about sensitivity lists. Otherwise it's trying to do what the
simulator does and set the tri-state to high impedance on every
falling edge (good luck with that).

Id try removing the else clause that is on the same level as the
clock, and keep the ONLY if path to be the rising_edge(pci_lclk_i).
so, its almost what you've got in the second instance:

read_ver_E_reg : process(pci_lclk_i)
begin
if rising_edge(pci_lclk_i) then
if (main_rst_h = '0') and (LRD1WR0 = DIR_READ) and (reg_access_req
= '1') then
case laddr_latched(7 downto 0) is
when DAC_CTRL_OFFSET =>
pci_data_out_p(7 downto 0) <= dac_ctrl_regval;
pci_data_out_p(63 downto 8) <= (others => '0');
when SYNCCTRL_OFFSET =>
pci_data_out_p(10 downto 0) <= sync_regval_rb;
pci_data_out_p(63 downto 11)<= (others => '0');
when COREID_OFFSET =>
pci_data_out_p(7 downto 0) <= X"02"; -- minor revision - 02
pci_data_out_p(23 downto 8) <= X"0100"; -- major revision -
100; T10_C1_image00_xx
pci_data_out_p(63 downto 24)<=(others => '0');
when others => pci_data_out_p(63 downto 0) <= (others => 'Z');
end case;
else
pci_data_out_p <= (others => 'Z'); -- do I need this?
end if;
end if;
end process;
 
M

Marty Ryba

Tricky said:
Modelsim appears to be working fine. The sensitivity list only applies
in simulation. The "problem" appears to be the else clause on the same
level as the clock, and the lack of the other signals in the
sensitivity list.
read_ver_E_reg : process(pci_lclk_i)
begin
if rising_edge(pci_lclk_i) then
if (main_rst_h = '0') and (LRD1WR0 = DIR_READ) and (reg_access_req
= '1') then
case laddr_latched(7 downto 0) is
when DAC_CTRL_OFFSET =>
pci_data_out_p(7 downto 0) <= dac_ctrl_regval;
pci_data_out_p(63 downto 8) <= (others => '0');
when SYNCCTRL_OFFSET =>
pci_data_out_p(10 downto 0) <= sync_regval_rb;
pci_data_out_p(63 downto 11)<= (others => '0');
when COREID_OFFSET =>
pci_data_out_p(7 downto 0) <= X"02"; -- minor revision - 02
pci_data_out_p(23 downto 8) <= X"0100"; -- major revision -
100; T10_C1_image00_xx
pci_data_out_p(63 downto 24)<=(others => '0');
when others => pci_data_out_p(63 downto 0) <= (others => 'Z');
end case;
else
pci_data_out_p <= (others => 'Z'); -- do I need this?
end if;
end if;
end process;

An update: yes, finally removing that last else clause and getting rid of
some other junk left over from when I collapsed three of the vendor
structures into that case statement seems to work. Now I have to debate the
merits of fixing the vendor's code in some of the sub-modules to have the
same structure. Right now, the register calls from my code work in both
Modelsim and Synplify; the calls to the vendor's modules break in simulation
but work fine in the chip. For the life of me I can't figure out what
possible switch/library setting changed in my Modelsim setup to cause the
behavior to change between runs. For even when I used the configuration
repository to roll back to the precise same code base as I had used earlier,
it no longer worked and I hadn't (to my knowledge) messed with my Modelsim
setup. Sigh. Maybe systems engineering is easier after all.

-Marty
 
M

Mike Treseler

Marty said:
An update: yes, finally removing that last else clause and getting rid of
some other junk left over from when I collapsed three of the vendor
structures into that case statement seems to work.

'Seems to work' as in
vcom compiled and vsim elaborated without error?
Or as in the simulation output waves and assertions are correct?
Now I have to debate the
merits of fixing the vendor's code in some of the sub-modules to have the
same structure.

There's only one side to that debate.
Right now, the register calls
instances?
from my code work in both
Modelsim and Synplify;
the calls to the vendor's modules break in simulation
but work fine in the chip.

The vendor code is broken.
Hope you didn't pay much for it.
Unless he is willing to fix it for you,
it's your code now, and your job to debug it.
Check it in to version control and start hacking.
For the life of me I can't figure out what
possible switch/library setting changed in my Modelsim setup to cause the
behavior to change between runs. For even when I used the configuration
repository to roll back to the precise same code base as I had used earlier,
it no longer worked and I hadn't (to my knowledge) messed with my Modelsim
setup. Sigh.

Learn the vcom and vsim command line options.
Write a .do file or a makefile so
that your compiles and sims are repeatable.

Maybe systems engineering is easier after all.

If this were easy, the boss would have done it already
and you would be working on something less interesting,
like a power supply.

Good luck.

-- Mike Treseler
 
K

Kim Enkovaara

Marty said:
structures into that case statement seems to work. Now I have to debate the
merits of fixing the vendor's code in some of the sub-modules to have the
same structure. Right now, the register calls from my code work in both
Modelsim and Synplify; the calls to the vendor's modules break in simulation
but work fine in the chip. For the life of me I can't figure out what
possible switch/library setting changed in my Modelsim setup to cause the
behavior to change between runs. For even when I used the configuration

With bad code anything can happen. Possibly for example some event order
changed and after that the code is not working correctly, because it is
incorrectly done. The code might work on chip now, but it also might
break in future tool versions, or after small change to the code.

Usually the problem is that the code works in simulator, but not on the
chip tough :) Simulator bugs in RTL simulations are very rare, I have
seen and debugged few ones but they have usually been in beta test
versions of the simulators or after some really major changes in
the tool. With SDF timing simulations the bugs are more common with
huge designs.
repository to roll back to the precise same code base as I had used earlier,
it no longer worked and I hadn't (to my knowledge) messed with my Modelsim
setup. Sigh. Maybe systems engineering is easier after all.

Systems engineering is just as hard if the documents are written by
incompetent people, and the simulation models are written by breaking
all the rules and by tweaking it to work with certain version of the
compiler on a certain platform.

--Kim
 
A

Andy

With bad code anything can happen. Possibly for example some event order
changed and after that the code is not working correctly, because it is
incorrectly done. The code might work on chip now, but it also might
break in future tool versions, or after small change to the code.

Usually the problem is that the code works in simulator, but not on the
chip tough :) Simulator bugs in RTL simulations are very rare, I have
seen and debugged few ones but they have usually been in beta test
versions of the simulators or after some really major changes in
the tool. With SDF timing simulations the bugs are more common with
huge designs.


Systems engineering is just as hard if the documents are written by
incompetent people, and the simulation models are written by breaking
all the rules and by tweaking it to work with certain version of the
compiler on a certain platform.

--Kim

Since most FPGA architectures don't actually implement internal tri-
states, it may be that the early tri-state is optimized out in
converting the tri-state bus into a mux structure (if nobody else is
driving the bus early). If it is implemented as a real tri-state, the
part may still appear to work since the tri-state will take a while to
float off of the original value.

Either way, not a good situation in HW, since changing something else
(someone else driving the bus early), or part-part timing variations
could render it inoperable.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top