![]() |
|
|
|||||||
![]() |
VHDL - Function has Sim vs. Syth Non-Equivalence |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
The two incarnations of the is_address_word() function (below)
simulate the same but FPGA prototype differently (on an unnamed FPGA synthesis tool). The purpose of this function is for decoding a specific index of a register array in a register-map. So my question for the VHDL gurus out there... should Version 1 of is_addressed_word() FPGA prototype the same as it simulates? SUBTYPE addr_type IS std_logic_vector (ADDR_WIDTH-1 DOWNTO 0); -- Version 1: works differently in sim vs. synth FUNCTION is_addressed_word ( CONSTANT specific_addr : addr_type; CONSTANT index : INTEGER := 0; SIGNAL current_addr : addr_type ) RETURN BOOLEAN IS CONSTANT specific_indexed_addr : procreg_addr_type := std_logic_vector(UNSIGNED( specific_addr) + index * PROCREG_ADDR_INC); BEGIN RETURN ( current_addr(current_addr'left DOWNTO 2) = specific_indexed_addr(current_addr'left DOWNTO 2) ); END FUNCTION is_addressed_word; -- Version 2: works same for sim vs. synth FUNCTION is_addressed_word ( CONSTANT specific_addr : addr_type; CONSTANT index : NATURAL; SIGNAL current_addr : addr_type ) RETURN BOOLEAN IS -- Ignore the last two bits... don't worry about byte addresssing -- stick to 32 bit aligned words. CONSTANT saddr_const : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0) := specific_addr(current_addr'LENGTH-1 DOWNTO 2); CONSTANT indexed_saddr_const : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0) := std_logic_vector(UNSIGNED( saddr_const ) + index); VARIABLE caddr_const : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0) := current_addr(current_addr'LENGTH-1 DOWNTO 2); BEGIN RETURN ( caddr_const = indexed_saddr_const ); END FUNCTION is_addressed_word; Thanks, Jeremy ------------- SpectaReg automates slave memory-map deliverables targeting standard protocols. Learn more at http://www.productive-eda.com. Jeremy Ralph |
|
|
|
|
#2 |
|
Posts: n/a
|
Jeremy Ralph wrote:
> The two incarnations of the is_address_word() function (below) > simulate the same Make sure the full range of all the parameters is tested. Note that "index" covers a 32 bit range in the description. This might not be what you want. > SUBTYPE addr_type IS std_logic_vector (ADDR_WIDTH-1 DOWNTO 0); subtype procreg_addr_type is ? > -- Version 1: works differently in sim vs. synth > > FUNCTION is_addressed_word ( > CONSTANT specific_addr : addr_type; I would leave out CONSTANT as this is the default. > CONSTANT index : INTEGER := 0; Having a default value for index is of little use if it isn't the last parameter.. > SIGNAL current_addr : addr_type I would leave out SIGNAL since only the value is being used anyway, and the default is easier to test. -- Mike Treseler Mike Treseler |
|
|
|
#3 |
|
Posts: n/a
|
Thanks Mike for the useful tips. Any comments on the synthesis
observations? Version 1 caused a lot of grief. After switching to Version 2 everything worked as expected. > Make sure the full range of all the parameters is tested. > Note that "index" covers a 32 bit range in the description. > This might not be what you want. The full range was covered i) in simulation, and ii) from embedded software on the FPGA. This is how the non-equivalence of Version 1 was identified. For "index" I was thinking the synthesis tool would be smart enough to only use as many bits as needed based on the calling context. Different contexts use different ranges of index, thus I did not narrow the the range. > > SUBTYPE addr_type IS std_logic_vector (ADDR_WIDTH-1 DOWNTO 0); > > subtype procreg_addr_type is ? Oops. Typo, I meant to remove all the "procreg_" prefixes to shorten things up... > > FUNCTION is_addressed_word ( > > CONSTANT specific_addr : addr_type; > > I would leave out CONSTANT as this is the default. Guess that would make things more readable. > > CONSTANT index : INTEGER := 0; > > Having a default value for index is of little use > if it isn't the last parameter.. Version 2 (the more mature one) abandoned this for that very reason. > > SIGNAL current_addr : addr_type > > I would leave out SIGNAL since only the > value is being used anyway, and the default > is easier to test. Hmmm, I thought it needed to be SIGNAL since current_addr is a runtime varying signal and not really a constant at build-time. When I get a chance I'll try out your recommendations. Thanks, Jeremy http://www.productive-eda.com Jeremy Ralph |
|
|
|
#4 |
|
Posts: n/a
|
Jeremy Ralph wrote:
> Thanks Mike for the useful tips. Any comments on the synthesis > observations? Version 1 caused a lot of grief. After switching to > Version 2 everything worked as expected. I hesitate to guess without knowing all the subtypes, libraries and actual parameters. I expect there is some functional difference that could be found in simulation. > For "index" I was thinking the synthesis tool would be smart enough to > only use as many bits as needed based on the calling context. > Different contexts use different ranges of index, thus I did not > narrow the the range. True, but knowing the range you are actually using would simplify the problem. > Oops. Typo, I meant to remove all the "procreg_" prefixes to shorten > things up... OK. I'll have another look. >>> FUNCTION is_addressed_word ( >>> CONSTANT specific_addr : addr_type; >> I would leave out CONSTANT as this is the default. > > Guess that would make things more readable. I agree. This a confusion factor for me. CONSTANT only covers the formal parameter, not the actual. >>> SIGNAL current_addr : addr_type >> I would leave out SIGNAL since only the >> value is being used anyway, and the default >> is easier to test. > > Hmmm, I thought it needed to be SIGNAL since current_addr is a runtime > varying signal and not really a constant at build-time. No. The function really doesn't care where the actual value comes from. Unless I am using signal attributes or creating "impure" side effects, the default is fine. > > Thanks, > Jeremy Thanks for the interesting question. -- Mike Treselr Mike Treseler |
|
|
|
#5 |
|
Posts: n/a
|
Mike Treseler wrote:
> OK. I'll have another look. assuming constant ADDR_WIDTH : natural := 16; constant procreg_addr_inc : natural := 2; I get a mismatch between functions for is_addressed_word(x"0001", 1, x"0001") 0,2,3,4, ... work ok. -- Mike Treseler Mike Treseler |
|
|
|
#6 |
|
Posts: n/a
|
Thought I already posted a response to this... guess it didn't go through. > assuming > constant ADDR_WIDTH : natural := 16; > constant procreg_addr_inc : natural := 2; These assumptions would lead to a mismatch since Version 2 assumes ADDR_WIDTH = 32 and ADDR_INC = 4 . Version two ignores the last two bits and increments by index rather than ADDR_INC * index, this change was made in an attempt to get things working and makes things less generic. > I get a mismatch between functions for > is_addressed_word(x"0001", 1, x"0001") I think this is due to the (16,2) vs. (32,4). I was seeing some other mismatches with the 32,4 combo for Version 2 (see prev. posting) and Version 3 (below). In the synthesis logs for version Version 2 were warnings about "Size of operands are different : result is <false>." These seemed to occur when the most significant bit of addr_type was one. Version 3 works as expected and seems synthesizable in XST. ----------------------------------------------------------------- -- Checks if the specified 32 bit word is being addressed... -- This function is not concerned about the byte offset from word -- aligned boundaries. ----------------------------------------------------------------- FUNCTION is_addressed_word ( specific_addr : addr_type; index : NATURAL; current_addr : addr_type ) RETURN BOOLEAN IS -- Ignore the last two bits... don't worry about byte addressing -- stick to 32 bit aligned words. CONSTANT saddr_const : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0) := specific_addr(specific_addr'LENGTH-1 DOWNTO 2); CONSTANT unsigned_index : unsigned(specific_addr'LENGTH-3 DOWNTO 0) := to_unsigned(index,specific_addr'LENGTH-2); CONSTANT indexed_saddr_const : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0) := std_logic_vector(UNSIGNED( saddr_const ) + unsigned_index); VARIABLE caddr : std_logic_vector(specific_addr'LENGTH-3 DOWNTO 0); BEGIN caddr := current_addr(current_addr'LENGTH-1 DOWNTO 2); RETURN ( caddr = indexed_saddr_const ); END FUNCTION is_addressed_word; ------------- -- SpectaReg automates slave memory-map deliverables targeting standard -- protocols. Learn more at http://www.productive-eda.com. Jeremy Ralph |
|
|
|
#7 |
|
Posts: n/a
|
Jeremy Ralph wrote:
>> assuming >> constant ADDR_WIDTH : natural := 16; >> constant procreg_addr_inc : natural := 2; > These assumptions would lead to a mismatch since Version 2 assumes > ADDR_WIDTH = 32 and ADDR_INC = 4 . Version two ignores the last two > bits and increments by index rather than ADDR_INC * index, this change > was made in an attempt to get things working and makes things less > generic. I would work all of the dependencies into the function or use subtypes so that all possible parameter ranges are legal. Otherwise I am better off without a function. I expect that the synthesis bugs are a result of allowing illegal parameters. I would work on debugging my best version rather than analyze the differences. Good luck. -- Mike Treseler Mike Treseler |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| equivalent function for itoa in Linux gcc compiler | suse | Software | 0 | 03-06-2009 05:30 AM |
| How to assign a returns value of a javascript function to a hiddenfield in a webpart | Chander | Software | 0 | 12-20-2007 09:14 AM |
| How to call C# function in javascript | visj4u | Software | 2 | 04-23-2007 03:24 PM |
| MS Access not recognising Date() function | tessythampan | Software | 0 | 08-28-2006 11:51 AM |
| I lost the "Help and Support" function from my start menu | Keith | A+ Certification | 1 | 03-14-2005 03:05 PM |