VHDL(Xilinx工具链)I';I’我被“打倒”;“阵列修剪”;

VHDL(Xilinx工具链)I';I’我被“打倒”;“阵列修剪”;,vhdl,compiler-warnings,synthesis,Vhdl,Compiler Warnings,Synthesis,我有一个两个文件的VHDL项目,我有初学者的困难 它采用系统时钟,并使用30位时钟除法器(其中我只使用少量非连续位)来驱动基本串行端口模块(仅输出TX)模块周期性地吐出8位字符 似乎在合成过程中,优化器删除了许多基本信号,这是我没有预料到的 顶级文件“Glue.vhd”… library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use ieee.std_logic_unsigned.all; entity Glu

我有一个两个文件的VHDL项目,我有初学者的困难

它采用系统时钟,并使用30位时钟除法器(其中我只使用少量非连续位)来驱动基本串行端口模块(仅输出TX)模块周期性地吐出8位字符

似乎在合成过程中,优化器删除了许多基本信号,这是我没有预料到的

顶级文件“Glue.vhd”…

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

entity Glue is
    port(
        clk : in std_logic;
        tx  : out std_logic;
        LED : out std_logic_vector(1 downto 0)
        );
end entity Glue;

architecture behavioural of Glue is
    signal divider : unsigned(29 downto 0);
begin
    LED(1) <= '0';

    ser_tx : entity SerialTX
    port map (
            baud_clk => divider(12),
            byte_to_transmit => std_ulogic_vector(divider(29 downto 22)),
            poke => divider(20),
            busy => LED(0),
            serial_out => tx
            );

    clocker : process(clk)
    begin
        IF(rising_edge(clk)) then
            divider <= divider + 1;
        END IF;
    end process clocker;
end architecture behavioural;
IEEE库;
使用IEEE.std_logic_1164.all;
使用IEEE.numeric_std.all;
使用ieee.std_logic_unsigned.all;
实体胶是
港口(
clk:标准逻辑中;
tx:输出标准逻辑;
LED:输出标准逻辑向量(1到0)
);
末端实体胶;
胶水的建筑性能是
信号除法器:无符号(29至0);
开始
LED(1)分配器(12),
字节到传输=>标准逻辑向量(除法器(29到22)),
戳=>分隔器(20),
忙=>LED(0),
串行输出=>tx
);
时钟:进程(时钟)
开始
如果(上升沿(clk)),则

divider虽然user1155120在您应该指定库或进行组件绑定的意义上是正确的,但是您的工具显然找到了正确的实体,因为这就是优化逻辑的地方

第一件事,不要用

use IEEE.numeric_std.all;
use ieee.std_logic_unsigned.all;
一起。除处理旧代码外,您应该使用数字_std

真正的问题有两个方面:

  • 你没有初始化你的计数器变量,它也不正确
  • 您的输入数据永远不会进入并行加载移位寄存器,因此会被修剪
您希望计数器以什么值启动?IIRC,未初始化的整数类型将采用其范围内的最低有效值。然而,在任何情况下,最好明确开始。然而,实际上FPGA中没有整数,只有冷的、硬的触发器。0到10的范围使用至少4位,因此使用4个触发器。然而,从0到“-1”将下溢并环绕到15,而不是您可能期望的10。
internal_busy
是一个触发器,但也没有初始化。我之所以说是有意的,是因为它实际上是由
位计数器
异步重置的。这种异步重置本身是有问题的,几乎肯定不是您想要的:

busy_handler : process(poke) is -- <-- wrong sensitivity list
begin
    if(rising_edge(poke)) then
        internal_busy <= '1';
    end if;
    if(bit_counter = 0) then   -- <-- not clocked
        internal_busy <= '0';
    end if;
end process busy_handler;
如果没有这种逻辑,
bit\u buf
实际上将是
9'h000
(Xilinx工具假定的值——您没有给出任何值!)。这是以下几行试图告诉您的:

WARNING:Xst:1710 - FF/Latch <bit_buf_9> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_8> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_7> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_6> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_5> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_4> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_3> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_2> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_1> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_0> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
WARNING:Xst:1710 - FF/Latch <serial_out> (without init value) has a constant value of 0 in block <SerialTX>. This FF/Latch will be trimmed during the optimization process.
  • 字节到字节传输
    未使用且不是顶级块的一部分,它将不会被保留
  • 分频器(从29到22)
    连接到
    字节到发送
    。由于该端口将被移除,所以可以优化掉最后使用的触发器、
    除法器(20)
    之后的所有触发器
  • 时钟警告:

    WARNING:Route:455 - CLK Net:divider<20> may have excessive skew because     0 CLK pins and 1 NON_CLK pins failed to route using a CLK template.
    WARNING:Route:455 - CLK Net:divider<12> may have excessive skew because     0 CLK pins and 1 NON_CLK pins failed to route using a CLK template.
    
    总之,您应该按照Brian Drummond的建议,在合成之前编写一个测试台并模拟您的设计


    在编写实现之前编写测试台的一部分通常是有帮助的,因为这将迫使您在实际编写组件之前考虑组件的接口以及您期望它如何反应。

    而user1155120在您应该指定库或进行组件绑定的意义上是正确的,您的工具显然找到了正确的实体,因为这就是优化逻辑的地方

    第一件事,不要用

    use IEEE.numeric_std.all;
    use ieee.std_logic_unsigned.all;
    
    一起。除处理旧代码外,您应该使用数字_std

    真正的问题有两个方面:

    • 你没有初始化你的计数器变量,它也不正确
    • 您的输入数据永远不会进入并行加载移位寄存器,因此会被修剪
    您希望计数器以什么值启动?IIRC,未初始化的整数类型将采用其范围内的最低有效值。然而,在任何情况下,最好明确开始。然而,实际上FPGA中没有整数,只有冷的、硬的触发器。0到10的范围使用至少4位,因此使用4个触发器。然而,从0到“-1”将下溢并环绕到15,而不是您可能期望的10。
    internal_busy
    是一个触发器,但也没有初始化。我之所以说是有意的,是因为它实际上是由
    位计数器
    异步重置的。这种异步重置本身是有问题的,几乎肯定不是您想要的:

    busy_handler : process(poke) is -- <-- wrong sensitivity list
    begin
        if(rising_edge(poke)) then
            internal_busy <= '1';
        end if;
        if(bit_counter = 0) then   -- <-- not clocked
            internal_busy <= '0';
        end if;
    end process busy_handler;
    
    如果没有这种逻辑,
    bit\u buf
    实际上将是
    9'h000
    (Xilinx工具假定的值——您没有给出任何值!)。这是以下几行试图告诉您的:

    WARNING:Xst:1710 - FF/Latch <bit_buf_9> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_8> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_7> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_6> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_5> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_4> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_3> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_2> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_1> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1895 - Due to other FF/Latch trimming, FF/Latch <bit_buf_0> (without init value) has a constant value of 0 in block <ser_tx>. This FF/Latch will be trimmed during the optimization process.
    WARNING:Xst:1710 - FF/Latch <serial_out> (without init value) has a constant value of 0 in block <SerialTX>. This FF/Latch will be trimmed during the optimization process.
    
  • 字节到字节传输
    未使用且不是顶级块的一部分,它将不会被保留
  • 分频器(从29到22)
    连接到
    字节到发送
    。由于该端口将被移除,所以可以优化掉最后使用的触发器、
    除法器(20)
    之后的所有触发器
  • 时钟警告:

    WARNING:Route:455 - CLK Net:divider<20> may have excessive skew because     0 CLK pins and 1 NON_CLK pins failed to route using a CLK template.
    WARNING:Route:455 - CLK Net:divider<12> may have excessive skew because     0 CLK pins and 1 NON_CLK pins failed to route using a CLK template.
    
    总之,您应该按照Brian Drummond的建议,在合成之前编写一个测试台并模拟您的设计


    在编写实现之前编写测试台的一部分通常是有帮助的,因为这将迫使您在实际编写组件之前考虑组件的接口以及您期望它如何反应。

    您可以模拟您的设计,它处于复杂性的边缘,比猜测在FPGA中合成和加载时为什么不工作要容易得多。也可以制作

    可以去掉位计数器,因为您有一个10位位移位寄存器

    这样做的方式是,您设置一个默认模式,该模式被识别为“空”,并且
    clk_en_p: process (clk) is
    begin
    
    if (rising_edge(clk)) then
        if (clk_en = '1') then
            my_signal <= assignment;
        end if;
    end if;
    end process clk_en_p;
    
    library ieee;
    use ieee.std_logic_1164.all;
    -- use ieee.numeric_std.all;
    
    entity SerialTX is
        port (
            baud_clk:          in  std_logic;
            byte_to_transmit:  in  std_logic_vector(7 downto 0); -- before -2008
            poke:              in  std_logic;
            busy:              out std_logic;
            serial_out:        out std_logic
        );
    end entity SerialTX;
    
    architecture foo of SerialTX is
        -- signal bit_buf:         unsigned(9 downto 0);
        constant BB_IDLE:       std_logic_vector (9 downto 0) := "0000000001";
        signal bit_buf:         std_logic_vector (9 downto 0) := BB_IDLE;
        -- signal internal_busy:   std_logic;
        signal poke_reg:        std_logic_vector (0 to 2) := "000";
        signal start_tx:        std_logic;
    
        -- shared variable bit_counter:    integer range 0 to 10;
    begin
        -- busy <= internal_busy;
    poke_filt:
        process (baud_clk)  -- translate poke to baud_clk domain
        begin
            if rising_edge (baud_clk) then
                poke_reg <= poke & poke_reg (0 to 1);
            end if;
        end process;
    
        -- front edge of poke in baud_clk_domain:
        start_tx <= poke_reg(0) and poke_reg(1) and not poke_reg(2);
    
    -- busy_handler:
    --     process (poke) is
    --     begin
    --         if rising_edge (poke) then
    --             internal_busy <= '1';
    --         end if;
    --         if bit_counter = 0 then
    --             internal_busy <= '0';
    --         end if;
    --     end process busy_handler;
    
    busy_handler:  
        process (baud_clk)
        begin
            if rising_edge (baud_clk) then
                if start_tx = '1' and bit_buf = BB_IDLE then
                    busy <= '1';
                elsif bit_buf = BB_IDLE then
                    busy <= '0';
                end if;
            end if;
        end process;
    
    do_transmit:
        process (baud_clk)
        begin
            if rising_edge(baud_clk) then 
                if start_tx = '1'  and bit_buf = BB_IDLE then
                    bit_buf <=  '1' & byte_to_transmit & '0';
                elsif bit_buf /= BB_IDLE then
                    -- bit_buf <= bit_buf srl 1; 
                    -- srl UNDEFINED in package std_logic_1164
                    bit_buf <= '0' & bit_buf(9 downto 1); -- shift right one
                end if;                                   -- zero fill
            end if;
        end process;
    
    -- do_transmit:
    --     process (baud_clk)
    --     begin
    --         if rising_edge(baud_clk) then
    --             if internal_busy = '1' and bit_counter = 0 then
    --                 bit_counter := 10;
    --                 bit_buf <= unsigned ('1' & byte_to_transmit & '0');
    --             end if;
    --             serial_out <= bit_buf(0);
    --             bit_buf <= bit_buf srl 1;
    --             bit_counter := bit_counter - 1;
    --         end if;
    --     end process do_transmit;
    
        serial_out <= bit_buf(0); -- ADDED, no 11th flip flop
    
    end architecture;
    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    -- use ieee.std_logic_unsigned.all;
    
    entity Glue is
        port (
            clk:  in  std_logic;
            tx:   out std_logic;
            LED:  out std_logic_vector(1 downto 0)
        );
    end entity Glue;
    
    architecture behavioural of Glue is
        signal divider:  unsigned(29 downto 0) := (others => '0'); -- init val
    begin
        LED(1) <= '0';
    
    ser_tx:  
        entity work.SerialTX  -- ADDED work prefix to make selected name
            port map (
                baud_clk => divider(12),
             -- byte_to_transmit => std_ulogic_vector(divider(29 downto 22)),
                byte_to_transmit => std_logic_vector(divider(25 downto 18)),
                poke => divider(17), -- WAS divider(20), for simulation
                busy => LED(0),
                serial_out => tx
            );
    clocker:  
        process (clk)
        begin
            if rising_edge(clk) then
                divider <= divider + 1;
            end if;
        end process clocker;
    end architecture behavioural;
    
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity glue_tb is
    end entity;
    
    architecture fum of glue_tb is
        signal clk:     std_logic := '0';
        signal tx:      std_logic;
        signal led:     std_logic_vector(1 downto 0);
    begin
    DUT:
        entity work.glue
            port map (
                clk => clk,
                tx => tx,
                led => led
            );
    CLOCK:
        process
        begin
            wait for 10 ns;
            clk <= not clk;
            if now > 40 ms then
                wait;
            end if;
        end process;
    end architecture;
    
    architecture fum of SerialTX is
        constant BB_IDLE:       std_logic_vector (9 downto 0) := "0000000001";
        signal bit_buf:         std_logic_vector (9 downto 0) := BB_IDLE;
        signal poke_event:      std_logic := '0'; -- Added
        signal internal_busy:   std_logic := '0'; -- Re-Added
        signal poke_reg:        std_logic_vector (0 to 1) := "00";
        signal start_tx:        std_logic;
        signal end_event:       std_logic := '0'; -- Added
    begin
    
        busy <= poke_event xor end_event;  -- ADDED, was FF output
    
    pokeevent:
        process (poke)
        begin
            if rising_edge(poke) then
                poke_event <= not poke_event;
            end if;
        end process;
    poke_edge:
        process (baud_clk)  -- translate poke to baud_clk domain
        begin
            if rising_edge (baud_clk) then
                poke_reg <= poke_event & poke_reg (0);
            end if;
        end process;
    
        -- front edge of poke in baud_clk_domain:
        start_tx <= poke_reg(0) xor poke_reg(1); -- CHANGED, when not equal
    
    endevent:
        process (baud_clk)
        begin
            if rising_edge (baud_clk) then
                if internal_busy = '1' and bit_buf = BB_IDLE then
                    end_event <= not end_event;
                end if;
            end if;
        end process;
    
    busy_handler:  -- CHANGED
        process (baud_clk)
        begin
            if rising_edge (baud_clk) then
                if start_tx = '1' and bit_buf = BB_IDLE then
                    internal_busy <= '1';
                elsif bit_buf = BB_IDLE then
                    internal_busy <= '0';
                end if;
            end if;
        end process;
    
    do_transmit:
        process (baud_clk)
        begin
            if rising_edge(baud_clk) then 
                if start_tx = '1'  and bit_buf = BB_IDLE then
                    bit_buf <=  '1' & byte_to_transmit & '0';
                elsif bit_buf /= BB_IDLE then
                    bit_buf <= '0' & bit_buf(9 downto 1);
                end if;
            end if;
        end process;
    
        serial_out <= bit_buf(0);
    
    end architecture;
    
    architecture behavioural of Glue is
        signal divider:  unsigned(29 downto 0) := (others => '0'); -- init val
        signal poke:    std_logic := '0';  -- ADDED
    begin
        LED(1) <= '0';
    
        poke <= divider(17), '0' after 10 us;  -- ADDED
    ser_tx:  
        entity work.SerialTX  -- ADDED work prefix to make selected name
            port map (
                baud_clk => divider(12),
                -- byte_to_transmit => std_ulogic_vector(divider(29 downto 22)),
                byte_to_transmit => std_logic_vector(divider(25 downto 18)),-- sim
                poke => poke, -- WAS divider(20), for simulation
                busy => LED(0),
                serial_out => tx
            );