From: Rhydian on 27 Jul 2010 06:26 Hi, I'm trying to debug a Cyclone design which writes values taken from a lookup table to the address inputs of a crosspoint analog switch. The problem is that everything looks OK in the Quartus simulator, but when I test the design on the target hardware it seems to be pulling the wrong values out of the LUT. I have tried enabling SignalTap and probing the output pins during the write operation, SignalTap reports correct operation but the outputs, as measured on a real logic analyser, are wrong. E.g. for CHANNEL=1, eeprom_en='0', path=0 I should get 0,0,0,0,B,A, 3,2, I actually get 0,0,0,0,9,8,3,2 The lookup table is implemented thus: library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity xpswitch is generic(PLL_CLK_FREQ : integer; CHANNEL : integer); port( pll_clk : in std_logic; sys_rst : in std_logic; path_index : in integer range 0 to 7; eeprom_en : in std_logic; go : in std_logic; busy : out std_logic; AX : out std_logic_vector(3 downto 0); AY : out std_logic_vector(2 downto 0); CS : out std_logic; DAT : buffer std_logic; RST : out std_logic; STRB : out std_logic ); end xpswitch; architecture rtl of xpswitch is type t_ax_lut is array(0 to 7) of std_logic_vector(3 downto 0); signal ax_lut : t_ax_lut; signal ay_count : integer range 0 to 7; begin p_lut : process(eeprom_en, path_index) begin case CHANNEL is when 1 => if(eeprom_en = '1') then case path_index is when 0 => ax_lut <= (x"7", x"6", x"8", x"9", x"B", x"A", x"3",x"2"); when 1 => ax_lut <= (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); when 2 => ax_lut <= (x"7", x"6", x"8", x"9", x"4", x"5", x"E",x"F"); when 3 => ax_lut <= (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); when 4 => ax_lut <= (x"7", x"6", x"8", x"9", x"3", x"2", x"B",x"A"); when 5 => ax_lut <= (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); when 6 => ax_lut <= (x"7", x"6", x"8", x"9", x"E", x"F", x"4",x"5"); when 7 => ax_lut <= (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); end case; else case path_index is when 0 => ax_lut <= (x"0", x"0", x"0", x"0", x"B", x"A", x"3",x"2"); when 1 => ax_lut <= (x"0", x"0", x"0", x"0", x"9", x"8", x"6",x"7"); when 2 => ax_lut <= (x"0", x"0", x"0", x"0", x"4", x"5", x"E",x"F"); when 3 => ax_lut <= (x"0", x"0", x"0", x"0", x"6", x"7", x"9",x"8"); when 4 => ax_lut <= (x"0", x"0", x"0", x"0", x"3", x"2", x"B",x"A"); when 5 => ax_lut <= (x"0", x"0", x"0", x"0", x"9", x"8", x"6",x"7"); when 6 => ax_lut <= (x"0", x"0", x"0", x"0", x"E", x"F", x"4",x"5"); when 7 => ax_lut <= (x"0", x"0", x"0", x"0", x"6", x"7", x"9",x"8"); end case; end if; when 2 => if(eeprom_en = '1') then case path_index is when 0 => ax_lut <= (x"3", x"2", x"A", x"B", x"8", x"9", x"7",x"6"); when 1 => ax_lut <= (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); when 2 => ax_lut <= (x"E", x"F", x"5", x"4", x"8", x"9", x"7",x"6"); when 3 => ax_lut <= (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); when 4 => ax_lut <= (x"B", x"A", x"2", x"3", x"8", x"9", x"7",x"6"); when 5 => ax_lut <= (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); when 6 => ax_lut <= (x"4", x"5", x"F", x"E", x"8", x"9", x"7",x"6"); when 7 => ax_lut <= (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); end case; else case path_index is when 0 => ax_lut <= (x"3", x"2", x"A", x"B", x"0", x"0", x"0",x"0"); when 1 => ax_lut <= (x"6", x"7", x"8", x"9", x"0", x"0", x"0",x"0"); when 2 => ax_lut <= (x"E", x"F", x"5", x"4", x"0", x"0", x"0",x"0"); when 3 => ax_lut <= (x"9", x"8", x"7", x"6", x"0", x"0", x"0",x"0"); when 4 => ax_lut <= (x"B", x"A", x"2", x"3", x"0", x"0", x"0",x"0"); when 5 => ax_lut <= (x"6", x"7", x"8", x"9", x"0", x"0", x"0",x"0"); when 6 => ax_lut <= (x"4", x"5", x"F", x"E", x"0", x"0", x"0",x"0"); when 7 => ax_lut <= (x"9", x"8", x"7", x"6", x"0", x"0", x"0",x"0"); end case; end if; when 3 => if(eeprom_en = '1') then case path_index is when 0 => ax_lut <= (x"B", x"A", x"6", x"7", x"4", x"5", x"3",x"2"); when 1 => ax_lut <= (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); when 2 => ax_lut <= (x"8", x"9", x"F", x"E", x"4", x"5", x"3",x"2"); when 3 => ax_lut <= (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); when 4 => ax_lut <= (x"7", x"6", x"A", x"B", x"4", x"5", x"3",x"2"); when 5 => ax_lut <= (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); when 6 => ax_lut <= (x"E", x"F", x"9", x"8", x"4", x"5", x"3",x"2"); when 7 => ax_lut <= (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); end case; else case path_index is when 0 => ax_lut <= (x"B", x"A", x"6", x"7", x"0", x"0", x"0",x"0"); when 1 => ax_lut <= (x"5", x"4", x"3", x"2", x"0", x"0", x"0",x"0"); when 2 => ax_lut <= (x"8", x"9", x"F", x"E", x"0", x"0", x"0",x"0"); when 3 => ax_lut <= (x"2", x"3", x"4", x"5", x"0", x"0", x"0",x"0"); when 4 => ax_lut <= (x"7", x"6", x"A", x"B", x"0", x"0", x"0",x"0"); when 5 => ax_lut <= (x"5", x"4", x"3", x"2", x"0", x"0", x"0",x"0"); when 6 => ax_lut <= (x"E", x"F", x"9", x"8", x"0", x"0", x"0",x"0"); when 7 => ax_lut <= (x"2", x"3", x"4", x"5", x"0", x"0", x"0",x"0"); end case; end if; when others => end case; end process; AX <= ax_lut(ay_count); There are 3 instances of this code in the design, with different switch mappings selected by the CHANNEL parameter. They all show the same problem, 'B','A' is consistently replaced by '9','8'. I can't resolve this discrepancy I'm seeing between what the tools are telling me and the behaviour when running on the target. The internal PLL is being used to generate a 57.6 MHz global clock; Quartus timing analysis shows f_max as about 85 MHz so i don't think it is a timing issue. I have checked the pin assignments by driving the AX outputs with a 4-bit counter which cycles continuously, this works correctly as seen on the simulator and the external logic analyser. Any ideas? I have raised a support case with Altera, no response as yet. TIA R.
From: firefox3107 on 27 Jul 2010 14:26 On Jul 27, 12:26 pm, Rhydian <n...(a)rblack01.plus.com> wrote: > Hi, > > I'm trying to debug a Cyclone design which writes values taken from a > lookup table to the address inputs of a crosspoint analog switch. The > problem is that everything looks OK in the Quartus simulator, but when > I test the design on the target hardware it seems to be pulling the > wrong values out of the LUT. I have tried enabling SignalTap and > probing the output pins during the write operation, SignalTap reports > correct operation but the outputs, as measured on a real logic > analyser, are wrong. > > E.g. for CHANNEL=1, eeprom_en='0', path=0 I should get 0,0,0,0,B,A, > 3,2, I actually get 0,0,0,0,9,8,3,2 > > The lookup table is implemented thus: > > library ieee; > use ieee.std_logic_1164.all; > use ieee.numeric_std.all; > > entity xpswitch is > generic(PLL_CLK_FREQ : integer; > CHANNEL : integer); > port( > pll_clk : in std_logic; > sys_rst : in std_logic; > path_index : in integer range 0 to 7; > eeprom_en : in std_logic; > go : in std_logic; > busy : out std_logic; > AX : out std_logic_vector(3 downto 0); > AY : out std_logic_vector(2 downto 0); > CS : out std_logic; > DAT : buffer std_logic; > RST : out std_logic; > STRB : out std_logic > ); > end xpswitch; > > architecture rtl of xpswitch is > > type t_ax_lut is array(0 to 7) of std_logic_vector(3 downto > 0); > signal ax_lut : t_ax_lut; > signal ay_count : integer range 0 to 7; > > begin > > p_lut : process(eeprom_en, path_index) begin > case CHANNEL is > when 1 => > if(eeprom_en = '1') then > case path_index is > when 0 => ax_lut <= > (x"7", x"6", x"8", x"9", x"B", x"A", x"3",x"2"); > when 1 => ax_lut <= > (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); > when 2 => ax_lut <= > (x"7", x"6", x"8", x"9", x"4", x"5", x"E",x"F"); > when 3 => ax_lut <= > (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); > when 4 => ax_lut <= > (x"7", x"6", x"8", x"9", x"3", x"2", x"B",x"A"); > when 5 => ax_lut <= > (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); > when 6 => ax_lut <= > (x"7", x"6", x"8", x"9", x"E", x"F", x"4",x"5"); > when 7 => ax_lut <= > (x"7", x"6", x"8", x"9", x"0", x"0", x"0",x"0"); > end case; > else > case path_index is > when 0 => ax_lut <= > (x"0", x"0", x"0", x"0", x"B", x"A", x"3",x"2"); > when 1 => ax_lut <= > (x"0", x"0", x"0", x"0", x"9", x"8", x"6",x"7"); > when 2 => ax_lut <= > (x"0", x"0", x"0", x"0", x"4", x"5", x"E",x"F"); > when 3 => ax_lut <= > (x"0", x"0", x"0", x"0", x"6", x"7", x"9",x"8"); > when 4 => ax_lut <= > (x"0", x"0", x"0", x"0", x"3", x"2", x"B",x"A"); > when 5 => ax_lut <= > (x"0", x"0", x"0", x"0", x"9", x"8", x"6",x"7"); > when 6 => ax_lut <= > (x"0", x"0", x"0", x"0", x"E", x"F", x"4",x"5"); > when 7 => ax_lut <= > (x"0", x"0", x"0", x"0", x"6", x"7", x"9",x"8"); > end case; > end if; > when 2 => > if(eeprom_en = '1') then > case path_index is > when 0 => ax_lut <= > (x"3", x"2", x"A", x"B", x"8", x"9", x"7",x"6"); > when 1 => ax_lut <= > (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); > when 2 => ax_lut <= > (x"E", x"F", x"5", x"4", x"8", x"9", x"7",x"6"); > when 3 => ax_lut <= > (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); > when 4 => ax_lut <= > (x"B", x"A", x"2", x"3", x"8", x"9", x"7",x"6"); > when 5 => ax_lut <= > (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); > when 6 => ax_lut <= > (x"4", x"5", x"F", x"E", x"8", x"9", x"7",x"6"); > when 7 => ax_lut <= > (x"0", x"0", x"0", x"0", x"8", x"9", x"7",x"6"); > end case; > else > case path_index is > when 0 => ax_lut <= > (x"3", x"2", x"A", x"B", x"0", x"0", x"0",x"0"); > when 1 => ax_lut <= > (x"6", x"7", x"8", x"9", x"0", x"0", x"0",x"0"); > when 2 => ax_lut <= > (x"E", x"F", x"5", x"4", x"0", x"0", x"0",x"0"); > when 3 => ax_lut <= > (x"9", x"8", x"7", x"6", x"0", x"0", x"0",x"0"); > when 4 => ax_lut <= > (x"B", x"A", x"2", x"3", x"0", x"0", x"0",x"0"); > when 5 => ax_lut <= > (x"6", x"7", x"8", x"9", x"0", x"0", x"0",x"0"); > when 6 => ax_lut <= > (x"4", x"5", x"F", x"E", x"0", x"0", x"0",x"0"); > when 7 => ax_lut <= > (x"9", x"8", x"7", x"6", x"0", x"0", x"0",x"0"); > end case; > end if; > when 3 => > if(eeprom_en = '1') then > case path_index is > when 0 => ax_lut <= > (x"B", x"A", x"6", x"7", x"4", x"5", x"3",x"2"); > when 1 => ax_lut <= > (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); > when 2 => ax_lut <= > (x"8", x"9", x"F", x"E", x"4", x"5", x"3",x"2"); > when 3 => ax_lut <= > (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); > when 4 => ax_lut <= > (x"7", x"6", x"A", x"B", x"4", x"5", x"3",x"2"); > when 5 => ax_lut <= > (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); > when 6 => ax_lut <= > (x"E", x"F", x"9", x"8", x"4", x"5", x"3",x"2"); > when 7 => ax_lut <= > (x"0", x"0", x"0", x"0", x"4", x"5", x"3",x"2"); > end case; > else > case path_index is > when 0 => ax_lut <= > (x"B", x"A", x"6", x"7", x"0", x"0", x"0",x"0"); > when 1 => ax_lut <= > (x"5", x"4", x"3", x"2", x"0", x"0", x"0",x"0"); > when 2 => ax_lut <= > (x"8", x"9", x"F", x"E", x"0", x"0", x"0",x"0"); > when 3 => ax_lut <= > (x"2", x"3", x"4", x"5", x"0", x"0", x"0",x"0"); > when 4 => ax_lut <= > (x"7", x"6", x"A", x"B", x"0", x"0", x"0",x"0"); > when 5 => ax_lut <= > (x"5", x"4", x"3", x"2", x"0", x"0", x"0",x"0"); > when 6 => ax_lut <= > (x"E", x"F", x"9", x"8", x"0", x"0", x"0",x"0"); > when 7 => ax_lut <= > (x"2", x"3", x"4", x"5", x"0", x"0", x"0",x"0"); > end case; > end if; > when others => > end case; > end process; > > AX <= ax_lut(ay_count); > > There are 3 instances of this code in the design, with different > switch mappings selected by the CHANNEL parameter. They all show the > same problem, 'B','A' is consistently replaced by '9','8'. > > I can't resolve this discrepancy I'm seeing between what the tools are > telling me and the behaviour when running on the target. The internal > PLL is being used to generate a 57.6 MHz global clock; Quartus timing > analysis shows f_max as about 85 MHz so i don't think it is a timing > issue. I have checked the pin assignments by driving the AX outputs > with a 4-bit counter which cycles continuously, this works correctly > as seen on the simulator and the external logic analyser. > > Any ideas? I have raised a support case with Altera, no response as > yet. > > TIA > > R. Have you tried the post-layout synthesis? You should register the outputs of a memory. Lg, Bernhard
From: Rhydian on 28 Jul 2010 05:46 OK, following some advice elsewhere re inferred ROMs I have re-worked the lookup table as a nested array: type t_ax_by_ay is array(0 to 7) of std_logic_vector(3 downto 0); type t_ax_by_path is array(0 to 7) of t_ax_by_ay; type t_ax_by_e_en is array(0 to 1) of t_ax_by_path; type t_ax_by_chan is array(0 to 2) of t_ax_by_e_en; constant AX_LUT : t_ax_by_chan := ((((x"0", x"0", x"0", x"0", x"B", x"A", x"3", x"2"), ... ... Then registered the output (the inputs are driven by registers in the parent block of code, one global clock used for everything): p_lut : process(pll_clk) begin if(pll_clk'event and pll_clk = '1') then ax_lut_out <= AX_LUT(CHANNEL)(ee_en)(path_index)(ay_count); end if; end process; Result : Exactly the same! When declaring arrays of constants, are the elements guaranteed to be assigned in the order they are declared? Only I came across this bit of example code http://mysite.ncnetwork.net/reszotzl/sync_rom.vhd where the position of each element within the array is explicitly given. If I don't do this, is the compiler allowed to re-order the elements to minimize the logic? Thanks R.
From: Brian Drummond on 28 Jul 2010 06:19 On Wed, 28 Jul 2010 02:46:40 -0700 (PDT), Rhydian <news(a)rblack01.plus.com> wrote: >OK, following some advice elsewhere re inferred ROMs I have re-worked >the lookup table as a nested array: > >type t_ax_by_ay is array(0 to 7) of std_logic_vector(3 downto 0); >type t_ax_by_path is array(0 to 7) of t_ax_by_ay; > >Result : Exactly the same! > >When declaring arrays of constants, are the elements guaranteed to be >assigned in the order they are declared? Only I came across this bit >of example code > >http://mysite.ncnetwork.net/reszotzl/sync_rom.vhd > >where the position of each element within the array is explicitly >given. If I don't do this, is the compiler allowed to re-order the >elements to minimize the logic? Explicitly giving the position ("named association") can add clarity or readability to a design, but for a large ROM like yours is likely to just add clutter. In its absence the compiler CANNOT re-order elements; they are guaranteed to be in the order given. (There are more complex rules regarding mixing named and positional association in the same array but don't worry about that here!) You did say the design exhibits correct behaviour - is it possible that synthesis has found and eliminated some redundant logic? I would ask if synthesis or mapping has concluded that one bit of your array is redundant, e.g. because it doesn't feed any logic - or because that piece of logic hasn't been implemented yet - or because it contains a design error - or because it hasn't been connected to any I/O pins yet - or any of the sometimes mysterious reasons why synthesis trims logic. This might appear as obscure clues in synthesis or mapping reports. Alternatively, a chain of XORs across the ROM output, tied to a spare output pin, may prevent the optimisation, as an experiment to see what is really going on.. - Brian
From: Rhydian on 28 Jul 2010 07:49
On Jul 28, 11:19 am, Brian Drummond <brian_drumm...(a)btconnect.com> wrote: > On Wed, 28 Jul 2010 02:46:40 -0700 (PDT), Rhydian <n...(a)rblack01.plus.com> > wrote: > > > > >OK, following some advice elsewhere re inferred ROMs I have re-worked > >the lookup table as a nested array: > > >type t_ax_by_ay is array(0 to 7) of std_logic_vector(3 downto 0); > >type t_ax_by_path is array(0 to 7) of t_ax_by_ay; > > >Result : Exactly the same! > > >When declaring arrays of constants, are the elements guaranteed to be > >assigned in the order they are declared? Only I came across this bit > >of example code > > >http://mysite.ncnetwork.net/reszotzl/sync_rom.vhd > > >where the position of each element within the array is explicitly > >given. If I don't do this, is the compiler allowed to re-order the > >elements to minimize the logic? > > Explicitly giving the position ("named association") can add clarity or > readability to a design, but for a large ROM like yours is likely to just add > clutter. > > In its absence the compiler CANNOT re-order elements; they are guaranteed to be > in the order given. OK, thanks, that's what I thought. I could really do with a language reference manual which covers details like this. Meanwhile, I've resolved the problem... [Terrible confession time] The LUT was actually working as designed all along - but buried in the data sheet for the switch is the detail that switch addresses don't map sequentially to analog channels (?!) Note to self : RTFDS properly next time... Thanks to all who replied. |