VHDL - FSM 未启动(仅在时序仿真中) [英] VHDL - FSM not starting (JUST in timing simulation)

查看:46
本文介绍了VHDL - FSM 未启动(仅在时序仿真中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的硕士论文工作,我对 VHDL 还很陌生,但我仍然需要实现一些复杂的东西.这是我必须编写的最简单的结构之一,但我仍然遇到了一些问题.

I'm working for my master thesis and I'm pretty new to VHDL, but still I have to implement some complex things. This is one of the easiest structures I had to write, and still I'm encountering some problems.

这是一个 FSM,它实现了一个带有低电平有效同步信号的 24 位移位寄存器(用于对 DAC 进行编程).这只是我为我的项目创建的复杂细化链的结束.我尽可能地遵循 FSM 的示例模型.

It's a FSM implementing a 24bit shift register with an active-low sync signal (to program a DAC). It's just the end of a complex elaboration chain I created for my project. I followed the example model of a FSM as much as I could.

行为模拟运行良好,实际上,就行为模拟而言,我创建的整个细化链运行良好.然而,一旦我尝试翻译后模拟,事情就开始出错:很多X"输出信号.

The behavioral simulation works fine, actually the whole elaboration chain I created works perfectly fine as far as the behavioral simulation concerns. However, once I try the Post-translate simulation things start to go wrong: lots of 'X' output signals.

使用这个简单的移位寄存器,我没有得到任何X",但是我无法进入 load_and_prepare_data 阶段.似乎 current_state 发生了变化(通过检查一些信号),但详细说明没有继续.

With this simple shift register I DON'T get any 'X', however I can't get to the load_and_prepare_data phase. It seems that the current_state changes (by inspecting some signals), but the elaboration doesn't go on.

请记住,由于我是这门语言的新手,我不知道应该在这个 FSM 上设置什么时间限制(无论如何我都不知道如何在 top.ucf 上写它们)

Please keep in mind that since I'm new to the language, I have no idea of what timing constraints I should set on this FSM (and I wouldn't know how to write them on the top.ucf anyway)

你能看出哪里出了问题吗?提前致谢

Can you see what's wrong? Thanks in advance

编辑

我听从了您的建议,并使用单状态进程清理了 FSM.我仍然对放在哪里"有些疑问,但我真的很喜欢新的实现.无论如何,我现在得到了一个干净的行为模拟,但在翻译后模拟中的所有输出上都是X".这是什么原因造成的?我将发布新代码和测试平台:

I followed your advices and cleaned up the FSM by using a single state process. I still have some doubts about "where to put what" but I really like the new implementation. Anyway I now get a clean behavioral simulation but 'X' on all outputs in post translate simulation. What is causing this? I'll post the both the new code and the testbench:

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:44:03 11/28/2014 
-- Design Name: 
-- Module Name:    dac_ad5764r_24bit_sr_programmer_v2 - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: This is a PISO shift register that gets a 24bit parallel input word.
--              It outputs the 24bit input word starting from the MSB and enables
--              an active low ChipSelect line for 24 clock periods.
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dac_ad5764r_24bit_sr_programmer_v2 is
    Port ( clk : in  STD_LOGIC;
           start : in  STD_LOGIC;
           reset : in  STD_LOGIC; -- Note that this reset is for the FSM not for the DAC
           reset_all_dac : in STD_LOGIC;
           data_in : in  STD_LOGIC_VECTOR (23 downto 0);
           serial_data_out : out  STD_LOGIC;
           sync_out : out  STD_LOGIC; -- This is a chip select
           reset_out : out STD_LOGIC;
           busy : out STD_LOGIC
         );
end dac_ad5764r_24bit_sr_programmer_v2;

architecture Behavioral of dac_ad5764r_24bit_sr_programmer_v2 is

-- Stati
type state_type is (idle, load_and_prepare_data, transmission);
--ATTRIBUTE ENUM_ENCODING : STRING; 
--ATTRIBUTE ENUM_ENCODING OF state_type: TYPE IS "001 010 100";
signal state: state_type := idle;
--signal next_state: state_type := idle;

-- Clock counter
--signal clk_counter_enable : STD_LOGIC := '0';
signal clk_counter : unsigned(4 downto 0) := (others => '0');

-- Shift register
signal stored_data: STD_LOGIC_VECTOR (23 downto 0) := (others => '0');

begin

FSM_single_process: process(clk)
begin
    if rising_edge(clk) then
        if reset = '1' then
            serial_data_out <= '0';
            sync_out <= '1';
            reset_out <= '1';
            busy <= '0';
            state <= idle;
        else
            -- Default
            serial_data_out <= '0';
            sync_out <= '1';
            reset_out <= '1';
            busy <= '0';

            case (state) is
                when transmission =>
                    serial_data_out <= stored_data(23);
                    sync_out <= '0';
                    busy <= '1';
                    clk_counter <= clk_counter + 1;
                    stored_data <= stored_data(22 downto 0) & "0";
                    state <= transmission;
                    if (clk_counter = 23) then
                        state <= idle;
                    end if;
                when others => -- Idle
                    if start = '1' then
                        serial_data_out <= data_in(23);
                        sync_out <= '0';
                        reset_out <= '1';
                        busy <= '1';
                        stored_data <= data_in;
                        clk_counter <= "00001";
                        state <= transmission;
                    end if;
            end case;

--            if (reset_all_dac = '1') then
--              reset_out <= '0';
--          end if;
        end if;
    end if;
end process;


end;

还有测试平台:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY dac_ad5764r_24bit_sr_programmer_tb IS
END dac_ad5764r_24bit_sr_programmer_tb;

ARCHITECTURE behavior OF dac_ad5764r_24bit_sr_programmer_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT dac_ad5764r_24bit_sr_programmer_v2
    PORT(
         clk : IN  std_logic;
         start : IN  std_logic;
         reset : IN  std_logic;
         data_in : IN  std_logic_vector(23 downto 0);
         serial_data_out : OUT  std_logic;
         reset_all_dac : IN std_logic;
         sync_out : OUT  std_logic;
         reset_out : OUT  std_logic;
         --finish : OUT  std_logic;
         busy : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal start : std_logic := '0';
   signal reset : std_logic := '0';
   signal data_in : std_logic_vector(23 downto 0) := (others => '0');
   signal reset_all_dac : std_logic := '0';

    --Outputs
   signal serial_data_out : std_logic;
   signal sync_out : std_logic;
   signal reset_out : std_logic;
   --signal finish : std_logic;
   signal busy : std_logic;

   -- Clock period definitions
   constant clk_period : time := 100 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: dac_ad5764r_24bit_sr_programmer_v2 PORT MAP (
          clk => clk,
          start => start,
          reset => reset,
          data_in => data_in,
          reset_all_dac => reset_all_dac,
          serial_data_out => serial_data_out,
          sync_out => sync_out,
          reset_out => reset_out,
          --finish => finish,
          busy => busy
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for clk_period*10;
      reset <= '1' after 25 ns;
      wait for clk_period*1;
      reset <= '0' after 25 ns;
      wait for clk_period*3; 
      reset_all_dac <= '1' after 25 ns;
      wait for clk_period*1;
      reset_all_dac <= '0' after 25 ns;
      wait for clk_period*5; 
      data_in <= "111111111111111111111111" after 25 ns;
      wait for clk_period*3;
        start <= '1' after 25 ns;
      wait for clk_period*1;
        start <= '0' after 25 ns;


      wait;
   end process;

END;

更新 1

更新了最后一个设计:这段代码没有导致任何X"(不知道为什么,这不是,但前一个做了).然而,它并没有像前 3 个进程机器那样启动(在 POST-TRANSLATE 模拟中),并且信号 sync_out 停留在 0 而默认情况下它应该是1".

Updated with the last design: this code is not causing any 'X' (can't figure out why, this doesn't but the previous did). However it's not starting (in POST-TRANSLATE simulation) just like the first 3 process machine, and the signal sync_out is stuck at 0 while it should be '1' by default.

更新 2

我一直在研究技术原理图,从 sync_out=0 的问题开始:它是用 FDS 实现的,S 是 FSM 复位信号,D 来自 LUT3,I = state&reset&start和 INIT = 45 = "00101101".我在模拟中寻找了这个 LUT3,我注意到它有 INIT = "00000000"

I've been looking into the tecnology schematic, starting from the problem of the sync_out=0: it's implemented with a FDS, S is the FSM reset signal, D is coming from a LUT3 with I = state&reset&start and INIT = 45 = "00101101". I've looked for this LUT3 in the simulation and I've noticed that it has INIT = "00000000"!

关于如何运行这个模拟,我有什么遗漏吗?好像设计中的每个LUT都没有设置好!

Is there something I'm missing about how to run this simulation? It seems that every LUT in the design have not been set!

更新 3似乎 Post-Translate 模拟在某些方面有问题,或者由于某种原因我没有正确配置它:Post-Map 和 Post-PAR 模拟工作并显示一些输出.然而,有一个奇怪的错误:stored_data 寄存器没有用完整的 data_in 向量更新,之后,FSM 正确运行并输出存储的数据.我刚刚在综合之后查看了技术原理图,出于某种原因,位 23、22、21、19、18 没有连接到相应的 data_in 位.您可以在 Post-Map 模拟的此屏幕截图中看到效果.在 Post-PAR 中也会发生同样的情况,但这个问题似乎直接来自于综合!

UPDATE 3 It seems that the Post-Translate simulation is buggy in some way, or I'm not configuring it correctly for some reason: the Post-Map and the Post-PAR simulations work and display some outputs. However there is an odd bug: the stored_data register is not updated with the complete data_in vector, after that, the FSM operates correctly and outputs the data stored. I've looked in the tecnology schematic just after synthesis and for some reason the bits 23,22,21,19,18 are not connected to the corresponding data_in bit. You can see the effect in this screenshot from Post-Map simulation. Same happens in Post-PAR, but it seems that this problems comes directly from the synthesis!

已解决:奇怪的输出来自综合优化.该工具意识到细化链中的前一个块永远不会为那些特定位输出与 0 不同的位.我的错误是假设我可以单独测试单个模块:我真正测试的是为 FPGA 综合的模块,同时考虑了设计中的所有其他内容!

Solved: the strange output comes from the Synthesis optimization. The tool realized that the previous block in the elaboration chain will never output a bit different from 0 for those specific bit. My mistake was assuming that I could test the single block alone: what I was really testing was the block synthetized for the FPGA taking into account everything else in the design!

感谢大家帮助我,我会听从你的建议!

Thanks to everybody helped me, I'm going to follow your advices!

推荐答案

我更喜欢单进程形式的状态机,它更干净、更简单,而且更不容易出现敏感列表错误等错误.我也会赞同 Paebbels 出色回答中的观点.不过,我认为这些都不是问题所在.

I prefer the single-process form of state machine, which is cleaner, simpler and much less prone to bugs like sensitivity-list errors. I would also endorse the points in Paebbels' excellent answer. However I don't think any of these are the problem here.

在合成后和 PAR 后模拟中需要注意的一件事是它们的时间模型与行为模型不同.行为模型遵循我在这个答案中描述的简单规则,并确保在典型的设计流程中,您可以直接进入硬件 - 无需合成后仿真,无需担心.

One thing to be aware of in post-synth and post-PAR simulations is that their model of time is different from the behavioural model. The behavioural model follows simple rules as I described in this answer and ensures that in a typical design flow you can go straight to hardware - without post-synth simulation, without worry.

确实,如果我正在寻找可疑的工具错误,我只会使用合成后或 PAR 后模拟.(适用于 FPGA 设计,而不是 ASIC!)

Indeed I only use post-synth or post-PAR simulations if I'm chasing a suspected tool bug. (For FPGA designs, not ASIC, that is!)

然而,这种简单的时序模型有其局限性.您可能熟悉一些问题,例如通过信号分配分配的时钟信号(通常隐藏在您不期望它的第 3 方模型中),它消耗增量周期,并确保您的时钟数据> 你的时钟而不是 after,随后所有的事情都比预期的提前一个周期发生......

However, that simple timing model has its limitations. You may be familiar with problems like a clock signal assigned via signal assignment (usually buried in a 3rd party model where you don't expect it) which consumes a delta cycle, and ensures that your clocked data arrives before your clock instead of after, and everything subsequently occurs one cycle earlier than intended...

在行为建模中,一点点纪律就可以避免此类麻烦.但后 PAR 建模并非如此.

In behavioural modelling, a little discipline will keep clear of such troubles. But the same is not true of post-PAR modelling.

您的测试平台可能与行为模型的设置方式相同.如果是这样,那很可能就是问题所在.

Your testbench is probably set up the same way as the behavioural model. And if so, that is likely to be the problem.

这是我在这种情况下所做的:我没有正式的权威,只是经验.当将 FPGA 连接到具有真实时序的外部存储器模型时,它也能很好地工作.

Here's what I do in this situation : I claim no formal authority for it, just experience. It also works well when interfacing the FPGA to external memory models with realistic timings.

1) 我假设简单(行为)时序模型适用于设计的所有内部信号.

1) I assume the simple (behavioural) timing model works correctly for all signals INTERNAL to the design.

2) 我对设计中的输入和输出没有任何假设.

2) I assume nothing of the sort for inputs and outputs from the design.

3) 我记下输入的估计建立和保持时序,(a) 来自 FPGA 数据表或更好,(b) 来自合成后或 PAR 后报告中显示的最坏情况值,以及围绕它们构建测试平台.工作示例:设置时间 1 ns,保持时间 2 ns,时钟周期 10 ns.这意味着可以保证正确读取时钟边沿后 2 ns 和 9 ns 之间的任何输入.我选择(任意)5 ns.

3) I take note of the estimated setup and hold timings on the inputs, (a) from the FPGA datasheet or better, (b) from the worst case values shown in the post-synth or post-PAR report, and structure the testbench around them. Worked example : setup time 1 ns, hold time 2 ns, clock period 10 ns. This means that any input between 2 ns and 9 ns after a clock edge is guaranteed to be corrrectly read. I choose (arbitrarily) 5 ns.

signal_to_fpga <= driving_value after 5 ns;

(请注意,Xilinx 通过将它们表示为偏移输入/输出之前/之后",将时序指的是前一个或未来时钟边沿,而不是您正在查看的时钟边沿,从而使这荒谬地违反直觉)

(Note that Xilinx makes this absurdly counter-intuitive by expressing them as "offset in/out before/after" which refers timings to a previous or future clock edge instead of the one you're looking at)

或者,如果输入来自现实世界中的 CPU 或内存,我会使用该设备的数据表时序规范.

Alternatively, if the input is fed from a CPU or memory in the real world, I use datasheet timing specifications for that device.

4) 我记下数据表或报告中报告的最坏情况时钟输出时序,并围绕它们构建设计.(比如说,7 ns)

4) I take note of the worst case clk-out timing reported in the datasheet or report, and structure the design around them. (say, 7 ns)

fpga_output_pin <= driving_value after 7 ns;

注意这个after"子句显然被合成忽略了;然而,合成后的反注会引入一些非常相似的东西.
5) 如果结果证明这还不够好,那么(可能在包装组件中以避免污染可合成代码)提高准确性,如

Note that this "after" clause is obviously ignored by synthesis; however the post-synth back-annotation will introduce something very like it.
5) If this turns out to be not good enough, then (possibly in a wrapper component to avoid polluting the synthesisable code) improve accuracy like

fpga_output_pin <= 'X' after 1 ps, driving_value after 7 ns;

6) 我重新运行了行为模拟.通常情况下,它现在会失败,因为它是在没有考虑现实时间的情况下编写的.

6) I re-run the behavioural simulation. Typically, it now fails, because it was written without realistic timings in mind.

7) 我修复了这些故障.这可能包括在测试从设计输出的值之前添加实际延迟.它可以是一个迭代过程.

7) I fix those failures. This may include adding realistic delays before testing values output from the design. It can be an iterative process.

现在,我有一个合理的期望,即后 PAR 仿真模型将直接放入测试平台并开始工作.

Now, I have a reasonable expectation that the post-PAR simulation model will drop straight in to the testbench and work.

这篇关于VHDL - FSM 未启动(仅在时序仿真中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆