子模块是由求解器独立激发的还是通过连接的顶层模块激发的?

Do sub modules get stimulated independently by the solver or through the connected top level module?

我正在尝试完成来自 Dan Gizzelquist 的 tutorial with example exercises

其中一个练习(练习 4)实现了一个移位寄存器,由两个子模块和一个顶层模块组成。

编辑: 添加练习源代码:

我会 post 此处提供 vhdl 源代码,如果您更喜欢 verilog,this link.[=22= 的 exercise-04 文件夹中也有 verilog 源代码]

lfsr_fib.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity  lfsr_fib is

    generic (LN : natural := 8;
        TAPS : std_logic_vector(LN-1 downto 0) := x"2d";
        INITIAL_FILL : std_logic_vector(LN-1 downto 0) := x"01");

    port (i_clk, i_reset, i_ce, i_in : in std_logic;
        o_bit : out std_logic := INITIAL_FILL(0));

end entity lfsr_fib;

architecture behavior of lfsr_fib is
    signal  sreg : std_logic_vector(LN-1 downto 0) := INITIAL_FILL;
begin


process(i_clk)
begin
    if (rising_edge(i_clk)) then
        if (i_reset = '1') then
            sreg <= INITIAL_FILL;
        elsif (i_ce = '1') then
            sreg(LN-2 downto 0) <= sreg(LN-1 downto 1);
            sreg(LN-1) <= (xor (sreg and TAPS)) xor i_in;
        end if;
    end if;
end process;

process(sreg)
begin
    o_bit <= sreg(0);
end process;


end behavior;

dblpipe.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity dblpipe is

    port (i_clk, i_ce, i_data : in std_logic;
        o_data : out std_logic := '0');

end entity dblpipe;

architecture behavior of dblpipe is
    component lfsr_fib
      port(i_clk, i_reset, i_ce, i_in : in std_logic;
        o_bit : out std_logic);
    end component;

    signal  a_data, b_data : std_logic;
begin
----
----

one: lfsr_fib port map (
    i_clk => i_clk,
    i_reset => '0',
    i_ce => i_ce,
    i_in => i_data,
    o_bit => a_data);

two: lfsr_fib port map (
    i_clk => i_clk,
    i_reset => '0',
    i_ce => i_ce,
    i_in => i_data,
    o_bit => b_data);

process(a_data, b_data)
begin
    o_data <= a_data xor b_data;
end process;

----
----
end behavior;

正式属性文件:

`default_nettype    none
//
module dblpipe_vhd(i_clk, i_ce, o_data);
    input   wire    i_clk;
    input   wire    i_ce;
    input   wire    o_data;

`ifdef FORMAL
// Your goal: to get the following assertion to pass
//

    // assume(one.sreg = two.sreg);
    // assert(one.sreg == two.sreg);

    always @(*)
    begin
        assert(o_data == 1'b0);
    end

    always @(*)
    begin
        if(i_clk)
            begin
                assume(one.i_clk);
                assume(two.i_clk);
            end
        else
            begin
                assume(!one.i_clk);
                assume(!two.i_clk);
            end
    end

    //Trigger a counter example at step 18 - to check if the assumptions made where applied
    // always @(posedge i_clk)
    //  if(f_time >= 18)
    //      assert(f_time < 18);


`endif
endmodule

bind dblpipe dblpipe_vhd copy (.*);

sby 控制脚本:

[options]
mode prove

[engines]
smtbmc
# abc pdr
# abc pdr
# aiger avy
# aiger suprove

[script]
read -vhdl   lfsr_fib.vhd
read -vhdl   dblpipe.vhd
read -formal dblpipe_vhd.sv
prep -top dblpipe

[files]
lfsr_fib.vhd
dblpipe.vhd
dblpipe_vhd.sv

相关问题一:

尝试不同的断言导致了以下 K 感应跟踪:

我的问题是,为什么跟踪显示子模块的时钟在滴答作响,而顶层时钟却没有?

即使添加以下代码也无法让时钟同时滴答作响:

always @(*)
begin
    if(i_clk)
        begin
            assume(one.i_clk);
            assume(two.i_clk);
        end
    else
        begin
            assume(!one.i_clk);
            assume(!two.i_clk);
        end
end

然而 i_ce 显然以某种方式连接,因为它在所有模块之间同步: i_ce Traces

相关问题2

为什么问题的解决方案是断言两个sreg相等而不是假设它们相等?

当我们定义哪些输入对我来说是理所当然的时,听起来更像是在这种情况下应该使用 assume。

always @(*)
    assert(one.sreg == two.sreg);

而不是:

always @(*)
    assume(one.sreg = two.sreg);

相关问题3

有人可以向我解释为什么输入数据没有连接到包装器模块中吗?这样我就无法在跟踪视图中看到哪些数据被输入到顶层模块中...但是如果我将它添加到模块定义中,它在跟踪文件中仍然始终为 0。

module dblpipe_vhd(i_clk, i_ce, o_data);
input   wire    i_clk;
input   wire    i_ce;
input   wire    o_data;

我过去遇到的大多数问题都可以通过反复阅读可用的文档来解决,但是对于这些问题我自己找不到解决方案。

关于问题 1

您看到的跟踪可能存在某种工具错误,导致它无法正确设置 dblpipe_vhd .i_clk 的值。我这样说,是因为您的断言似乎正在触发。该工具可能会看到直接在 dblpipe_vhd 下没有时钟逻辑,并将时钟视为冗余。

该工具(以及其他形式验证工具)自动推断时钟并以不同于描述逻辑的“常规”信号的方式处理它们。您为时钟编写的 assumes 可能不会执行任何操作。

(我对 sby 不太熟悉,但我可以想象它实际上使用 smt_clock 信号为逻辑计时,而其他时钟仅用于调试目的。)

关于问题 2

IMO,要通过 o_data 的断言,assume 两个 LSFR 从相同状态开始就足够了。由于您从不应用重置,因此该工具可以自由选择初始状态。我猜作者是想说明这一点。

不知道您为什么要在不先应用重置的情况下进行校样。那里有复位信号以确保可预测的启动状态。如果不先重置它们,您将永远无法真正使用它们。

关于问题 3

dblpipe_vhd 不是顶层模块。 dblpipe 是。 bind 语句在 dblpipe 下添加了一个名为 copydblpipe_vhd 实例。它只针对 o_data 断言,所以它只需要那个信号。