1

I am converting an old AHDL code to VHDL, and I need to create 5 arrays of resisters using a generate statement. I've never used generate before, and after trying for a couple of hours I still can't find an answer for my problem. My initial approach was to use a 18 bit input array, and a 18 bit output array, but I know that that's not the way to do it.

This is the code I have right now:

entity setup_comp_reg is

    generic(
    NUM_ID: integer := 18
   );

  port ( 
  clk:      in std_logic;  
  D:            in std_logic_vector(17 downto 0);   
  clrn:     in std_logic;   
  ena:      in std_logic;   

  Q:            out std_logic_vector(17 downto 0)

  );
end setup_comp_reg;

architecture rtl of setup_comp_reg is

begin

DFFE: process (clk, clrn, ena) -- 18 times, using generate 
begin

    if (clrn = '0') then
        Q<= (others => '0');

    elsif (rising_edge(clk)) then

        if (ena = '1') then
            Q<= D;
        end if;

    end if;
end process;


end rtl;

So, I already have the DFFE, but how to use generate to create 5 arrays with 18 bits each?

The AHDL code is pretty self explanatory, it might help too:

for i in 17 to 0 generate                       
            rg_bit_time[i].(d, clk, clrn, ena)      = (iDATA[i], clk, not reg_reset, adBT&iWR);
            rg_sample_time[i].(d, clk, clrn, ena)   = (iDATA[i], clk, not reg_reset, adSP&iWR);
            rg_low_sync[i].(d, clk, clrn, ena)      = (iDATA[i], clk, not reg_reset, adLS&iWR);
            rg_hi_sync[i].(d, clk, clrn, ena)       = (iDATA[i], clk, not reg_reset, adHS&iWR);
    end generate;

Thank you.

9
  • 2
    You already have generated 18 DFFEs, without Generate, because D and Q are 18 bits wide. So what are you really asking? If you want 18 registers each with 18 bits, you first have to decide how you want to interconnect them. Commented Jan 31, 2018 at 14:33
  • I need to create the DFFEs without 18 bits input and outputs. The old AHDL code was pretty straight forward, I need to do the same as this (below) because I'll have 5 arrays of 18 bit resgisters. Here's the AHDL: for i in 17 to 0 generate rg_bit_time[i].(d, clk, clrn, ena) = (iDATA[i], clk, not reg_reset, enable[i]); end generate; Commented Jan 31, 2018 at 14:37
  • So you want 18 one bit registers. You still need to define how they are interconnected. If you just need 18 individual inputs and 18 individual output your code above is fine, just pick bits off the std_logic_vector in the module above this one. std_logic_vector is just an abstraction over individual bits; that's what you get in a higher level language. Commented Jan 31, 2018 at 14:42
  • 2
    What 5 arrays? Oh you edited the comment. This is like jelly. I can't read your mind, please update the question with what you want to do and the AHDL equivalent. If you need 5 instances of setup_comp_reg, it doesn't matter if you instantiate it 5 times individually or in one for..generate statement. Commented Jan 31, 2018 at 14:54
  • 1
    Your confusion appears to stem from the AHDL priimitive for DFFE which is described with a function prototype: FUNCTION DFFE (d, clk, clrn, prn, ena) RETURNS (q) ;. The only place to hang the name for it's q output is in the assignment (which associates what would be formals with actuals in VHDL). See the Altera Hardware Description Language (AHDL) Language Reference Manual. The names would be associated with q outputs. Commented Jan 31, 2018 at 18:38

1 Answer 1

2

The AHDL generate statement represents four flip flops for each iteration of i.

AHDL generate statement:

for i in 17 to 0 generate                       
            rg_bit_time[i].(d, clk, clrn, ena)      = (iDATA[i], clk, not reg_reset, adBT&iWR);
            rg_sample_time[i].(d, clk, clrn, ena)   = (iDATA[i], clk, not reg_reset, adSP&iWR);
            rg_low_sync[i].(d, clk, clrn, ena)      = (iDATA[i], clk, not reg_reset, adLS&iWR);
            rg_hi_sync[i].(d, clk, clrn, ena)       = (iDATA[i], clk, not reg_reset, adHS&iWR);
    end generate; 

AHDL uses a function prototype to represent primitives (here, DFFE). The return value would be the q output (and isn't mentioned in the AHDL generate statement). There are four assignments to names with function prototype associations. That represents four arrays of 18 flip flops.

The function prototype for the DFFE register is shown in the Altera Hardware Description Language (AHDL) Language Reference Manual, Section 3, Primitives, Flip Flop and latch Primitives, Table 3-9. MAX+PLUS II Flipflops & Latches:

Table 3.9

Where the return value would be associated with the name (e.g. rg_bit_time[i]) in assignment statements in the AHDL generate statement.

In VHDL we'd do that by associating actuals with formals of a DFFE entity that would include the output.

A behavioral representation with ports for all the outputs and inputs would look something like:

library ieee;                   -- ADDED context clause
use ieee.std_logic_1164.all;

entity setup_comp_reg is

    generic (
        NUM_ID: integer := 18
    );

    port ( 
        clk:            in  std_logic;  
        D:              in  std_logic_vector(NUM_ID - 1 downto 0);   
        clrn:           in  std_logic;   
        ena:            in  std_logic;   
        -- Q:        out std_logic_vector(17 downto 0)
        WR:             in  std_logic;  -- ADDED
        adBT:           in  std_logic;  -- ADDED
        adSP:           in  std_logic;  -- ADDED
        adLS:           in  std_logic;  -- ADDED
        adHS:           in  std_logic;  -- ADDED
        rg_bit_time:    out std_logic_vector(NUM_ID - 1 downto 0); -- ADDED
        rg_sample_time: out std_logic_vector(NUM_ID - 1 downto 0); -- ADDED
        rg_low_sync:    out std_logic_vector(NUM_ID - 1 downto 0); -- ADDED
        rg_hi_sync:     out std_logic_vector(NUM_ID - 1 downto 0)  -- ADDED
    );
end entity setup_comp_reg;

architecture rtl of setup_comp_reg is
    -- For no -2008 dependency, ADD these:
    signal adBTWR:      std_logic;
    signal adSPWR:      std_logic;
    signal adLSWR:      std_logic;
    signal adHSWR:      std_logic;
begin
-- Write ENABLE conditions:

    adBTWR <= adBT and WR;
    adSPWR <= adSP and WR;
    adLSWR <= adLS and WR;
    adHSWR <= adHS and WR;

SETUP_REGS:
    for i in NUM_ID - 1 downto 0 generate
BIT_TIME:
        process (clk, clrn)  -- enables not needed in sensitivity list
        begin
            if clrn = '0' then
                rg_bit_time(i)  <= '0';
            elsif rising_edge (clk) then
                if adBTWR = '1' then
                    rg_bit_time(i) <= D(i);
                end if;
            end if;
        end process;
SAMPLE_TIME:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_sample_time(i)  <= '0';
            elsif rising_edge (clk) then
                if adSPWR = '1' then
                    rg_sample_time(i) <= D(i);
                end if;
            end if;
        end process;
LOW_SYNC:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_low_sync(i)  <= '0';
            elsif rising_edge (clk) then
                if adLSWR = '1' then
                    rg_low_sync(i) <= D(i);
                end if;
            end if;
        end process;
HI_SYNC:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_hi_sync(i)  <= '0';
            elsif rising_edge (clk) then
                if adHSWR = '1' then
                    rg_hi_sync(i) <= D(i);
                end if;
            end if;
        end process;
    end generate;

end architecture rtl;

You could associate individual flip flops from an entity (DFFE) but there's no need in a VHDL Register Transfer Logic (RTL) representation. In AHDL you'd have no choice, a named element would be a flip flop associated more than likely with a pin of a device.

You could also streamline the above description, it's written this way to show providence with the AHDL generate statement (without individual flip flops).

Using a generate statement with instantiated flip flops would elaborate to i number of nested block statements for the instantiation, the outer for the port map, the inner containing one or more processes implementing the flip flop for each of the four names. The above does that without instantiation (saving one block statement nesting level).

A description using loop statements instead of the generate statement would eliminate all the processes for individual flip flops and could be collapsed further by using assignment with a target that's an array object:

architecture rtl1 of setup_comp_reg is
    -- For no -2008 dependency, ADD these:
    signal adBTWR:      std_logic;
    signal adSPWR:      std_logic;
    signal adLSWR:      std_logic;
    signal adHSWR:      std_logic;
begin
-- Write ENABLE conditions:

    adBTWR <= adBT and WR;
    adSPWR <= adSP and WR;
    adLSWR <= adLS and WR;
    adHSWR <= adHS and WR;

-- SETUP_REGS:
BIT_TIME:
        process (clk, clrn)  -- enables not needed in sensitivity list
        begin
            if clrn = '0' then
                rg_bit_time  <= (others => '0');
            elsif rising_edge (clk) then
                if adBTWR = '1' then
                    rg_bit_time <= D;
                end if;
            end if;
        end process;
SAMPLE_TIME:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_sample_time  <= (others => '0');
            elsif rising_edge (clk) then
                if adSPWR = '1' then
                    rg_sample_time <= D;
                end if;
            end if;
        end process;
LOW_SYNC:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_low_sync  <= (others => '0');
            elsif rising_edge (clk) then
                if adLSWR = '1' then
                    rg_low_sync <= D;
                end if;
            end if;
        end process;
HI_SYNC:
        process (clk, clrn)
        begin
            if clrn = '0' then
                rg_hi_sync  <= (others => '0');
            elsif rising_edge (clk) then
                if adHSWR = '1' then
                    rg_hi_sync <= D;
                end if;
            end if;
        end process;
end architecture rtl1;

That's four process statements.

The canny ready will notice the code could be compacted further by using separate enables for the named register outputs:

architecture rtl2 of setup_comp_reg is
    signal adBTWR:      std_logic;
    signal adSPWR:      std_logic;
    signal adLSWR:      std_logic;
    signal adHSWR:      std_logic;
begin
-- Write ENABLE conditions:
    adBTWR <= adBT and WR;
    adSPWR <= adSP and WR;
    adLSWR <= adLS and WR;
    adHSWR <= adHS and WR;

BT_SP_LS_HS:
        process (clk, clrn)  -- enables not needed in sensitivity list
        begin
            if clrn = '0' then
                rg_bit_time  <= (others => '0');
                rg_sample_time  <= (others => '0');
                rg_low_sync  <= (others => '0');
                rg_hi_sync  <= (others => '0');
            elsif rising_edge (clk) then
                if adBTWR = '1' then
                    rg_bit_time <= D;
                end if;
                if adSPWR = '1' then
                    rg_sample_time <= D;
                end if;
                if adLSWR = '1' then
                    rg_low_sync <= D;
                end if;
                if adHSWR = '1' then
                    rg_hi_sync <= D;
                end if;
            end if;
        end process;
end architecture rtl2;

Process statements are the unit of simulation in VHDL. The fewer there are the less execution overhead from suspension and resumption. The rtl2 example has one process statement. It works without having all the enables in the sensitivity list because they are 'sampled' on the clock rising edge. The authority for leaving the enables out comes from IEEE Std 1076.6-2004 (now withdrawn, RTL Synthesis) which describes syntax for and the required sensitivity list elements for edge sensitive sequential logic. Vendors typically provide examples of a subset of the sequential logic forms they will support and are guaranteed to comply with 1076.6.

The VHDL code above all analyzes.

(Looks like part of an IC tester.)

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, this answers my question. Just one more thing, using the generate statement is not as good as using rtl2 architecture? I should go for the rtl2, right? Thank You for our help.
Actel's generate statement supports bottom up design (with register primitives) that's not needed in VHDL which supports implied registers through RTL synthesis. The lack of RTL synthesis is a limitation in AHDL. All three architectures would generate equivalent net lists. The last, rtl2 would be better for simulation when porting more of a system design into the same higher density modern device or performing system simulation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.