M
Marty Ryba
Guest
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
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