首页 文章

VHDL状态机输出不同步

提问于
浏览
0

这是一个普遍的FPGA设计问题,我是FPGA设计的新手,刚刚开始了我的第一个大型项目,构建了一些不错的线性代数求解器 . 系统非常大,所以第一次正确使用非常重要 .

在成功模拟之后,我现在正在进行sythensizing,但是我有一个噩梦,我不得不逐个构建和测试它,因为它没有像在模拟中那样表现!我主要遇到输出未同步的状态机问题,例如这是我正在使用的数据加载器:

entity TriDiag_Data_Scheduler is
    generic( W : integer :=16;  
                AW : integer := 10 -- address width
                );
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC; --attatched to data finished
           d_ready : in  STD_LOGIC;
           din : in  STD_LOGIC_VECTOR (W-1 downto 0);
              wr_en : out STD_LOGIC_VECTOR (3 downto 0);
              dout_a, dout_b, dout_c, dout_y : out  STD_LOGIC_VECTOR (W-1 downto 0);
              addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;

architecture Behavioral of TriDiag_Data_Scheduler is

type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');

signal wr_en_next : std_logic_vector(3 downto 0);

--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');

begin

process(clk,rst)
begin
    if(clk'event and clk ='1') then
        state_pr <= state_next;
        d_buff_a <= d_buff_a_reg;
        d_buff_b <= d_buff_b_reg;
        d_buff_c <= d_buff_c_reg;
        d_buff_y <= d_buff_y_reg;

        addr_reg <= addr_next;
        wr_en <= wr_en_next;
    end if;

end process;

addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;


--Data out logic
process(state_pr, d_buff_a, d_buff_b, d_buff_c, d_buff_y, d_buff)
begin

    d_buff_a_reg <= d_buff_a;
    d_buff_b_reg <= d_buff_b;
    d_buff_c_reg <= d_buff_c;
    d_buff_y_reg <= d_buff_y;

    case state_pr is
        when a => --move data to a reg
            d_buff_a_reg <= d_buff;
        when b => --move data to b reg
            d_buff_b_reg <= d_buff;
        when c => --move data to c reg
            d_buff_c_reg <= d_buff;
        when y => 
            d_buff_y_reg <= d_buff;
    end case; 
end process;

--next state and addr logic
process(state_pr, d_ready, rst, din)
begin

    state_next <= state_pr;
    addr_next <= addr_reg;
    wr_en_next <= (others => '0');

if(rst = '1') then
    state_next <= a;
    addr_next <= (others =>'1');
    wr_en_next <= (others => '0');
elsif(d_ready = '1') then
--Read in the data to the buffer
    d_buff <= din;
--next state logic
    case state_pr is
        when a => --move data to a reg
            addr_next <= addr_reg + 1;
        --  d_buff_a_reg <= din;
            wr_en_next <= "0001";
            state_next <= b;
        when b => --move data to b reg
            wr_en_next <= "0010";
        --  d_buff_b_reg <= din;
            state_next <= c;
        when c => --move data to c reg
            wr_en_next <= "0100";
        --  d_buff_c_reg <= din;
            state_next <= y;
        when y => 
        --  d_buff_y_reg <= din;
            wr_en_next <= "1000";
            state_next <= a;
    end case; 
end if;
end process;
end Behavioral;

基本上,当通过UART模块接收数据时,其作业是加载到正确的存储器中(由write_en信号控制) . 问题在于,在我的所有设计中(这是修订版7),所有addr_out,wr_en和正确的数据都在syn中,但在综合中我一直发现addr和wr_en不与数据同步,并从前面读取一半和前一个州的一半 .

我应该使用哪些设计实践,以便我的VHDL更易于合成,因为按照这个速度,我将不得不重新编写我以前为每个组件所做的所有努力工作!

非常感谢Sam

1 回答

  • 0

    在工作设计中,旧设计遭受了从另一个模块断言的d_ready信号与此模块clk之间的偏差 . 因此,没有像第一个希望同步的变化 . 为了修复这个I但是在d_tick_next信号中,该信号断言本地同步信号d_tick,它允许所有正确的行为 . 学到的一个教训(如果我错了,请纠正我)是你不能依赖假设的外部时钟信号(例如d_ready)与接收模块clk同步 .

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use ieee.std_logic_unsigned.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;
    
    
    -- ////////////////////////////////////////////////////////////////////
    --Takes in the linear stream of data and builds up the memory structure
    
    --INPUT DATA MUST FOLLOW SEQUENCE [a b c] x = [y] (0 if a or c do not exist) rows 0 and N respectivly 
    --//////////////////////////////////////////////////////////////////////
    entity TriDiag_Data_Scheduler is
        generic( W : integer :=16;  
                    AW : integer := 10 -- address width
                    );
        Port ( clk : in  STD_LOGIC;
               rst : in  STD_LOGIC; --attatched to data finished
               d_ready : in  STD_LOGIC;
               din : in  STD_LOGIC_VECTOR (W-1 downto 0);
                  wr_en : out STD_LOGIC_VECTOR (3 downto 0);
                  dout_a, dout_b, dout_c, dout_y : out  STD_LOGIC_VECTOR (W-1 downto 0);
                  addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
    end TriDiag_Data_Scheduler;
    
    architecture Behavioral of TriDiag_Data_Scheduler is
    
    type state is (a,b,c,y);
    signal state_pr, state_next : state := y;
    signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
    
    signal wr_en_next : std_logic_vector(3 downto 0);
    
    signal d_tick, d_tick_next : std_logic;
    
    --data buffer
    signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
    signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
    
    begin
    
    process(clk,rst)
    begin
        if(clk'event and clk ='1') then
            state_pr <= state_next;
    
            d_buff_a <= d_buff_a_reg;
            d_buff_b <= d_buff_b_reg;
            d_buff_c <= d_buff_c_reg;
            d_buff_y <= d_buff_y_reg;
    
            d_tick <= d_tick_next;
    
            addr_reg <= addr_next;
            wr_en <= wr_en_next;
        end if;
    
    end process;
    
    addr_out <= addr_reg;
    dout_a <= d_buff_a;
    dout_b <= d_buff_b;
    dout_c <= d_buff_c;
    dout_y <= d_buff_y;
    
    
    --Data out logic
    process(state_pr,d_tick,rst)
    begin
    
        d_buff_a_reg <= d_buff_a;
        d_buff_b_reg <= d_buff_b;
        d_buff_c_reg <= d_buff_c;
        d_buff_y_reg <= d_buff_y;
    
        wr_en_next <= (others => '0');
    
    if(rst = '1') then
        addr_next <= (others =>'1');
    else
        addr_next <= addr_reg;
    end if;
    
    if(d_tick = '1') then
        case state_pr is
            when a => --move data to a reg
                d_buff_a_reg <= d_buff;
                addr_next <= addr_reg + 1;
                wr_en_next <= "0001";
            when b => --move data to b reg
                d_buff_b_reg <= d_buff;
                wr_en_next <= "0010";
            when c => --move data to c reg
                d_buff_c_reg <= d_buff;
                wr_en_next <= "0100";
            when y => 
                d_buff_y_reg <= d_buff;
                wr_en_next <= "1000";
        end case; 
    end if;
    end process;
    
    --next state and d_tick
    process(state_pr, d_ready, rst, din)
    begin
    
        state_next <= state_pr;
        d_tick_next <='0';
    
    if(rst = '1') then
        state_next <= y;
    elsif(d_ready = '1') then
    --Read in the data to the buffer
        d_buff <= din;
    -- set sync tick
        d_tick_next <= '1';
    --next state logic
        case state_pr is
            when a => 
                state_next <= b;
            when b => 
                state_next <= c;
            when c =>
                state_next <= y;
            when y => 
                state_next <= a;
        end case; 
    end if;
    end process;
    

    结束行为;

相关问题