Search code examples
arraysvhdlrecordxilinxintel-fpga

Assigning Records VHDL


Good time to everyone.

Resently I try to improve code in new project and found some interesting decoder. It has 2 processes: in first all data formed and in second all bus triggered in out registers by control signal. But some wires need to be reset in some period of time (in second process).

So I deside to write this code for correct resettind some signals ([cm_regA/cm_regB] are records with different types of data):

----------------------------------------
LOAD_DATA_PROCESS: process(clk_i)
begin
  if rising_edge(clk_i) then
    if (reset_reg) then
      cm_regB.reg_1 <= '0';
      cm_regB.reg_2 <= '0';
      cm_regB.reg_3 <= '0';
      cm_regB.reg_4 <= '0';
    else
      if (load_reg) then
        cm_regB <= cm_regA;
      else null;
      end if;
    end if;
  end if;
end process;
----------------------------------------

But this construction Synthesized with lot of multiplexers betwen reg_5...reg_10, so next code give me good synthesized construction and great speed:

----------------------------------------
LOAD_DATA_PROCESS: process(clk_i)
begin
  if rising_edge(clk_i) then
    if (reset_reg) then
      cm_regB.reg_1 <= '0';
      cm_regB.reg_2 <= '0';
      cm_regB.reg_3 <= '0';
      cm_regB.reg_4 <= '0';
    else
      if (load_reg) then
        cm_regB.reg_1 <= cm_regA.reg_1;
        cm_regB.reg_2 <= cm_regA.reg_2;
        cm_regB.reg_3 <= cm_regA.reg_3;
        cm_regB.reg_4 <= cm_regA.reg_4;
      else null;
      end if;
    end if;

    if (load_reg) then
      cm_regB.reg_5  <= cm_regA.reg_5;
      cm_regB.reg_6  <= cm_regA.reg_6;
      cm_regB.reg_7  <= cm_regA.reg_7;
      cm_regB.reg_8  <= cm_regA.reg_8;
      cm_regB.reg_9  <= cm_regA.reg_9;
      cm_regB.reg_10  <= cm_regA.reg_10;
    else null;
    end if;

  end if;
end process;
----------------------------------------

So the questions next:

  1. How make this construction more compact (like first example)?
  2. Or how to make any changes in buses [cm_regA/cm_regB] visible for second example (in case changing first process and forgot add this changes to LOAD_DATA_PROCESS)?

P.S. Type of cm_regA and cm_regB are declarated in package. Here it is:

----------------------------------------
type cm_t is record
    reg_1   : STD_LOGIC;
    reg_2   : STD_LOGIC;
    reg_3   : STD_LOGIC;   
    reg_4   : STD_LOGIC;
    reg_5   : STD_LOGIC;
    reg_6   : BOOLEAN;
    reg_7   : STD_LOGIC;
    reg_8   : STD_LOGIC;
    reg_9   : STD_LOGIC_VECTOR(CONST_1-1 downto 0);
    reg_10  : STD_LOGIC_VECTOR(CONST_2-1 downto 0);
end record cm_t;
----------------------------------------

Solution

  • In the case of your first code, you are indeed adding a dependency to reset for reg_5 to reg_10. This is because of the if-else statement. This is the effective code you write for these registers.

    if not(reset_reg) and load_reg then
        cm_regB.reg_5 <= cm_regA.reg_5;
        [...]
        cm_regB.reg_10 <= cm_regA.reg_10;
    end if;
    

    So, you should separate the reset block from the other assignment. You can achieve that by using the fact that for signals only the last assignment in a process will be applied the next delta cycle. So something like this:

    LOAD_DATA_PROCESS: process(clk_i)
    begin
        if rising_edge(clk_i) then
            if load_reg then
                cm_regB <= cm_regA;
            end if;
            if reset_reg then
                cm_regB.reg_1 <= '0';
                cm_regB.reg_2 <= '0';
                cm_regB.reg_3 <= '0';
                cm_regB.reg_4 <= '0';
            end if;
        end if;
    end process;