Electronics > FPGA

CycloneIV registers - infer use of both clock ENA and synch clear SCLR

(1/2) > >>

voltsandjolts:
Hmm, stuck on the basics here!  :-[

Just a simple 16bit register.
First picture shows almost what I want, just need to connect i_rst to SCLR...but I can't get there.
The second picture is functional but not what I expected ...and less efficient since it's not using available hardware?
Tried different ways of structuring the code but no luck.

What do I need to do in VHDL to infer the use of both ENA and SCLR?


--- Code: ---library ieee;
use ieee.std_logic_1164.all;

entity dtype is
port (
i_clk, i_clk_en : in std_logic;
i_rst : in std_logic;
i : in std_logic_vector(15 downto 0);
q : out std_logic_vector(15 downto 0)
);
end dtype;

architecture rtl of dtype is
begin
process (i_clk)
begin
-- this produces 16bit register and uses ENA for clock enable. All as expected.
-- if rising_edge(i_clk) then
--   if (i_clk_en = '1') then
--     q <= i;
--   end if;
-- end if;
-- end process;
 
-- this doesn't use ENA or SCLR, why not?
if rising_edge(i_clk) then
if (i_rst = '1') then
q <= (others => '0');
elsif (i_clk_en = '1') then
q <= i;
end if;
end if;
end process;
 
end architecture;

--- End code ---

SiliconWizard:
Regarding the use of SCLR itself, you probably have an answer there: https://www.intel.com/content/www/us/en/support/programmable/articles/000075977.html

As to the second version not even using ENA, you need to take a look at the schematic you got. It's more "severe" than just not using ENA. As you can see, the result *looks* very inefficient, with the output of the register fed back to an input MUX, and an additional MUX to deal with the synchronous clear. While it's not "pretty" to look at, it may actually not make a difference. The reason for the first point (synthesis not necessarily using SCLR) is an optimization one. In FPGAs, you don't deal with fully independent logic structures as shown on schematics, you deal with logic blocks, and their efficient use is something that often eludes us poor humans. So you may think it didn't do a good job, while actually the end result is everything as good, if not better.

Now the last point here regarding your second version is the use of both a clock enable and a synchronous clear. One thing to check in Intel's docs is whether the synchronous clear signal of registers is subject to the clock enable signal or not. In the code you posted, you are assuming it's not. I am not sure.


voltsandjolts:

--- Quote from: SiliconWizard on November 28, 2021, 05:11:25 pm ---Regarding the use of SCLR itself, you probably have an answer there: https://www.intel.com/content/www/us/en/support/programmable/articles/000075977.html

--- End quote ---

I had guessed that might be the case, hence sized the register to use a whole LAB.

Resorting to primitives fixes it, but that's not ideal.


--- Code: ---library ieee;
use ieee.std_logic_1164.all;

library altera;
use altera.altera_primitives_components.all;

entity dtype is
generic (
USE_PRIMITIVE_DFFEAS : natural := 1
);
port (
i_clk, i_clk_en : in std_logic;
i_rst : in std_logic;
d : in std_logic_vector(15 downto 0);
q : out std_logic_vector(15 downto 0)
);
end dtype;

architecture rtl of dtype is

component DFFEAS
port (
d : in STD_LOGIC;
clk : in STD_LOGIC;
clrn : in STD_LOGIC;
prn : in STD_LOGIC;
ena : in STD_LOGIC;
asdata : in STD_LOGIC;
aload : in STD_LOGIC;
sclr : in STD_LOGIC;
sload : in STD_LOGIC;
q : out STD_LOGIC
);
end component;
 
begin
test_infer : if USE_PRIMITIVE_DFFEAS = 0 generate
process (i_clk)
begin
-- this produces 16bit register and uses ENA for clock enable. All as expected.
-- if rising_edge(i_clk) then
-- if (i_clk_en = '1') then
-- q <= i;
-- end if;
-- end if;
-- end process;

-- this doesn't use ENA or SCLR, why not?
if rising_edge(i_clk) then
if (i_rst = '1') then
q <= (others => '0');
elsif (i_clk_en = '1') then
q <= d;
end if;
end if;
end process;
end generate test_infer;

test_prim : if USE_PRIMITIVE_DFFEAS = 1 generate
GEN_REG :
for I in 0 to 15 generate
REGX : DFFEAS
port map(
d => d(I),
clk => i_clk,
clrn => '1',
prn => '1',
ena => i_clk_en,
asdata => '0',
aload => '0',
sclr => i_rst,
sload => '0',
q => q(I)
);
end generate GEN_REG;
   end generate test_prim;

end architecture;

--- End code ---

Someone:

--- Quote from: voltsandjolts on November 28, 2021, 07:13:21 pm ---Resorting to primitives fixes it, but that's not ideal.
--- End quote ---
That has also changed the functionality and is not equivalent to the HDL code you wrote, as SiliconWizard discussed.


--- Quote from: SiliconWizard on November 28, 2021, 05:11:25 pm ---Now the last point here regarding your second version is the use of both a clock enable and a synchronous clear. One thing to check in Intel's docs is whether the synchronous clear signal of registers is subject to the clock enable signal or not. In the code you posted, you are assuming it's not. I am not sure.
--- End quote ---
Lead a horse to water and all that....

voltsandjolts:
Thanks.  In my OP I did say that I tried different ways of structuring the code, including this, which also doesn't work:


--- Code: ----- this doesn't use SCLR, why not?
if rising_edge(i_clk) then
    if (i_clk_en = '1') then
        if (i_rst = '1') then
            q <= (others => '0');
        else
            q <= d;
        end if;
    end if;
end if;

--- End code ---

Any more clues on the direction of nearest water for this thoroughbred?

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version