简体   繁体   English

伊势模拟VHDL

[英]Ise simulation VHDL

I would like to ask the following. 我想问以下问题。 I am working on an FPGA Tetris design. 我正在从事FPGA Tetris设计。 My code language is VHDL in ISE Environment in windows 7. 我的代码语言是Windows 7中ISE环境中的VHDL。

While I progress my work I ofter check my work with isim simulation. 在进行工作时,我经常通过isim模拟检查工作。 As the design is getting big isim stops working and closes. 随着设计变大,isim停止工作并关闭。 Basically the module causing this crash is a big fsm. 基本上,导致崩溃的模块是很大的fsm。 When I comment some states of the fsm ISIM is working fine again. 当我评论fsm的某些状态时,ISIM再次正常运行。

It doesn't matter which states I will comment. 我要评论哪个状态都没关系。 I can check the fsm working in parts. 我可以检查部分工作的fsm。 But I can not test it as a whole. 但是我无法整体测试。 Is it possible that this is not code error and it is just ISIM? 这可能不是代码错误,而只是ISIM吗?

Thanks 谢谢

How to split a complex FSM into parts? 如何将复杂的FSM分成几部分?
Here are some example lines to illustrate a simple call/return handshaking protocol between a main FSM and two function FSMs 这是一些示例行,用于说明主FSM和两个功能FSM之间的简单呼叫/返回握手协议

process(Clock)
begin
    if (Reset = '1') then
        MainFSM_State       <= ST_IDLE;
        Func1FSM_State  <= ST_IDLE;
        Func2FSM_State  <= ST_IDLE;
    else
        MainFSM_State       <= MainFSM_NextState;
        Func1FSM_State  <= Func1FSM_NextState;
        Func2FSM_State  <= Func2FSM_NextState;
    end if;
end process;

process(MainFSM_State, Input, ...,
                Func1FSM_Output, Func1FSM_Return,
                Func2FSM_Output, Func2FSM_Return)
begin
    Func1FSM_Call           <= '0';
    Func2FSM_Call           <= '0';

    MainFSM_Output      <= x"00";

    case MainFSM_State is
        when ST_IDLE =>
            if (Input = '1') then
                Func1FSM_Call               <= '1';
                MainFSM_NextState       <= ST_FUNC1_EXECUTING;
            end if;

        when ST_FUNC1_EXECUTING =>
            MainFSM_Output              <= Func1FSM_Output;

            if (Func1FSM_Return = '1') then
                Func2FSM_Call               <= '1';
            end if;

       ....
    end case;
end process;

Some general hints for your design (based on the code snippet) 有关设计的一些一般性提示(基于代码段)

Using big FSMs is also very fault-prone. 使用大型FSM也很容易出错。 So one goal of writing big FSMs should be readability, so you can find errors more easily. 因此,编写大型FSM的目标之一应该是可读性,这样您就可以更轻松地发现错误。

  • Don't use std_logic_arith, std_logic_unsigned while numeric_std is used. 使用numeric_std时,请勿使用std_logic_arith和std_logic_unsigned。 Use only numeric_std, that's adequate. 仅使用numeric_std,就足够了。

  • wait until is not a synthesizeable statement. wait until不是可综合的语句。 Use: 采用:

     if rising_edge(clk) then ... end if; 
  • Are your external inputs like reset_switch synchronized and debounced? 您的外部输入(例如reset_switch)是否同步和去抖动? A signal name like reset_switch implies that this signal is raw ;) 像reset_switch这样的信号名称表示该信号是原始的;)

  • You can improve the readability of if..elsif..else..end if; 您可以提高if..elsif..else..end if;的可读性if..elsif..else..end if; statements by using case statements (see line 230) 使用case语句的语句(请参见第230行)

  • You use masses of binary assignments like t_left_most <= "010111"; --23 您使用大量的二进制分配,例如t_left_most <= "010111"; --23 t_left_most <= "010111"; --23 . t_left_most <= "010111"; --23 Maybe it's better to declare t_left_most with another type (eg a constrained natural), so you can use integer literals in your FSM. 也许最好用其他类型(例如自然约束)声明t_left_most ,以便可以在FSM中使用整数文字。 For exporting these signals to other modules the signal is converted back to std_logic_vector. 为了将这些信号导出到其他模块,信号被转换回std_logic_vector。 -> improved readability ->提高了可读性

  • Some times it's good to introduce constants eg 有时最好引入常量,例如

     constant C_TOP_MOST : NATURAL := 0; 
  • I would advice you to extract your counter memReadAddress from your FSM. 我建议您从FSM中提取计数器memReadAddress Big FSMs should only generate flow-control signals, FSMs should not contain any data-flow logic (counters, multiplexers, ...). 大型FSM仅应生成流控制信号,FSM不应包含任何数据流逻辑(计数器,多路复用器等)。 So extract the counter to a separate process and add control signals to your big FSM. 因此,将计数器提取到一个单独的进程中,然后将控制信号添加到大型FSM中。

     when T_block_1 => ReadAddressCounter_en <= '1'; 

    Personally, I use prefixes like _rst, _en, _us, _inc, _dec for the counter control signals. 就个人而言,我为计数器控制信号使用诸如_rst,_en,_us,_inc,_dec之类的前缀。 _us stands for unsigned, because the my counters are unsigned counters and the value is converted to std_logic if needed. _us代表无符号,因为我的计数器是无符号计数器,并且在需要时将值转换为std_logic。

    Counter example with FSM 'remote control' signals: 带FSM“远程控制”信号的反例:

     process(Clock) begin if rising_edge(Clock) then if ((Reset or MemAddressCounter_rst) = '1') then MemAddressCounter_us <= (others => '0'); else if (MemAddressCounter_load = '1') then MemAddressCounter_us <= to_unsigned(5, MemAddressCounter_us'length); elsif (MemAddressCounter_inc = '1') then MemAddressCounter_us <= MemAddressCounter_us + 1; end if; end if; end if; end process; MemAddress <= std_logic_vector(MemAddressCounter_us); 
  • line 286 should not be synthesizable (I think Xilinx XST is not smart enough and if so, it's not predictable what XST would produce ...) 286行不应该是可综合的(我认为Xilinx XST不够智能,如果这样的话,就无法预测XST会产生什么...)

     dataIn<=dataOut(39 downto conv_integer(T_left_most+1))&T_square&T_square&T_square&dataOut(conv_integer(T_right_most-1) downto 0); 

So how can you fix the last point in the list of my hints? 那么,如何确定提示列表中的最后一点呢?

  1. simple way: use a 40:1 multiplexer 简单方法:使用40:1多路复用器
  2. more advanced way: try to use mask and bit-shift operations 更高级的方法:尝试使用掩码和移位操作
  3. use another data structure, which is more suitable for hardware :) 使用另一个数据结构,它更适合于硬件:)

If you want a more detailed discussion on this points, please leave a comment and I will try to extend my answer. 如果您想在这点上进行更详细的讨论,请发表评论,我将尝试扩大答案。

Extended answer - bit operation solution 扩展答案-位运算解决方案

So lets summarize line 286: 因此,让我们总结一下286行:

dataIn <= dataOut(39 downto conv_integer(T_left_most+1)) &
          T_square & T_square & T_square &
          dataOut(conv_integer(T_right_most-1) downto 0);

Your result consists of 3 parts: 您的结果包括3个部分:

  • dataout sliced from MSB downto dynamic marker 从MSB切片到动态标记的数据输出
  • 3 bits 3位
  • dataout sliced from dynamic marker downto 0 从动态标记到0的dataout切片

This bit insertion can also be done by a bitwise set/clear operation: 该位插入也可以通过按位设置/清除操作来完成:

  • set: result <= input or set_mask; set: result <= input or set_mask;
  • clear: result <= input and not clear_mask; clear: result <= input and not clear_mask;

This can be combined to a bit override operation: 可以将其组合为位覆盖操作:

  • override: result <= (input and not override_mask) or override_value; 覆盖: result <= (input and not override_mask) or override_value;
  • secure override result <= (input and not override_mask) or (override_value and override_mask); 安全覆盖result <= (input and not override_mask) or (override_value and override_mask);

The latter must be used if you can not assume that override_value has only bits set within the range of override_mask. 如果您不能假定override_value仅在override_mask范围内设置了位,则必须使用后者。

The next step is to move T_square to the right position. 下一步是将T_square移到正确的位置。 Shifting bits in a fast way can be done by a barrel-shifter or a multiplier (DSP block). 可以通过桶形移位器或乘法器(DSP模块)来快速移位位。 Because your vector has 40 bits, a barrel-shifter is faster then a DSP block. 由于向量具有40位,因此桶形移位器比DSP块更快。

A barrel shifter of 64 bits has a 6 bit shift_value input. 64位的桶形移位器具有6位的shift_value输入。 Each bit of the input specifies if the value should be shifted by a power of two. 输入的每一位都指定该值是否应移位2的幂。

entity arith_BarrelShifter is
  generic (
    BITS            : POSITIVE      := 32
  );
  port (
    Input           : in    STD_LOGIC_VECTOR(BITS - 1 downto 0);
    ShiftAmount     : in    STD_LOGIC_VECTOR(log2ceilnz(BITS) - 1 downto 0);
    Output          : out   STD_LOGIC_VECTOR(BITS - 1 downto 0)
  );
end;

architecture rtl of arith_BarrelShifter is
  constant STAGES       : POSITIVE      := log2ceilnz(BITS);

  subtype   T_INTERMEDIATE_RESULT is STD_LOGIC_VECTOR(BITS - 1 downto 0);
  type  T_INTERMEDIATE_VECTOR is array (NATURAL range <>) of T_INTERMEDIATE_RESULT;

  signal IntermediateResults    : T_INTERMEDIATE_VECTOR(STAGES downto 0);

begin
  IntermediateResults(0)    <= Input;
  Output                    <= IntermediateResults(STAGES);

  for i in 0 to STAGES - 1 generate
    process(IntermediateResults(i), ShiftRotate, LeftRight, ArithmeticLogic)
    begin
      if (ShiftAmount(i) = '0') then
        IntermediateResults(i + 1) <= IntermediateResults(i);
      else
        IntermediateResults(i + 1) <= IntermediateResults(i)((BITS - i**2 - 1) downto 0) & ((i**2 - 1) downto 0 => '0');                                                        -- SLA, SLL
      end if;
    end process;
  end generate;
end;

So now we can combine all steps: 现在,我们可以结合所有步骤:

override_value <= (39 downto 3 => '0') & (2 downto 0 => T_square);
override_mask  <= (39 downto 3 => '0') & (2 downto 0 => '1');

shift_value : entity PoC.arith_BarrelShifter
  generic map (
    BITS        => 40
  )
  port map (
    Input       => override_value,
    ShiftAmount => T_left_most,
    Output      => shifted_value
  );

shift_mask : entity PoC.arith_BarrelShifter
  generic map (
    BITS        => 40
  )
  port map (
    Input       => override_mask,
    ShiftAmount => T_left_most,
    Output      => shifted_mask
  );

--           clear bits from source   / set bits from value
dataIn <= (dataOut and not shifted_mask) or shifted_value;

I hope I made no mistakes :) 我希望我没有犯错:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM