0

これは一般的な FPGA 設計の質問です。私は FPGA 設計は初めてで、最初の大規模なプロジェクトに着手したばかりで、優れた線形代数ソルバーを構築しています。システムはかなり大きいので、最初に正しく理解することが重要です。

シミュレーションが成功した後、私は現在合成していますが、悪夢に見舞われています。シミュレーションでのように動作するものは何もないため、コンポーネントごとにビルドしてテストする必要があります! 私は主に、出力が同期されていないステート マシンに問題があります。たとえば、これは私が使用しているデータ ローダーです。

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、および正しいデータが同期していることですが、合成では、addr と wr_en がデータと同期されておらず、前のものから半分を読み取ることがわかり続けています。前の状態から半分。

VHDL をより合成しやすいものにするには、どのようなデザイン プラクティスを使用する必要がありますか?

どうもありがとうサム

4

1 に答える 1

0

動作中のデザインでは、古いデザインでは、別のモジュールからアサートされた d_ready 信号とこのモジュール clk の間のスキューが発生していました。そのため、最初に期待したように同期されない変更があります。これを修正するには、ローカル同期信号 d_tick をアサートする d_tick_next 信号で、すべての正しい動作を可能にしました。学んだ教訓の 1 つ (間違っていたら訂正してください) は、受信モジュール clk と同期するために、想定される外部クロック信号 (d_ready など) に依存できないということです。

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;

行動を終了します。

于 2013-07-25T10:09:05.633 に答える