FPGARelated.com
Forums

Efficient implementation of Address Decoding logic

Started by Srikanth BJ June 6, 2006
Hi all,
I am using 6.3.02i Xilinx editor and Modelsim 5.3 simulator.  I am
slightly confused about which type of address decoding logic should be
used when?.
Consider an example where I need to write and read back some 50
registers in FPGA from a host processor.
Consider,
S_Write_Enable <= write_from_cpu or Ce ;
-- /AWE(Write enable) or /CE(chip enable(Active low))
S_Read_Enable  <= read_from_cpu or Ce;
-- /ARE(Read enable) or /CE(chip enable(Active low))
I first tried to use the Case logic,as I needed to program 4 channel
parameters, which could be easily written using Case logic.
Process(S_Write_Enable,Reset)
variable Vl_Offset : std_logic_vector(3 downto 0);
variable Vl_ch_num : std_logic_vector(1 downto 0);
begin
if(Reset = '1') then
-- initializatin
elsif(S_Write_Enable'event  AND S_Write_Enable = '0') then
Vl_Offset    :=  address_input(3 downto 0);
Vl_ch_num :=  conv_integer(address_input(5 downto 4));
case Vl_Offset is
     when ZERO =>
        S_Ch_Control_Reg <= data_bus;
    when ONE =>
        S_Code_Phase_Inc(Vl_ch_num)(31 downto 16) <= data_bus;
    when TWO =>
        S_Code_Phase_Inc(Vl_ch_num)(15 downto 0) <= data_bus;
    when THREE =>
        S_Data_Phase_Inc(Vl_ch_num)(31 downto 16) <= data_bus;
   when FOUR =>
        S_Data_Phase_Inc(Vl_ch_num)(15 downto 0) <= data_bus;
  -
  - Other decoding logics-- 15 * 4 registers(4 Channel Parameters)
  -
   when others =>  null;
end case;
end if;
end process;
While reading the registers also , I used the same decoding logic to
read back the registers.
I dont know why? i got timing errors i.e when I simulated it using
ModelSim 5.3 ., and programmed setup(/CE low to AWE low) as 30ns ,
strobe time(/AWE low time) as 30 ns and hold time(/AWE high to /CE
high) as 30 ns. The registers were in unknown state.
How does the case logic works? does it do priority encoding or normal
encoding??
I changed my case logic to direct if-else structure which worked fine .
But I still dont understand why the same logic didnot work in Case.
Process(S_Write_Enable,Reset)
variable Vl_Offset := std_logic_vector(3 downto 0);
variable Vl_ch_num := std_logic_vector(1 downto 0);
begin
if(Reset = '1') then
-- initializatin
elsif(S_Write_Enable'event  AND S_Write_Enable = '0') then
if(address_input  = "0000001000") then
   S_Code_Aid1(0) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if;
if(address_input  = "0000001001") then
  S_Code_Aid2(0) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if;
if(address_input  = "0000011000") then
 S_Code_Aid1(1) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if;
if(address_input  = "0000011001") then
 S_Code_Aid2(1) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if;
if(address_input  = X"0028") then
 S_Code_Aid1(2) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if
 if(address_input  = X"0029") then
 S_Code_Aid2(2) <= data_bus(C_LFSR_LENGTH-1 downto 0);
end if;
end if;

First, your code (both versions) will create latches, not registers.
You need a clock edge specification:

if rising_edge(clk) then
-- decode/assignment statements go here
end if;

Second, whenever I see a long case or if-then-else tree, I look for
ways to use an array, or array of arrays, to do the decoding for me,
possibly within a loop. Think about transforming slices of the address
into indices for the array, then assign the desired element(s) of the
array from the data bus. For documentation, you can assign
meaningfully-named constants to the appropriate index values, and use
them where you want to individually access the contents by name.

Lastly, VHDL case statement targets are required to be mutually
exclusive, therefore no priority is assigned.  If-then-else statements
do imply priority, but if the synthesis tool is smart enough to figure
out that the conditions are all mutually exclusive, then it will remove
the priority logic anyway.

if address = 1 then
a <= data;
elsif address = 2 then
b <= data;
elsif address = 3 then
c <= data;
end if;

Address clearly cannot be 1 and 2 and 3 at the same time; the
synthesizer should recognize that and remove the priority logic,
creating something that looks more like:

if address = 1 then
a <= data;
end if;
if address = 2 then
b <= data;
end if;
if address = 3 then
c <= data;
end if;

or:

case address is
when 1 => a <= data;
when 2 => b <= data;
when 3 => c <= data;
end case;

Andy Jones

Andy wrote:

> If-then-else statements > do imply priority,
... if (and only if) two or more cases overlap. Otherwise, excellent posting. -- Mike Treseler
Mike,

You're correct, but the synthesizer must _recognize_ whether two or
more cases overlap (i.e. if they are not mutually exclusive). If it
cannot prove they are ME, then it must include (keep) the priority
logic. In other words, priority is assumed for an if-then-else
statement until proven otherwise.

Another way to imply priority (which the synthesizer can remove if it
recognizes ME conditions) is to use an exit statement inside an if
statement in a loop:

for i in reg'range loop
  if addr = i then
    reg(i) <= data;
    exit; -- should not make any difference, except for sim speed
  end if;
end loop;

An example of where this gets messy is if you are pre-decoding the
address a clock cycle early, then using the decoded strobes to enable
reads or writes to a set of registers.  You know the decoded strobes
are ME, but does the synthesizer know it?  It would be nice if we could
define a standare mutex function inside an assertion statement, and the
synthesis tool could recognize/accept that as proof that the strobes
(or any set of conditions) were ME.

This is also an excellent application of retiming, since you could
simply delay (register) the address a cycle, then decode and enable
read/write in one cycle using the (ME) delayed address.  Then let the
synthesis retiming push the pre-decoding back a cycle for you (if
necessary).

Andy


Mike Treseler wrote:
> Andy wrote: > > > If-then-else statements > > do imply priority, > ... if (and only if) two or more cases overlap. > > Otherwise, excellent posting. > > -- Mike Treseler
Andy wrote:

> You're correct, but the synthesizer must _recognize_ whether two or > more cases overlap (i.e. if they are not mutually exclusive). If it > cannot prove they are ME, then it must include (keep) the priority > logic. In other words, priority is assumed for an if-then-else > statement until proven otherwise.
Yes, of course, but if *I* know that cases A, B cannot overlap, it is up to *me* to exclude special coverage of the (A and B) case in my description, if I want to save the gates. I would say: ___________________ ... if A then do_A_thing; endif; if B then do_B_thing; endif; ... ___________________ I see coding an if-then-else for this example as a logical error on *my* part, even though there is no functional difference. -- Mike Treseler
Good point, but just for grins, let's turn this around into a read,
rather than a write:

If a then
  data <= a_thing;
end if;

if b then
  data <= b_thing;
end if;

There is still an implied priority of B over A which, without
explicitly coding an and-or tree, is pretty difficult to code with no
priority implied. In other words, the priority is still implied by the
order, but in your case it can be resolved without knowledge of the
mutual exclusivity of the conditions if the resulting actions are
independent (i.e. do_a and do_b can both be done at the same time).

Another way I have coded it is like a tri-state bus, then told the
synthesis tool to convert tri-states to muxes. It assumes the tri-state
enables are mutually exclusive.

Andy


Mike Treseler wrote:
> Andy wrote: > > > You're correct, but the synthesizer must _recognize_ whether two or > > more cases overlap (i.e. if they are not mutually exclusive). If it > > cannot prove they are ME, then it must include (keep) the priority > > logic. In other words, priority is assumed for an if-then-else > > statement until proven otherwise. > > Yes, of course, but if > *I* know that cases A, B cannot overlap, > it is up to *me* to exclude special coverage > of the (A and B) case in my description, > if I want to save the gates. > > I would say: > ___________________ > ... > if A then > do_A_thing; > endif; > > if B then > do_B_thing; > endif; > ... > ___________________ > I see coding an if-then-else for this > example as a logical error on *my* part, > even though there is no functional difference. > > -- Mike Treseler
Hi Andy,thanks a lot for your response.
Andy wrote:
> First, your code (both versions) will create latches, not registers. > You need a clock edge specification: > > if rising_edge(clk) then > -- decode/assignment statements go here > end if; >
I am using address decoding logic irrespective of the Clock i.e based on that particular address., i am implementing read and write functionalities.If i need a edge, could I use the /ARE low or /AWE low i.e if falling_edge(AWE) -- decoding end if; Please clarify..
Andy wrote:
> Good point, but just for grins, let's turn this around into a read, > rather than a write: > > If a then > data <= a_thing; > end if; > > if b then > data <= b_thing; > end if; > > There is still an implied priority of B over A which, without > explicitly coding an and-or tree, is pretty difficult to code with no > priority implied.
Since a and b are exclusive, I might save a gate by doing a single bit selection, if b_thing is ok as default data: if a then data <= a_thing; else data <= b_thing; end if; -- Mike Treseler
If you use "falling_edge(awe)" then awe will get tied to the clock
input on one or more registers that will hold the signal values that
you assign within that if-then clause.

Storing data on falling edges of strobes will work, but think about
what you are going to do with that data in the latches. The timing can
be very difficult to manage if you need to use that data elsewhere in a
synchronous (clocked) system. Handling asynchronous buses in a
synchronous system is beyond the scope of this conversation. Whole
chapters/books have been written on it. Generally speaking, you usually
end up syncrhonizing the control lines, and using those synchronized
versions to control storage into synchronous registers (i.e. they form
clock enables on registers that are clocked by your system clock). If
your clock is not fast enough to handle the timing of the controls,
then you may need to latch the data with the asynchronous strobe, then
use a synchronized version of the strobe to enable transfer from the
latch into a register on the system clock.

Andy


Srikanth BJ wrote:
> Hi Andy,thanks a lot for your response. > Andy wrote: > > First, your code (both versions) will create latches, not registers. > > You need a clock edge specification: > > > > if rising_edge(clk) then > > -- decode/assignment statements go here > > end if; > > > I am using address decoding logic irrespective of the Clock i.e based > on that particular address., i am implementing read and write > functionalities.If i need a edge, could I use the /ARE low or /AWE low > i.e > if falling_edge(AWE) > -- decoding > end if; > Please clarify..
Andy wrote:
> If you use "falling_edge(awe)" then awe will get tied to the clock > input on one or more registers that will hold the signal values that > you assign within that if-then clause. > > Storing data on falling edges of strobes will work, but think about > what you are going to do with that data in the latches. The timing can > be very difficult to manage if you need to use that data elsewhere in a > synchronous (clocked) system. Handling asynchronous buses in a > synchronous system is beyond the scope of this conversation. Whole > chapters/books have been written on it. Generally speaking, you usually > end up syncrhonizing the control lines, and using those synchronized > versions to control storage into synchronous registers (i.e. they form > clock enables on registers that are clocked by your system clock). If > your clock is not fast enough to handle the timing of the controls, > then you may need to latch the data with the asynchronous strobe, then > use a synchronized version of the strobe to enable transfer from the > latch into a register on the system clock. >
Andy., got to know many things from you. I havenot worked too much on handling asynchronous events., i think its probably very challenging and i guess one should be fully equipped with the basics involved. If you could suggest any book/links which might be very helpful to go further in to the above discussed topics, it would be really appreciated. Thanks in advance, Srikanth