首页 文章

增加内部信号

提问于
浏览
0

VHDL编码问题:(你好!我一直在研究这个问题 . 我觉得这是一个我不太明白的开始问题 .

  • 我正在访问内部存储器,每行4行2位数 . 我已经能够很好地读取和写入内存,我的问题是增加我将存储下一个数据集的地址 .

  • 我的单位由具有三种状态的FSM控制 . 空闲,芦苇和仪式 . 我有三个内部信号,addressin:指向下一个要读取的地址的指针,addressout:指向下一个要写入的地址的指针和addressall,该地址将进入实际的存储器阶段 .

PROCESS (y)
    BEGIN
    CASE y IS
    WHEN I=>
    enable<='0';

    WHEN reed=>
    enable<='0';
    IF (addressin="00" OR addressin="01" OR addressin="10") THEN

        addressin<=addressin+"01";
    ELSE
        addressin<="00";
    END IF;
    addressall<=addressin;

    WHEN rite=>
    enable<='1';
    IF (addressout="00" OR addressout="01" OR addressout="10") THEN
        addressout<=addressout+1;
    ELSE
        addressout<="00";
    END IF;
    addressall<=addressout;

    END CASE;
END PROCESS;    

memorystage: memory PORT MAP (clck, NOT reset, NOT enable, addressall, datain, dataout);

当y发生变化时,过程将激活(状态变化是在代码中看不见 . )我的问题是,地址将改变,地址输出将改变,地址也将改变......但是从来没有一个,也从不在任何地方顺序逻辑...(我在十六进制显示中看到这个)例如我会得到地址:3 3 1 0 3 0 3 0 2 0 2 1 0 ....与其他两个地址信号相同 . 我不知道我做错了什么 . 这只是一个大项目的一部分,所以我把它拉出去自己动手 . :(我做错了什么?谢谢 . -Jen

3 回答

  • 1

    我认为你've fallen prey to VHDL'(very well defined,但经常让新手感到困惑)信号更新规则 . 另见这个问题.. When do signals get assigned in VHDL?

    信号仅在流程结束时更新(或者当 wait 发生时,但我们现在将保留该选项!)


    IF (addressin="00" OR addressin="01" OR addressin="10") THEN
        addressin<=addressin+"01";
    ELSE
        addressin<="00";
    END IF;
    addressall<=addressin;
    

    addressall 将获得 addressin 的先前值,而不是've just set it to as that hasn'尚未更新的值 .

    要获得所需的行为,请在流程中将 addressin 更改为 variable (并且您必须将所有 <= 分配更改为 := 赋值) . 变量按您希望的方式工作 - 立即应用更新 .

    我几乎总是在过程中使用变量来保留信号,以便与其他过程进行通信 .

  • 0

    不确定你是否可以使用同步设计,但我把它扔在了一起 . 如果您处于簧片或仪式状态,则此设计将通过您的地址指针(addressin,addressout)增加,如时钟更新 .

    PROCESS (y, clk) BEGIN
        IF rising_edge(clk) then
            enable<='0';
            CASE y IS
                WHEN I=>
    
                WHEN reed=>
                    IF(addressin ="11") then
                        addressin <= "00";
                    ELSE
                        addressin <= addressin + 1;
                    END IF;
    
                    addressall<=addressin;
    
                WHEN rite=>
                    enable<='1';
    
                    IF(addressout ="11") then
                        addressout <= "00";
                    ELSE
                        addressout <= addressin + 1;
                    END IF;
    
                    addressall<=addressout;
            END CASE;
        END IF;
    END PROCESS;    
    
    memorystage: memory PORT MAP (clck, NOT reset, NOT enable, addressall, datain, dataout);
    

    如果您只希望每次状态更改一次更新,您可以执行类似的操作

    prev_state : PROCESS (y,clk) BEGIN
        IF rising_edge(clk) then
            ybuff <= y;
        END IF;
    END PROCESS;
    
    PROCESS (y, clk) BEGIN
        IF rising_edge(clk) then
            IF (ybuff /= y) then
                enable <= '0';
                CASE y IS 
                    ....
                    ....
    

    如果你想要别的东西,你需要给我们更多的代码 . 这有点被黑(因为我没有你的状态逻辑或更新信号)

    我同意Martin的说法,你当前对addressall的更新并不是正确的方法 . 就像他说你可以使用变量来解决这个问题,或者如果你真的想要保留它,你应该将它放在一个单独的进程块中,更新addressall以使奇怪性更加明确和受控制 . 现在(和我发布的第二个更新程序)你将始终是指针后面的一个地址(并且在状态机后面有一个完整的循环)

  • 0

    还需要考虑几点:

    1)输入/输出地址的递增方式不一致: addressin<=addressin+"01";addressout<=addressout+1; . 这些分配的行为将取决于操作数的信号类型,这就是为什么该信息有用,尽管这可能不是一个真正的问题 .

    2)假设地址信号的任何变化与开启 y 直接相关应该是相对安全的,因为这是该过程的灵敏度列表中的唯一信号 . 您是否在波形查看器中检查了 y 的值和地址?

    3)保罗建议这样做,但我只是想澄清为什么你可能希望这个电路是"clocked"(同步) . 如果灵敏度列表中没有时钟,则此过程仅对 y 上的更改敏感 . 因此,此过程隐含的任何内存元素都将完全忽略时钟,并且仅受输入 y 的更改影响 . 换句话说,要推进读指针, y 必须在 idlereed 状态之间切换 . 您必须决定这是否是预期的,或者逻辑是否应该在 y 上存在 reed 状态的每个时钟周期推进读指针 . 由于时钟接受特殊处理以简化静态时序分析,因此存储器元件不接收指定时钟可能是非传统的,但它对下游工具的承诺相同 .

    总的来说,听起来你很清楚你想要完成什么,并掌握一些VHDL的细微差别,所以下一步是进一步隔离意外行为 . 更多代码有助于排除一些潜在问题,但也许同时测试您的假设并提供可重现示例的最佳方法是创建一个说明意外行为的测试平台 .

    例如,这是一个测试平台,用于处理您的进程的时钟副本 .

    Library ieee;
    Use ieee.std_logic_1164.all;
    Use ieee.numeric_std.all;
    
    Entity test Is
    End Entity;
    
    Architecture main of test Is
        Signal enable, clock : std_logic := '0';
        Signal addressin, addressout, addressall : unsigned(0 to 1) := "00";
        Type op_t is (reed, idle, rite);
        Signal y : op_t; 
        Signal done : boolean;
    Begin
        clocks: process
        begin
            if not done then
                clock <= not clock;
                wait for 0.5 ns;
            else
                wait;
            end if;
        end process;
    
        PROCESS (clock, y)
        BEGIN
        if rising_edge(clock) then
        CASE y IS
            WHEN idle=>
                enable<='0';
    
            WHEN reed=>
                enable<='0';
                IF (addressin="00" OR addressin="01" OR addressin="10") THEN
                    addressin<=addressin+1;
                ELSE
                    addressin<="00";
                END IF;
                addressall<=addressin;
    
            WHEN rite=>
                enable<='1';
                IF (addressout="00" OR addressout="01" OR addressout="10") THEN
                    addressout<=addressout+1;
                ELSE
                    addressout<="00";
                END IF;
                addressall<=addressout;
    
        END CASE;
        end if;
        END PROCESS;
    
        main: Process
        Begin
            y <= idle;
            wait for 1 ns;
            y <= reed;
            wait for 1 ns;
            assert addressall = "00";
            wait for 1 ns;
            assert addressall = "01";
            wait for 1 ns;
            assert addressall = "10";
            wait for 1 ns;
            assert addressall = "11";
            y <= idle;
            wait for 1 ns;
            done <= true;
            wait;
        End Process;
    
    End Architecture;
    

相关问题