![]() |
|
|
|||||||
![]() |
VHDL - Yet another question about array indexing |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
Hi,
I found several posts about array indexing but I am still confused on how to use an one-hot address to index the array. The reason why I want o use a hot-one address is that I have to generate the addresses myself in another part of the project and therefore there is no need for an address encoder/decoder if I use the one-hot address. However, from the posts I read, it seams that I can only index an array with integer and enumerate types. Is this correct? How can I get avoid the use of an address encoder/decoder? In the following code both R_ADR and W_ADR are a 32 bits hot-one address: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity memory is generic( addr_width : integer := 5; data_width : integer := 4); port( Q : out std_logic_vector(data_width - 1 downto 0 ); R_ADR : in std_logic_vector(2**addr_width - 1 downto 0); -- This is a hot-one address W_ADR : in std_logic_vector(2**addr_width - 1 downto 0); -- This is a hot-one address D : in std_logic_vector(data_width - 1 downto 0 ); W : in std_logic; R : in std_logic; ME : in std_logic; CLK : in std_logic ); end memory; architecture synth_mem of memory is type mem_array is array (std_logic_vector range <>) of std_logic_vector(data_width - 1 downto 0 ); signal ram : mem_array(2**addr_width - 1 downto 0); begin process (ME, CLK) begin if ME = '1' then Q <= (others => '1'); elsif CLK'event and CLK = '1' then if R = '1' then Q <= ram(R_ADR); else Q <= (others => '1'); end if; if W = '1' then ram(W_ADR) <= D; end if; end if; end process; end synth_mem; I have the following errors: Entity <memory> compiled. ERROR:HDLParsers:201 - "RTL/memory.vhdl" Line 25. Array index subtype std_logic_vector is not a discrete range. ERROR:HDLParsers:3312 - "RTL/memory.vhdl" Line 26. Undefined symbol 'mem_array'. ERROR:HDLParsers:1209 - "RTL/memory.vhdl" Line 26. mem_array: Undefined symbol (last report in this block) ERROR:HDLParsers:3313 - "/RTL/memory.vhdl" Line 56. Undefined symbol 'ram'. Should it be: rem? ERROR:HDLParsers:1209 - "RTL/memory.vhdl" Line 56. ram: Undefined symbol (last report in this block) How can I use an one-hot address to index my array? Thank you in advance. tudelftrocks@gmail.com |
|
|
|
|
#2 |
|
Posts: n/a
|
> The reason why I
> want o use a hot-one address is that I have to generate the addresses > myself in another part of the project and therefore there is no need > for an address encoder/decoder if I use the one-hot address. There may not be on the write side, but the read side has a massive Mux. This will be ok for small numbers of address lines, but it will get very slow very quickly. > > How can I use an one-hot address to index my array? > > Thank you in advance. Short answer : you cant without a decoder. using a one hot address bus really just gives you a load of registers with each one hot write address line connected to the enable on the appropriate register. Its the read address that then becomes a problem, because the output will be a large one hot mux, which is just a long chain of 2-1 muxes, that you will have to define yourself. Array's in VHDL are always indexed using integers. And so it's easiest to have the addresses as an integer. They also map nicely to internal memory blocks. A Std_logic_vector is NOT an integer, its just an array of bits. I recommend using ieee.numeric_std.all instead of ieee.std_logic_unsigned.all (this package is NOT an ieee standard and different vendors implement it differently, whereas numeric_std IS a standard). if you REALLY wanted to use one hot addressing, you could use something like the following (all code assumed address_width = 5 and data width = 4): process (CLK) function find_value_1hot(a : std_logic_vector; mem : mem_array) return std_logic_vector is variable ret_slv : std_logic_vector(3 downto 0) := (others => '1'); begin for i in a'range loop if a(i) = '1' then ret_slv := mem(i); end if; end loop; return ret_slv; end function find_value_1hot; begin if rising_edge(clk) then if R = '1' then Q <= find_value_1hot(R_ADR, ram); else Q <= (others => '1'); end if; ram_write : for i in ram'range loop if W = '1' and W_ADR(i) = '1' then ram(i) <= D; end if; end loop ram_write; end if; end process; From synthesis and timing analysis, the Q output mux was one large mux chain, as expected. The fmax was 284MHz. I then tried the following (using the numeric_std_package, not std_logic_unsigned): process (CLK) begin if rising_edge(clk) then if R = '1' then Q <= ram( to_integer( unsigned(R_ADR) )); else Q <= (others => '1'); end if; if W = '1' then ram( to_integer(unsigned(w_adr) )) <= D; end if; end if; end process; No surprises, the synthesisor built a ram primitive. And the FMax is now 356Mhz, about 50% faster than the other method. Dont be worried about address decoders. They are very common, used alot and easy to understand. When you start doing things 1-hot it starts getting a little less clear about whats going on. Tricky |
|
|
|
#3 |
|
Posts: n/a
|
On Nov 26, 6:16*pm, Rob Gaddi <rga...@technologyhighland.com> wrote:
> On Wed, 26 Nov 2008 08:00:09 -0800 (PST) > tudelftro...@gmail.com wrote: > > Hi, > > > I found several posts about array indexing but I am still confused on > > how to use an one-hot address to index the array. The reason why I > > want o use a hot-one address is that I have to generate the addresses > > myself in another part of the project and therefore there is no need > > for an address encoder/decoder if I use the one-hot address. However, > > from the posts I read, it seams that I can only index an array with > > integer and enumerate types. Is this correct? How can I get avoid the > > use of an address encoder/decoder? > > > In the following code both R_ADR and W_ADR are a 32 bits hot-one > > address: > > > library ieee; > > use ieee.std_logic_1164.all; > > use ieee.std_logic_unsigned.all; > > > entity memory is > > * *generic( addr_width : integer := 5; > > * * * * * * * *data_width : integer := 4); > > * *port( > > * * * * * *Q : out std_logic_vector(data_width - 1 downto 0 ); > > * * * * * *R_ADR : in *std_logic_vector(2**addr_width - 1 downto > > 0); -- This is a hot-one address > > * * * * * *W_ADR : in *std_logic_vector(2**addr_width - 1 downto > > 0); -- This is a hot-one address > > * * * * * *D : in *std_logic_vector(data_width - 1 downto 0 ); > > * * * * * *W : in *std_logic; > > * * * * * *R : in *std_logic; > > * * * * * *ME : in *std_logic; > > * * * * * *CLK : in *std_logic > > * * * * * *); > > end memory; > > > architecture synth_mem of memory is > > * *type mem_array is array (std_logic_vector range <>) of > > std_logic_vector(data_width - 1 downto 0 ); > > * *signal ram : mem_array(2**addr_width - 1 downto 0); > > > begin > > * *process (ME, CLK) > > * *begin > > * * * * * *if ME = '1' then > > * * * * * * * * * *Q <= (others => '1'); > > * * * * * *elsif CLK'event and CLK = '1' then > > * * * * * * * * * *if R = '1' then > > * * * * * * * * * * * * * *Q <= ram(R_ADR); > > * * * * * * * * * *else > > * * * * * * * * * * * * * *Q <= (others => '1'); > > * * * * * * * * * *end if; > > * * * * * * * * * *if W = '1' then > > * * * * * * * * * * * * * *ram(W_ADR) <= D; > > * * * * * * * * * *end if; > > * * * * * *end if; > > * *end process; > > > end synth_mem; > > > I have the following errors: > > Entity <memory> compiled. > > ERROR:HDLParsers:201 - "RTL/memory.vhdl" Line 25. Array index subtype > > std_logic_vector is not a discrete range. > > ERROR:HDLParsers:3312 - "RTL/memory.vhdl" Line 26. Undefined symbol > > 'mem_array'. > > ERROR:HDLParsers:1209 - "RTL/memory.vhdl" Line 26. mem_array: > > Undefined symbol (last report in this block) > > ERROR:HDLParsers:3313 - "/RTL/memory.vhdl" Line 56. Undefined symbol > > 'ram'. *Should it be: rem? > > ERROR:HDLParsers:1209 - "RTL/memory.vhdl" Line 56. ram: Undefined > > symbol (last report in this block) > > > How can I use an one-hot address to index my array? > > > Thank you in advance. > > The first question is: are you sure this is actually what you want to > do? *The answer to that question depends on what you envision the > actual hardware implementation of this thing looking like (assuming > that this code is meant to one day see hardware). *If you're planning > to try to implement this in a real RAM, then the decoding functionality > is hardwired into the RAM block. *I suppose you CAN use a RAM in which > the address is always a one-hot value, but it means throwing away the > vast majority of it. > > If, on the other hand, your intended result is a register file of > discrete flip-flops with selection logic on the input and output sides > of things, this is a reasonable way to be attacking the problem. *If > that's the case, the decision to declare your address widths to be > powers of two long is something of a strange one, but I digress. *If > that's the implementation you're looking to generate, then look into > using a process with a for loop to AND each register with it's > selector, then OR the results together. *Note that this approach will > rapidly become unwieldly for any serious number of registers. > > -- > Rob Gaddi, Highland Technology > Email address is currently out of order > - Hide quoted text - > > - Show quoted text - Hi, Thank you for your answer. Yes, I am sure that is what I want to do. the memory sizes I need can be quite small, so the option of using a real RAM will take more area then using a "synthesizable" memory. Moroever, because I generate my own addresses I do not need a decoder therefore taking even less area than a real RAM implementation. Your idea of using a for loop seams interesting but I got a bit lost on how to actually code this. Could you please explain a bit more what you mean with AND the register and the selector? From the code I sent you mean: D AND W_ADR? Could you please also elaborate on why you consider the option of using a hot-one address a strange one? From which point of view do you mean? Thanks. Filipa tudelftrocks@gmail.com |
|
|
|
#4 |
|
Posts: n/a
|
<> wrote in message news:7a4c9a77-6479-46d6-acef-... > Hi, > > I found several posts about array indexing but I am still confused on > how to use an one-hot address to index the array. The same way you would use any other vector, by converting it to an integer. address_integer <= to_integer(unsigned(my_one_hot_address_vector)); This doesn't 'cost' anything in terms of logic resources, it is simply applying a specific interpretation (i.e. integer) to something that is defined to be another type (presumalbly your one hot address is std_logic_vector). > However, > from the posts I read, it seams that I can only index an array with > integer and enumerate types. Is this correct? Yes, arrays can only be indexed by discrete types, integers and enumerations being the ones most commonly used. > How can I get avoid the > use of an address encoder/decoder? > The encoder doesn't cost anything in terms of generated logic resources. A collection of arbitrary bits can always be interpreted as an integer number without it generating any logic. It is simply a type conversion operation that is required by the language because from a language perspective it requires proper conversion when things are of different types. This does not imply though that these conversions generate any logic in synthesized code. The fact that your address is 'one hot' is totally irrelevant to using it to address the memory. The fact that you choose to only read/write N addresses out of a possible 2**N doesn't factor into the implementation at all. Kevin Jennings KJ |
|
|
|
#5 |
|
Posts: n/a
|
On Nov 27, 3:47*am, Tricky <Trickyh...@gmail.com> wrote:
> > if you REALLY wanted to use one hot addressing, you could use > something like the following (all code assumed address_width = 5 and > data width = 4): > > process (CLK) > * * function find_value_1hot(a : std_logic_vector; mem : mem_array) > return std_logic_vector is > * * * variable ret_slv : std_logic_vector(3 downto 0) := (others => > '1'); > * * begin > * * * for i in a'range loop > * * * * if a(i) = '1' then > * * * * * ret_slv := mem(i); > * * * * end if; > * * * end loop; > > * * * return ret_slv; > * * end function find_value_1hot; > The problem with converting the one-hot address to an integer-encoded index is that the synthesis tool does not know that only one bit in a () is set, i.e. that a() is mutually exclusive. So prioritization logic is inserted for you. As written the rightmost set bit in a() will determine which element of mem is returned. To avoid this, you have to create an and-or mux, or use a tri-state assignment such that, when converted to a mux, the synthesis tool can assume the tri-state enables are mutually exclusive. And-or priority-less mux: variable temp : std_logic_vector(mem(0)'range) := (others => '0'); .... for i in a'range loop temp := temp or ((mem(i)'range => a(i)) and mem(i)); end loop; return temp; Or for a tri-state approach that will be converted to a mux (must be a concurrent generate statement, so it won't work in a function): ts: for i in a'range generate output <= mem(i) when a(i) = '1' else (others => 'Z'); end generate; For tri-state buses to work (or be converted to priority-less muxes) each conditional assignment must be a separate concurrent statement, not sequential statements. In some ways the t-state version is easier to understand, but it also requires the reader to understand that no real tri-state signals are being used, it will all get converted to mux logic. It also cannot be implemented in a function or procedure. Andy Andy |
|
|
|
#6 |
|
Posts: n/a
|
Andy wrote:
> And-or priority-less mux: > variable temp : std_logic_vector(mem(0)'range) := (others => '0'); > ... > for i in a'range loop > temp := temp or ((mem(i)'range => a(i)) and mem(i)); > end loop; > return temp; So how does this compare with Tricky's second example in synthesis? -- Mike Treseler Mike Treseler |
|
|
|
#7 |
|
Posts: n/a
|
On Dec 2, 3:19 pm, Andy <jonesa...@comcast.net> wrote:
> In some ways the t-state version is easier to understand, but it also > requires the reader to understand that no real tri-state signals are > being used, it will all get converted to mux logic. It also cannot be > implemented in a function or procedure. > For an example of an encoding method that does not prioritize hark back to the overly windy "New keyword 'orif' and its implications" thread in this group from Sep, 2007 http://groups.google.com/group/comp....3697772e2d7f94 From there is an example of 8->3 encoding (shown below) that can be implemented in a function and can be generalized to work with other bit widths as well and will be implemented in minimal logic. Encoded_OneHotInps(0) <= OneHotInps(1) xor OneHotInps(3) xor OneHotInps(5) xor OneHotInps(7); Encoded_OneHotInps(1) <= OneHotInps(2) xor OneHotInps(3) xor OneHotInps(6) xor OneHotInps(7); Encoded_OneHotInps(2) <= OneHotInps(4) xor OneHotInps(5) xor OneHotInps(6) xor OneHotInps(7); Kevin Jennings KJ |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Re: Dial-up Modem Question | w_tom | A+ Certification | 0 | 09-18-2005 09:12 PM |
| "Installing two drives" question - what next? | Jim | A+ Certification | 12 | 08-07-2005 01:19 PM |
| Re: Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good | God | DVD Video | 3 | 04-25-2005 04:19 PM |
| Re: Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good | Filthy Mcnasty | DVD Video | 0 | 04-25-2005 04:29 AM |
| Re: Safe Mode Question (A+ question) | Gordon Findlay | A+ Certification | 0 | 06-16-2004 10:48 AM |