keep_hierarchy约束在三模冗余中的应用

节选自《FPGA之道》

keep_hierarchy是一个综合和实现方面的约束。Xilinx的综合工具XST更倾向于平化HDL代码的层级结构,即将一级级的模块调用机制转换为一个没有子模块的超大模块,这样做的好处是能够进行更好地设计优化工作,因为平化操作去除了原有实体或模块之间的边界限制。
不过有些时候,XST的这种平化工作是我们所不希望的,这时keep_hierarchy语法便派上了用场。使用keep_hierarchy约束能够使综合工具保留指定部分的层级关系,这样一来,在后续的实现阶段也将保留这种层级关系。与此同时,也可以生成用于仿真的具有层级关系的网表。下图就很形象地说明了使用keep_hierarchy约束和不使用keep_hierarchy约束在综合及实现后的区别。

下面列举出在HDL中嵌入keep_hierarchy约束的语法:

--VHDL syntax
--第一步,先要声明keep_hierarchy约束;
attribute keep_hierarchy:string;
--第二步,为keep_hierarchy语法指定约束线网名称和属性取值;
attribute keep_hierarchy of <architecture_name>:architecture is "{TRUE | FALSE | SOFT}";
//Verilog syntax
(*KEEP_HIERARCHY=“{TRUE | FALSE | SOFT}”*)
//上述约束会作用于紧随其后调用的模块

从上述语法可以看出,keep_hierarchy约束具有三种属性值,其中false自然是不保留层级关系,而true和soft的区别就是,true会将这种约束传递给后续的实现环节,而soft则仅仅是在综合环节保留层级关系。
下面给出一个利用keep_hierarchy实现三模冗余D的示例:

三模冗余是航空、航天系统中经常用到的一种技术。简要来说,由于空间中的射线等原因,会有一定几率引起电子产品尤其是基于SRAM的FPGA发生一种称做“单粒子翻转”的效应。“单粒子翻转”即1变成0、0变成1,这样将会导致系统运行出错。因此,为了提高系统的稳定性和可靠性,人们想了很多种方法来应对空间中较为恶劣的工作环境,其中一种就是三模冗余,即通过3倍的冗余,结合3中取2的少数服从多数仲裁机制,来提高FPGA设计的抗干扰能力。

--VHDL example
--file lock.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY lock IS
    PORT (
        clk : IN STD_LOGIC;
        rst : IN STD_LOGIC;
        din : IN STD_LOGIC;
        dout : OUT STD_LOGIC
    );
END lock;
ARCHITECTURE Behavioral OF lock IS
BEGIN
    PROCESS (clk)
    BEGIN
        IF (clk'event AND clk = '1') THEN
            IF (rst = '1') THEN
                dout <= '0';
            ELSE
                dout <= din;
            END IF;
        END IF;
    END PROCESS;
END Behavioral;

--file mode3.vhd
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mode3 IS
    PORT (
        clk : IN STD_LOGIC;
        rst : IN STD_LOGIC;
        din : IN STD_LOGIC;
        dout : OUT STD_LOGIC
    );
END mode3;
ARCHITECTURE Behavioral OF mode3 IS
    SIGNAL a, b, c : STD_LOGIC;
    COMPONENT lock
        PORT (
            clk : IN STD_LOGIC;
            rst : IN STD_LOGIC;
            din : IN STD_LOGIC;
            dout : OUT STD_LOGIC
        );
    END COMPONENT;
    ATTRIBUTE keep_hierarchy : STRING;
    ATTRIBUTE keep_hierarchy OF m0 : ARCHITECTURE IS "TRUE";
    ATTRIBUTE keep_hierarchy OF m1 : ARCHITECTURE IS "TRUE";
    ATTRIBUTE keep_hierarchy OF m2 : ARCHITECTURE IS "TRUE";
BEGIN
    m0 : lock
    PORT MAP(
        clk => clk,
        rst => rst,
        din => din,
        dout => a
    );
    m1 : lock
    PORT MAP(
        clk => clk,
        rst => rst,
        din => din,
        dout => b
    );
    m2 : lock
    PORT MAP(
        clk => clk,
        rst => rst,
        din => din,
        dout => c
    );
    -- ATTRIBUTE keep_hierarchy : STRING;
    -- ATTRIBUTE keep_hierarchy OF m0 : ARCHITECTURE IS "TRUE";
    -- ATTRIBUTE keep_hierarchy OF m1 : ARCHITECTURE IS "TRUE";
    -- ATTRIBUTE keep_hierarchy OF m2 : ARCHITECTURE IS "TRUE";
    PROCESS (clk)
    BEGIN
        IF (clk'event AND clk = '1') THEN
            IF (rst = '1') THEN
                dout <= '0';
            ELSE
                IF (b /= c) THEN
                    dout <= a;
                ELSE
                    dout <= b;
                END IF;
            END IF;
        END IF;
    END PROCESS;
END Behavioral;

采用上例这种keep_hierarchy的约束添加方式,就可以成功确保在FPGA中实现了三个功能一模一样的模块。否则,由于这三个模块在功能上面完全等价,编译器便会优化掉其中的两个,而最终只保留一个模块,但是这样就无法实现“三模冗余”的保护功能了。

posted @ 2024-02-20 14:42  Radiumlrb  阅读(279)  评论(0编辑  收藏  举报