FPGARelated.com
Forums

Bit order reversed in Xilinx post-translate simulation

Started by Jhlw October 24, 2006
Hi All,

Does anyone have any experience with getting their bit order reversed
in Xilinx post-translate simulation? I am using Xilinx ISE ver 8.2.03i
and ModelSim III XE 6.1e starter edition, and this mysteriously started
happening to me last week when I never had a problem with this before.
I have reinstalled both programs and have reverted to testing only what
Xilinx gives me, and I still get the problem. I generated
user_logic.vhd by following the directions in the
EDK_82_PPC_Tutorial.pdf for the ML403 board; see
http://www.xilinx.com/support/techsup/tutorials/edk_tutorials.htm --
"EDK PowerPC Tutorial using the ML403 Development Kit 8.2"
(EDK_82_PPC_Tutorial.pdf). Then I took it and put it in a separate new
ISE project in order to simulate it. I didn't change any synthesize or
translate options. I made sure that my testbench has sufficient input
setup time and output valid delay according to the timing report (9 ns
each, using a clock period of 20 ns). I have reduced the problem to
just trying to write slv_reg0 and not see the contents backwards
post-translate. I set Bus2IP_BE to F to select all registers,
Bus2IP_Data to my test data of 0x01020304 and Bus2IP_WrCE to 8 in order
to write slv_reg0. This succeeds in behavioral simulation, but in
post-translate simulation, what I see for slv_reg0 is 0x20C04080, which
is just the bits reversed low-order to high-order. I opened a webcase
with Xilinx, but I don't know if they'll be able to reproduce the
problem.

With fresh installs of ISE and ModelSim, no changes to Synthesize or
Translate options, no touching of any ModelSim menu options, and VHDL
straight out of Xilinx's own user_logic from the Create Peripheral
Wizard that always worked before (and works in Behavioral sim), what is
left? What could I have set generally on my computer that could be
causing this? Could there be some Translate option that I idiotically
set and didn't remember that I set?

It must be a problem with how ISE creates models for simulation, or in
the simulator, since I can put my built project in the ML403 board and
write and read the slv_regs correctly following the tutorial, over
RS232. However, my core doesn't seem to be giving the correct output,
so I need to simulate, and therefore I need a reliable simulation
process.

Thanks in advance,
-James

Here's user_logic.vhd as I am simulating it (straight from the Create
Peripheral Wizard, with only the two "library proc_common_v2_00_a"
lines commented-out so that the syntax check will succeed -- this
always worked before):
------------------------------------------------------------------------------
-- user_logic.vhd - entity/architecture pair
------------------------------------------------------------------------------

------------------------------------------------------------------------------
-- Filename:          user_logic.vhd
-- Version:           1.00.a
-- Description:       User logic.
-- Date:              Tue Oct 03 15:53:39 2006 (by Create and Import
Peripheral Wizard)
-- VHDL Standard:     VHDL'93
------------------------------------------------------------------------------
-- Naming Conventions:
--   active low signals:                    "*_n"
--   clock signals:                         "clk", "clk_div#", "clk_#x"
--   reset signals:                         "rst", "rst_n"
--   generics:                              "C_*"
--   user defined types:                    "*_TYPE"
--   state machine next state:              "*_ns"
--   state machine current state:           "*_cs"
--   combinatorial signals:                 "*_com"
--   pipelined or register delay signals:   "*_d#"
--   counter signals:                       "*cnt*"
--   clock enable signals:                  "*_ce"
--   internal version of output port:       "*_i"
--   device pins:                           "*_pin"
--   ports:                                 "- Names begin with
Uppercase"
--   processes:                             "*_PROCESS"
--   component instantiations:              "<ENTITY_>I_<#|FUNC>"
------------------------------------------------------------------------------

-- DO NOT EDIT BELOW THIS LINE --------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

--library proc_common_v2_00_a;
--use proc_common_v2_00_a.proc_common_pkg.all;
-- DO NOT EDIT ABOVE THIS LINE --------------------

--USER libraries added here

------------------------------------------------------------------------------
-- Entity section
------------------------------------------------------------------------------
-- Definition of Generics:
--   C_DWIDTH                     -- User logic data bus width
--   C_NUM_CE                     -- User logic chip enable bus width
--
-- Definition of Ports:
--   Bus2IP_Clk                   -- Bus to IP clock
--   Bus2IP_Reset                 -- Bus to IP reset
--   Bus2IP_Data                  -- Bus to IP data bus for user logic
--   Bus2IP_BE                    -- Bus to IP byte enables for user
logic
--   Bus2IP_RdCE                  -- Bus to IP read chip enable for
user logic
--   Bus2IP_WrCE                  -- Bus to IP write chip enable for
user logic
--   IP2Bus_Data                  -- IP to Bus data bus for user logic
--   IP2Bus_Ack                   -- IP to Bus acknowledgement
--   IP2Bus_Retry                 -- IP to Bus retry response
--   IP2Bus_Error                 -- IP to Bus error response
--   IP2Bus_ToutSup               -- IP to Bus timeout suppress
------------------------------------------------------------------------------

entity user_logic is
  generic
  (
    -- ADD USER GENERICS BELOW THIS LINE ---------------
    --USER generics added here
    -- ADD USER GENERICS ABOVE THIS LINE ---------------

    -- DO NOT EDIT BELOW THIS LINE ---------------------
    -- Bus protocol parameters, do not add to or delete
    C_DWIDTH                       : integer              := 32;
    C_NUM_CE                       : integer              := 4
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );
  port
  (
    -- ADD USER PORTS BELOW THIS LINE ------------------
    --USER ports added here
    -- ADD USER PORTS ABOVE THIS LINE ------------------

    -- DO NOT EDIT BELOW THIS LINE ---------------------
    -- Bus protocol ports, do not add to or delete
    Bus2IP_Clk                     : in  std_logic;
    Bus2IP_Reset                   : in  std_logic;
    Bus2IP_Data                    : in  std_logic_vector(0 to
C_DWIDTH-1);
    Bus2IP_BE                      : in  std_logic_vector(0 to
C_DWIDTH/8-1);
    Bus2IP_RdCE                    : in  std_logic_vector(0 to
C_NUM_CE-1);
    Bus2IP_WrCE                    : in  std_logic_vector(0 to
C_NUM_CE-1);
    IP2Bus_Data                    : out std_logic_vector(0 to
C_DWIDTH-1);
    IP2Bus_Ack                     : out std_logic;
    IP2Bus_Retry                   : out std_logic;
    IP2Bus_Error                   : out std_logic;
    IP2Bus_ToutSup                 : out std_logic
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );
end entity user_logic;

------------------------------------------------------------------------------
-- Architecture section
------------------------------------------------------------------------------

architecture IMP of user_logic is

  --USER signal declarations added here, as needed for user logic

  ------------------------------------------
  -- Signals for user logic slave model s/w accessible register example
  ------------------------------------------
  signal slv_reg0                       : std_logic_vector(0 to
C_DWIDTH-1);
  signal slv_reg1                       : std_logic_vector(0 to
C_DWIDTH-1);
  signal slv_reg2                       : std_logic_vector(0 to
C_DWIDTH-1);
  signal slv_reg3                       : std_logic_vector(0 to
C_DWIDTH-1);
  signal slv_reg_write_select           : std_logic_vector(0 to 3);
  signal slv_reg_read_select            : std_logic_vector(0 to 3);
  signal slv_ip2bus_data                : std_logic_vector(0 to
C_DWIDTH-1);
  signal slv_read_ack                   : std_logic;
  signal slv_write_ack                  : std_logic;

begin

  --USER logic implementation added here

  ------------------------------------------
  -- Example code to read/write user logic slave model s/w accessible
registers
  --
  -- Note:
  -- The example code presented here is to show you one way of
reading/writing
  -- software accessible registers implemented in the user logic slave
model.
  -- Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to
correspond
  -- to one software accessible register by the top level template. For
example,
  -- if you have four 32 bit software accessible registers in the user
logic, you
  -- are basically operating on the following memory mapped registers:
  --
  --    Bus2IP_WrCE or   Memory Mapped
  --       Bus2IP_RdCE   Register
  --            "1000"   C_BASEADDR + 0x0
  --            "0100"   C_BASEADDR + 0x4
  --            "0010"   C_BASEADDR + 0x8
  --            "0001"   C_BASEADDR + 0xC
  --
  ------------------------------------------
  slv_reg_write_select <= Bus2IP_WrCE(0 to 3);
  slv_reg_read_select  <= Bus2IP_RdCE(0 to 3);
  slv_write_ack        <= Bus2IP_WrCE(0) or Bus2IP_WrCE(1) or
Bus2IP_WrCE(2) or Bus2IP_WrCE(3);
  slv_read_ack         <= Bus2IP_RdCE(0) or Bus2IP_RdCE(1) or
Bus2IP_RdCE(2) or Bus2IP_RdCE(3);

  -- implement slave model register(s)
  SLAVE_REG_WRITE_PROC : process( Bus2IP_Clk ) is
  begin

    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      if Bus2IP_Reset = '1' then
        slv_reg0 <= (others => '0');
        slv_reg1 <= (others => '0');
        slv_reg2 <= (others => '0');
        slv_reg3 <= (others => '0');
      else
        case slv_reg_write_select is
          when "1000" =>
            for byte_index in 0 to (C_DWIDTH/8)-1 loop
              if ( Bus2IP_BE(byte_index) = '1' ) then
                slv_reg0(byte_index*8 to byte_index*8+7) <=
Bus2IP_Data(byte_index*8 to byte_index*8+7);
              end if;
            end loop;
          when "0100" =>
            for byte_index in 0 to (C_DWIDTH/8)-1 loop
              if ( Bus2IP_BE(byte_index) = '1' ) then
                slv_reg1(byte_index*8 to byte_index*8+7) <=
Bus2IP_Data(byte_index*8 to byte_index*8+7);
              end if;
            end loop;
          when "0010" =>
            for byte_index in 0 to (C_DWIDTH/8)-1 loop
              if ( Bus2IP_BE(byte_index) = '1' ) then
                slv_reg2(byte_index*8 to byte_index*8+7) <=
Bus2IP_Data(byte_index*8 to byte_index*8+7);
              end if;
            end loop;
          when "0001" =>
            for byte_index in 0 to (C_DWIDTH/8)-1 loop
              if ( Bus2IP_BE(byte_index) = '1' ) then
                slv_reg3(byte_index*8 to byte_index*8+7) <=
Bus2IP_Data(byte_index*8 to byte_index*8+7);
              end if;
            end loop;
          when others => null;
        end case;
      end if;
    end if;

  end process SLAVE_REG_WRITE_PROC;

  -- implement slave model register read mux
  SLAVE_REG_READ_PROC : process( slv_reg_read_select, slv_reg0,
slv_reg1, slv_reg2, slv_reg3 ) is
  begin

    case slv_reg_read_select is
      when "1000" => slv_ip2bus_data <= slv_reg0;
      when "0100" => slv_ip2bus_data <= slv_reg1;
      when "0010" => slv_ip2bus_data <= slv_reg2;
      when "0001" => slv_ip2bus_data <= slv_reg3;
      when others => slv_ip2bus_data <= (others => '0');
    end case;

  end process SLAVE_REG_READ_PROC;

  ------------------------------------------
  -- Example code to drive IP to Bus signals
  ------------------------------------------
  IP2Bus_Data        <= slv_ip2bus_data;

  IP2Bus_Ack         <= slv_write_ack or slv_read_ack;
  IP2Bus_Error       <= '0';
  IP2Bus_Retry       <= '0';
  IP2Bus_ToutSup     <= '0';

end IMP;

Entire thread:
http://groups.google.com/group/comp.arch.fpga/browse_thread/thread/8a8af923fa745e92/6f5f8b0c63a6bf79?hl=en#6f5f8b0c63a6bf79

The solution is in Answer Record # 11635
See
http://www.support.xilinx.com/xlnx/xil_ans_display.jsp?getPagePath=11635

 Solution 1:
 You can work around this issue in two ways:
 1. Change the bus-ordering from (x to y) to (y downto x).
 2. Create a separate testbench for functional and timing simulation.
 This issue will be fixed in 6.1i.

Like fun it's fixed. If it was, it has since been un-fixed. I am using
Xilinx ISE ver 8.2.03i and ModelSim III XE 6.1e starter edition.

I chose approach 1., declaring the slv_regs as "downto" and rewrote the
Xilinx code for writing to the slv_regs as (eg):
slv_reg11((C_DWIDTH-1)-(byte_index*8) downto
(C_DWIDTH-1)-(byte_index*8+7)) <= Bus2IP_Data(byte_index*8 to
byte_index*8+7)

Simulation succeeds now and is readable, which is an important feature
in simulation, and this should work in the board.

One of the things I tried to fix this was reinstalling ISE and
ModelSim. Then I had the "brilliant" idea that since I was only using
Virtex 4, I would only install the files for that device. Then ISE
would always crash when I would try to open a new project,
notwithstanding trying what Answer Record 23387 said ("Fixed in SP1".
Like fun.). According to a Xilinx CAE, it now crashes because not all
device support was installed. I will try reinstalling with everything.

-James


Jhlw wrote:
> Hi All, > > Does anyone have any experience with getting their bit order reversed > in Xilinx post-translate simulation? I am using Xilinx ISE ver 8.2.03i > and ModelSim III XE 6.1e starter edition, and this mysteriously started > happening to me last week when I never had a problem with this before. > I have reinstalled both programs and have reverted to testing only what > Xilinx gives me, and I still get the problem. I generated > user_logic.vhd by following the directions in the > EDK_82_PPC_Tutorial.pdf for the ML403 board; see > http://www.xilinx.com/support/techsup/tutorials/edk_tutorials.htm -- > "EDK PowerPC Tutorial using the ML403 Development Kit 8.2" > (EDK_82_PPC_Tutorial.pdf). Then I took it and put it in a separate new > ISE project in order to simulate it. I didn't change any synthesize or > translate options. I made sure that my testbench has sufficient input > setup time and output valid delay according to the timing report (9 ns > each, using a clock period of 20 ns). I have reduced the problem to > just trying to write slv_reg0 and not see the contents backwards > post-translate. I set Bus2IP_BE to F to select all registers, > Bus2IP_Data to my test data of 0x01020304 and Bus2IP_WrCE to 8 in order > to write slv_reg0. This succeeds in behavioral simulation, but in > post-translate simulation, what I see for slv_reg0 is 0x20C04080, which > is just the bits reversed low-order to high-order. I opened a webcase > with Xilinx, but I don't know if they'll be able to reproduce the > problem. > > With fresh installs of ISE and ModelSim, no changes to Synthesize or > Translate options, no touching of any ModelSim menu options, and VHDL > straight out of Xilinx's own user_logic from the Create Peripheral > Wizard that always worked before (and works in Behavioral sim), what is > left? What could I have set generally on my computer that could be > causing this? Could there be some Translate option that I idiotically > set and didn't remember that I set? > > It must be a problem with how ISE creates models for simulation, or in > the simulator, since I can put my built project in the ML403 board and > write and read the slv_regs correctly following the tutorial, over > RS232. However, my core doesn't seem to be giving the correct output, > so I need to simulate, and therefore I need a reliable simulation > process. > > Thanks in advance, > -James > > Here's user_logic.vhd as I am simulating it (straight from the Create > Peripheral Wizard, with only the two "library proc_common_v2_00_a" > lines commented-out so that the syntax check will succeed -- this > always worked before): > ------------------------------------------------------------------------------ > -- user_logic.vhd - entity/architecture pair > ------------------------------------------------------------------------------ > > ------------------------------------------------------------------------------ > -- Filename: user_logic.vhd > -- Version: 1.00.a > -- Description: User logic. > -- Date: Tue Oct 03 15:53:39 2006 (by Create and Import > Peripheral Wizard) > -- VHDL Standard: VHDL'93 > ------------------------------------------------------------------------------ > -- Naming Conventions: > -- active low signals: "*_n" > -- clock signals: "clk", "clk_div#", "clk_#x" > -- reset signals: "rst", "rst_n" > -- generics: "C_*" > -- user defined types: "*_TYPE" > -- state machine next state: "*_ns" > -- state machine current state: "*_cs" > -- combinatorial signals: "*_com" > -- pipelined or register delay signals: "*_d#" > -- counter signals: "*cnt*" > -- clock enable signals: "*_ce" > -- internal version of output port: "*_i" > -- device pins: "*_pin" > -- ports: "- Names begin with > Uppercase" > -- processes: "*_PROCESS" > -- component instantiations: "<ENTITY_>I_<#|FUNC>" > ------------------------------------------------------------------------------ > > -- DO NOT EDIT BELOW THIS LINE -------------------- > library ieee; > use ieee.std_logic_1164.all; > use ieee.std_logic_arith.all; > use ieee.std_logic_unsigned.all; > > --library proc_common_v2_00_a; > --use proc_common_v2_00_a.proc_common_pkg.all; > -- DO NOT EDIT ABOVE THIS LINE -------------------- > > --USER libraries added here > > ------------------------------------------------------------------------------ > -- Entity section > ------------------------------------------------------------------------------ > -- Definition of Generics: > -- C_DWIDTH -- User logic data bus width > -- C_NUM_CE -- User logic chip enable bus width > -- > -- Definition of Ports: > -- Bus2IP_Clk -- Bus to IP clock > -- Bus2IP_Reset -- Bus to IP reset > -- Bus2IP_Data -- Bus to IP data bus for user logic > -- Bus2IP_BE -- Bus to IP byte enables for user > logic > -- Bus2IP_RdCE -- Bus to IP read chip enable for > user logic > -- Bus2IP_WrCE -- Bus to IP write chip enable for > user logic > -- IP2Bus_Data -- IP to Bus data bus for user logic > -- IP2Bus_Ack -- IP to Bus acknowledgement > -- IP2Bus_Retry -- IP to Bus retry response > -- IP2Bus_Error -- IP to Bus error response > -- IP2Bus_ToutSup -- IP to Bus timeout suppress > ------------------------------------------------------------------------------ > > entity user_logic is > generic > ( > -- ADD USER GENERICS BELOW THIS LINE --------------- > --USER generics added here > -- ADD USER GENERICS ABOVE THIS LINE --------------- > > -- DO NOT EDIT BELOW THIS LINE --------------------- > -- Bus protocol parameters, do not add to or delete > C_DWIDTH : integer := 32; > C_NUM_CE : integer := 4 > -- DO NOT EDIT ABOVE THIS LINE --------------------- > ); > port > ( > -- ADD USER PORTS BELOW THIS LINE ------------------ > --USER ports added here > -- ADD USER PORTS ABOVE THIS LINE ------------------ > > -- DO NOT EDIT BELOW THIS LINE --------------------- > -- Bus protocol ports, do not add to or delete > Bus2IP_Clk : in std_logic; > Bus2IP_Reset : in std_logic; > Bus2IP_Data : in std_logic_vector(0 to > C_DWIDTH-1); > Bus2IP_BE : in std_logic_vector(0 to > C_DWIDTH/8-1); > Bus2IP_RdCE : in std_logic_vector(0 to > C_NUM_CE-1); > Bus2IP_WrCE : in std_logic_vector(0 to > C_NUM_CE-1); > IP2Bus_Data : out std_logic_vector(0 to > C_DWIDTH-1); > IP2Bus_Ack : out std_logic; > IP2Bus_Retry : out std_logic; > IP2Bus_Error : out std_logic; > IP2Bus_ToutSup : out std_logic > -- DO NOT EDIT ABOVE THIS LINE --------------------- > ); > end entity user_logic; > > ------------------------------------------------------------------------------ > -- Architecture section > ------------------------------------------------------------------------------ > > architecture IMP of user_logic is > > --USER signal declarations added here, as needed for user logic > > ------------------------------------------ > -- Signals for user logic slave model s/w accessible register example > ------------------------------------------ > signal slv_reg0 : std_logic_vector(0 to > C_DWIDTH-1); > signal slv_reg1 : std_logic_vector(0 to > C_DWIDTH-1); > signal slv_reg2 : std_logic_vector(0 to > C_DWIDTH-1); > signal slv_reg3 : std_logic_vector(0 to > C_DWIDTH-1); > signal slv_reg_write_select : std_logic_vector(0 to 3); > signal slv_reg_read_select : std_logic_vector(0 to 3); > signal slv_ip2bus_data : std_logic_vector(0 to > C_DWIDTH-1); > signal slv_read_ack : std_logic; > signal slv_write_ack : std_logic; > > begin > > --USER logic implementation added here > > ------------------------------------------ > -- Example code to read/write user logic slave model s/w accessible > registers > -- > -- Note: > -- The example code presented here is to show you one way of > reading/writing > -- software accessible registers implemented in the user logic slave > model. > -- Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to > correspond > -- to one software accessible register by the top level template. For > example, > -- if you have four 32 bit software accessible registers in the user > logic, you > -- are basically operating on the following memory mapped registers: > -- > -- Bus2IP_WrCE or Memory Mapped > -- Bus2IP_RdCE Register > -- "1000" C_BASEADDR + 0x0 > -- "0100" C_BASEADDR + 0x4 > -- "0010" C_BASEADDR + 0x8 > -- "0001" C_BASEADDR + 0xC > -- > ------------------------------------------ > slv_reg_write_select <= Bus2IP_WrCE(0 to 3); > slv_reg_read_select <= Bus2IP_RdCE(0 to 3); > slv_write_ack <= Bus2IP_WrCE(0) or Bus2IP_WrCE(1) or > Bus2IP_WrCE(2) or Bus2IP_WrCE(3); > slv_read_ack <= Bus2IP_RdCE(0) or Bus2IP_RdCE(1) or > Bus2IP_RdCE(2) or Bus2IP_RdCE(3); > > -- implement slave model register(s) > SLAVE_REG_WRITE_PROC : process( Bus2IP_Clk ) is > begin > > if Bus2IP_Clk'event and Bus2IP_Clk = '1' then > if Bus2IP_Reset = '1' then > slv_reg0 <= (others => '0'); > slv_reg1 <= (others => '0'); > slv_reg2 <= (others => '0'); > slv_reg3 <= (others => '0'); > else > case slv_reg_write_select is > when "1000" => > for byte_index in 0 to (C_DWIDTH/8)-1 loop > if ( Bus2IP_BE(byte_index) = '1' ) then > slv_reg0(byte_index*8 to byte_index*8+7) <= > Bus2IP_Data(byte_index*8 to byte_index*8+7); > end if; > end loop; > when "0100" => > for byte_index in 0 to (C_DWIDTH/8)-1 loop > if ( Bus2IP_BE(byte_index) = '1' ) then > slv_reg1(byte_index*8 to byte_index*8+7) <= > Bus2IP_Data(byte_index*8 to byte_index*8+7); > end if; > end loop; > when "0010" => > for byte_index in 0 to (C_DWIDTH/8)-1 loop > if ( Bus2IP_BE(byte_index) = '1' ) then > slv_reg2(byte_index*8 to byte_index*8+7) <= > Bus2IP_Data(byte_index*8 to byte_index*8+7); > end if; > end loop; > when "0001" => > for byte_index in 0 to (C_DWIDTH/8)-1 loop > if ( Bus2IP_BE(byte_index) = '1' ) then > slv_reg3(byte_index*8 to byte_index*8+7) <= > Bus2IP_Data(byte_index*8 to byte_index*8+7); > end if; > end loop; > when others => null; > end case; > end if; > end if; > > end process SLAVE_REG_WRITE_PROC; > > -- implement slave model register read mux > SLAVE_REG_READ_PROC : process( slv_reg_read_select, slv_reg0, > slv_reg1, slv_reg2, slv_reg3 ) is > begin > > case slv_reg_read_select is > when "1000" => slv_ip2bus_data <= slv_reg0; > when "0100" => slv_ip2bus_data <= slv_reg1; > when "0010" => slv_ip2bus_data <= slv_reg2; > when "0001" => slv_ip2bus_data <= slv_reg3; > when others => slv_ip2bus_data <= (others => '0'); > end case; > > end process SLAVE_REG_READ_PROC; > > ------------------------------------------ > -- Example code to drive IP to Bus signals > ------------------------------------------ > IP2Bus_Data <= slv_ip2bus_data; > > IP2Bus_Ack <= slv_write_ack or slv_read_ack; > IP2Bus_Error <= '0'; > IP2Bus_Retry <= '0'; > IP2Bus_ToutSup <= '0'; > > end IMP;