【问题标题】:VHDL - My code is synthesizable and works the way i want on simulation, but it doesn't on the fpgaVHDL - 我的代码是可合成的,并且在模拟中按照我想要的方式工作,但它不在 fpga 上
【发布时间】:2017-12-16 13:15:34
【问题描述】:

我的 VHDL 代码在功能上是正确的,在模拟中它可以达到预期的效果。我测试了许多变体,代码工作正常。

但是当我对 fpga (Nexyx 4 ddr) 进行编程时,除了计数器的预加载之外,一切都运行良好。

我不知道 fsm 的负载启用 (load_e) 输出是否没有到达计数器,或者表示计数器的输出信号是否已加载 (counter_loaded) 没有到达 fsm,但是当我对fpga 它永远不会从状态 C 或 D(等待计数器加载)过渡到状态 E 或 F(它会进行倒计时)。

我测试了目标中代码的其他部分,它工作正常,所以到目前为止唯一的问题是那个我找不到错误,我正在考虑计时,但我不知道如何解决。

我将计数器和 fsm 代码以及 TOP 代码留在这里,我是 VHDL 新手,可能有很多不好的实践错误。

我是西班牙人,这是我英语不好的原因,也是一些信号的西班牙名称,但我在它们旁边添加了评论。

--------COUNTER---------------------------------------

entity counter is
Generic (NBITS    : positive := 15
        );
Port    (clk      : in STD_LOGIC;
        rst      : in STD_LOGIC;
        ce       : in STD_LOGIC;
        load     : in STD_LOGIC_VECTOR (NBITS-1 downto 0);
        load_e   : in STD_LOGIC;
        unit     : out STD_LOGIC_VECTOR(3 downto 0); 
        dec      : out STD_LOGIC_VECTOR(3 downto 0); 
        zero_n   : out STD_LOGIC;                   --true si cuenta = 0
        loaded   : out STD_LOGIC);
end counter;

architecture Behavioral of counter is
signal q_i : unsigned (NBITS-1 downto 0) := (others => '1');
begin  
    process(clk,rst)
        begin
            if rst = '1'    then
                q_i <= (OTHERS => '1');
                loaded <= '0';
            elsif rising_edge(clk)  then
                if CE = '1' then
                    if load_e = '1' then             --ONE OF MY GUESSES OF THE PROBLEM
                        q_i <= unsigned(load);
                        loaded <= '1';
                    else
                        q_i <= q_i - 1;
                        loaded <= '0';                        
                    end if;
                end if;
            end if;              
        end process;     
    dec <= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) / 10),dec'length));      --first 5 bits are the tens        
    unit <= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) rem 10),unit'length));  --fist 5 bits are the unit
    zero_n <= '1' WHEN q_i < "000010000000000" ELSE '0';        --cout is zero if the first 5 bits are less tan 1 in binary
end Behavioral;

------FINITE STATE MACHINE--------------------------------

entity maquina_estados is
Port ( 
    clk : in STD_LOGIC;
    rst : in STD_LOGIC;
    corto : in STD_LOGIC;
    largo : in STD_LOGIC;
    b_on : in STD_LOGIC;
    zero_n : in STD_LOGIC;
    counter_loaded : in STD_LOGIC;
    load_e : out STD_LOGIC;
    load : out STD_LOGIC_VECTOR(14 downto 0);
    bomba_led : out STD_LOGIC;
    indica_on : out STD_LOGIC);
end maquina_estados;

architecture Behavioral of maquina_estados is

type state_type is (A, B, C, D, E, F);  --define state(A = powered off, B = powered on, C = short coffee preload, D = large coffee preload, E = short coffee, F = large coffee)

signal state, next_state : state_type;  --type state signal

begin 
    process(clk,rst)
        begin
            if rst = '1' then
                state <= A;
            elsif rising_edge(clk) then
                state <= next_state;
            end if;
    end process;

    process(state, b_on, corto, largo, zero_n, counter_loaded)
        begin
            CASE state IS
                WHEN A =>   if b_on = '1' then
                                next_state <= B;
                            else
                                next_state <= A;
                            end if;
                WHEN B =>   if b_on = '0' then
                                next_state <= A;
                            elsif corto = '1' then
                                next_state <= C;
                            elsif largo = '1' then
                                next_state <= D;
                            else
                                next_state <= B;
                            end if;
                WHEN C =>   if counter_loaded = '1' then
                                next_state <= E;
                            else
                                next_state <= C;
                            end if;
                WHEN D =>   if counter_loaded = '1' then
                                next_state <= F;
                            else
                                next_state <= D;
                            end if;
                WHEN E =>   if zero_n = '1' then
                                next_state <= B;
                            else
                                next_state <= E;
                            end if;
                WHEN F =>   if zero_n = '1' then
                                next_state <= B;
                            else
                                next_state <= F;
                            end if;
                WHEN OTHERS => next_state <= A;
            end case;
    end process;

    process(state)
        begin
            CASE state IS
                WHEN A =>   load        <= "111111111111111";  --default value of the count 
                            load_e      <= '0';
                            bomba_led   <= '0';
                            indica_on   <= '0';
                WHEN B =>   load        <= "111111111111111";
                            load_e      <= '0';
                            bomba_led   <= '0';
                            indica_on   <= '1';
                WHEN C =>   load        <= "010101111111111";  --10 second, this in addition to a 1024 hz clock made posible to use the first 5 bits as the number
                            load_e      <= '1';
                            bomba_led   <= '0';
                            indica_on   <= '1';
                WHEN D =>   load        <= "101001111111111";  --20 seconds
                            load_e      <= '1';
                            bomba_led   <= '0';
                            indica_on   <= '1';
                WHEN E =>   load        <= "111111111111111";
                            load_e      <= '0';
                            bomba_led   <= '1';
                            indica_on   <= '1';
                WHEN F =>   load        <= "111111111111111";
                            load_e      <= '0';
                            bomba_led   <= '1';
                            indica_on   <= '1';
            end case;
    end process;
end behavioral;

------TOP-----------------------

entity TOP is
Generic(
FIN     : positive := 100000000;
FOUT    : positive := 1024);
Port ( clk : in STD_LOGIC;
       rst : in STD_LOGIC;
       corto : in STD_LOGIC;
       largo : in STD_LOGIC;
       b_on : in STD_LOGIC;
       display_number : out STD_LOGIC_VECTOR (6 downto 0);
       display_selection : out STD_LOGIC_VECTOR (7 downto 0);
       bomba_led : out STD_LOGIC;
       indica_on : out STD_LOGIC);
end TOP;

architecture Behavioral of TOP is



  --instancies

  component clk_divider is
   --  Port ( );
   generic(
FIN     :   positive;
FOUT    :   positive
);
port ( 
Clk     :   in STD_LOGIC;
Reset   :   in STD_LOGIC;
Clk_out :   out STD_LOGIC
);
end component;


component maquina_estados is
Port ( clk : in STD_LOGIC;
       rst : in STD_LOGIC;
       corto : in STD_LOGIC;
       largo : in STD_LOGIC;
       b_on : in STD_LOGIC;
       zero_n : in STD_LOGIC;
       counter_loaded : in STD_LOGIC;
       load_e : out STD_LOGIC;
       load : out STD_LOGIC_VECTOR(14 downto 0);
       bomba_led : out STD_LOGIC;
       indica_on : out STD_LOGIC);
end component;

component counter is
Generic (NBITS    : positive
        );
Port    (clk      : in STD_LOGIC;
        rst      : in STD_LOGIC;
        ce       : in STD_LOGIC;
        load     : in STD_LOGIC_VECTOR (NBITS-1 downto 0);
        load_e   : in STD_LOGIC;
        unit     : out STD_LOGIC_VECTOR(3 downto 0); 
        dec      : out STD_LOGIC_VECTOR(3 downto 0); 
        zero_n   : out STD_LOGIC;                   
        loaded   : out STD_LOGIC);
end component;


component clk_manager is
generic(
CLK_FREQ : positive
);
Port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
strobe_1024Hz : out STD_LOGIC;
strobe_128Hz : out STD_LOGIC
);
end component;

component decoder is
Port ( code : in STD_LOGIC_VECTOR(3 downto 0);
       led : out STD_LOGIC_vector(6 downto 0)
      );
end component;

component display_refresh is
Port ( clk                  : in STD_LOGIC;
       ce                   : in STD_LOGIC;
       segment_unit         : in STD_LOGIC_VECTOR (6 downto 0);
       segment_dec          : in STD_LOGIC_VECTOR (6 downto 0);
       display_number       : out STD_LOGIC_VECTOR (6 downto 0);
       display_selection    : out STD_LOGIC_VECTOR (1 downto 0));   --cada elemento del vector corresponde a un 7 seg, true se ve false no
end component;                                                   


-- prescaler signals

signal prescaler_clk_out : STD_LOGIC;

--maquina estados signals
signal zero_n_fsm : STD_LOGIC;
signal load_e_fsm : STD_LOGIC;
signal load_fsm : STD_LOGIC_VECTOR(14 downto 0);
signal bomba_led_fsm: STD_LOGIC;
--counter signals
signal unit : STD_LOGIC_VECTOR(3 downto 0); 
signal dec      : STD_LOGIC_VECTOR(3 downto 0); 
signal zero_n_cntr : STD_LOGIC;
signal load_e_cntr : STD_LOGIC;
signal load_cntr : STD_LOGIC_VECTOR(14 downto 0);
signal counter_loaded : STD_LOGIC;
--clk_manager signals
signal strobe_1024Hz : STD_LOGIC;
signal strobe_128Hz : STD_LOGIC;

signal ce_clkm : STD_LOGIC;
signal rst_clkm : STD_LOGIC;

--decoders signals

signal unit_code : STD_LOGIC_VECTOR(6 downto 0);
signal dec_code : STD_LOGIC_VECTOR(6 downto 0);

--display refresh signals

signal display_refresh_number : STD_LOGIC_VECTOR(6 downto 0);
signal display_refresh_selection : STD_LOGIC_VECTOR(1 downto 0); 

begin

prescaler: clk_divider
    generic map(
    FIN     =>   FIN,
    FOUT    =>   FOUT
    )
    port map( 
    Clk     =>   clk,
    Reset   =>   rst,
    Clk_out =>   prescaler_clk_out
    ); 

sm: maquina_estados
    Port map( clk => prescaler_clk_out,
           rst => rst,
           corto => corto,
           largo => largo,
           b_on => b_on,
           zero_n => zero_n_fsm,
           counter_loaded => counter_loaded,
           load_e => load_e_fsm,
           load => load_fsm,
           bomba_led => bomba_led_fsm,
           indica_on => indica_on);

cntr: counter 
Generic map(NBITS    => 15
        )
Port map(clk      => clk,
        rst      => rst,
        ce       => strobe_1024Hz,
        load     => load_cntr,
        load_e   => load_e_fsm,
        unit     => unit,
        dec      => dec,
        zero_n   => zero_n_cntr,                 
        loaded   => counter_loaded);

   clk_m: clk_manager 
       generic map(
       CLK_FREQ => FIN
       )
       Port map(
       clk => clk,        
       rst => rst,
       strobe_1024Hz => strobe_1024Hz,
       strobe_128Hz => strobe_128Hz
       ); 

   unit_dcd: decoder 
       Port map( 
       code => unit,
       led => unit_code
       );

    dec_dcd: decoder 
      Port map( 
      code => dec,
      led => dec_code
      );

    dr: display_refresh 
     Port map(
     clk                  => clk,       
     ce                   => strobe_128Hz,
     segment_unit         => unit_code,
     segment_dec          => dec_code,
     display_number       => display_refresh_number,
     display_selection    => display_refresh_selection);   


    display_number <= display_refresh_number WHEN bomba_led_fsm = '1' ELSE "1111111";
    display_selection <= ("111111" & display_refresh_selection) WHEN bomba_led_fsm = '1' ELSE "11111111";
    zero_n_fsm <= zero_n_cntr;
    bomba_led <= bomba_led_fsm;
    load_cntr <= load_fsm;      
end Behavioral;

以下是实施和综合给我的所有报告:

Synthesis reports

implementation reports 1/6

implementation reports 2/6

implementation reports 3/6

implementation reports 4/6

implementation reports 5/6

implementation reports 6/6

我希望有人能找到问题并给我一个解决方案或如何调试这个问题的方法。

谢谢。

【问题讨论】:

  • 有合成消息吗?用户指南 901 Vivado 综合将告诉您 rem(在 unit &lt;= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) rem 10),unit'length)); 中)仅在右操作数是 2 的恒定幂时才受支持。(VHDL 构造支持状态)。你暗示除以 10 来找到余数(你可以在这里使用无符号数学而不是转换为整数)。 “/” (dec &lt;= std_logic_vector(to_unsigned((to_integer(q_i(14 downto 10)) / 10),dec'length));) 也一样。两个操作数都不是常数(在分析时不计算表达式)。
  • 你的代码几乎看不懂:(1)缩进损坏; (2) 使用 FSM 状态的专有名称而不是字母; (3) 不要使用像010101111111111 这样的幻数,(4) 尽量减少您的 FSM 重置条件; (5) 使用case语句来区分FSM状态; (6) 不支持时钟门控 (b_on = '1'),正如您在 VHDL 中描述的那样——您需要另一个描述; (7) FSM无启动状态; (8) 组合划分需要大量的硬件资源; (9) 标识符如果不是英文的,其他人是无法理解的。
  • (10) 不建议对 FPGA 设计进行异步复位; (11) 简化indica_on 的表达,以便人们理解
  • @Paebbels,首先感谢您的回复。我用你的建议修改了 FSM,我不能修改州名和其他标识符,因为我需要它们成为女巫日。如果您对我的问题的可能解决方案有任何想法或任何其他建议,请告诉我。
  • @user1155120 感谢您的回复。我编辑了帖子,更改了 fsm 并添加了 vivado 给我的报告的图像,如果您有任何解决方案的想法,请告诉我。

标签: vhdl fpga


【解决方案1】:

您的 FSM 的时钟频率为 prescaler_clk_out,而您的计数器的时钟频率为 clk,这是一个危险信号。这很容易导致实施失败。

  • 绘制一个时序图,显示您的所有时钟和复位,以及您的较低频率启用(特别是strobe_1024Hz
  • 尝试在同一个时钟(大概是clk)上为所有逻辑提供时钟,并确保一切都与此时钟同步(换句话说,输入相对于此时钟有足够的建立和保持时间)
  • 确保您确实在重置芯片

完成时序图后,编写一个约束文件,告诉合成器您的时钟是什么。 clk_managerclk_divider 在这里可能是个问题,但希望一切都将在“clk”上计时,并且约束文件将仅包含时钟名称和频率。如果您仍然无法使其工作,请提出一个新问题,显示您的时序图以及您对约束文件的尝试。

【讨论】:

  • 完美,我会修改代码并做时序图。如果无法解决,我会再问谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多