0

uart トランスミッタ用の一般的なボー レート ジェネレータ プロセスを構築しようとしています。

ボーレート分周器を無視して感度リストに clk 信号を渡すと、トランスミッタは正常に動作します。しかし、仕切りを実装しようとすると、エラーが発生します (コード コメントに記述)。2 つの異なる方法を試しましたが、どちらもエラーが発生したか、期待どおりの出力が得られませんでした。はい、fbaud を 2 回割り当てるため、投稿された正確なコードは機能しません。1 つをコメントアウトしてテストします。

おそらく、ボージェネレーターがどのように機能するのか理解していません。私の理解では、fpga クロックは 50mHz で動作しますが、これは rs232 通信には速すぎます。そのため、キャラクターを送信する前に、特定の数のクロック サイクルを待機する必要があります。

この場合、可変ボーがあるので、ストック クロックをボー ジェネレータで割って、「ティック」信号を送信ステート マシンに送信する前に待機する必要があるクロック サイクル数を取得します。

ボー ディバイダは、テストベンチで x"000008" に設定されています。


-- Universal Asynch Receiver Transmitter
---------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity eds_uart is
   generic (width : positive := 16);
   port ( clk,reset: in std_logic ;
     din_wen: in std_logic; -- state machine sets value thus buffer needed
     brd : in std_logic_vector(23 downto 0); -- buad rate dividor
     din : in std_logic_vector(7 downto 0); -- input value
     txd: out std_logic; -- sent data bit
     tx_busy : buffer std_logic -- sent data bit active
     );
end entity eds_uart;

architecture behaviour of eds_uart is
    type state_type is (idle_s, wait_s, transmit_s);  -- three possible states of uat
    signal current_s: state_type; 
    signal tick: std_logic := '0'; -- baud rate clock
    signal count: integer := 0; -- count number of characters sent
    signal shift: std_logic_vector(9 downto 0); -- intermediate vector to be shifted
    signal fbaud: integer := 0;
    signal fbaud_counter: integer := 0;

begin
   --- process that is causing the issue. 
   process(clk, brd) begin
      fbaud <= (50000000)/to_integer(signed(brd)); -- 50,000,000 is the default clock Hz
      ------ error message  ------
      --# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
      -- # Time: 0 ns  Iteration: 0  Instance: /eds_uart_tb/inst_uart
      -- # ** Fatal: (SIGFPE) Floating point exception.
      --#    Time: 0 ns  Iteration: 0  Process: /eds_uart_tb/inst_uart/line__29 File: 

      fbaud <= 50000;
      --- error ---
      -- this command simply does not work, it compiles and runs though
      -- I don't get any transitions in my output wave
      -- I don't think it is entering the transmit stage based on a clock signal

      if (rising_edge(clk)) then
         if (fbaud_counter = fbaud) then -- tick when proper number of counts have appeared
             tick <= '1';
         elsif (fbaud_counter < fbaud) then
             tick <= '0';
             fbaud_counter <= fbaud_counter + 1;
         end if;
      end if;
   end process; 

   process(tick, reset, din) begin 
       if (reset = '1') then
           current_s <= idle_s; -- default state
           count <= 0; -- reset character counter
           txd <= '1'; 
           tx_busy <= '0'; 
       elsif (current_s = idle_s and din_wen = '1') then -- transition when write enable is high
           current_s <= wait_s; -- transition
           tx_busy <= '1';  
           shift <= '1' & din & '0'; -- init shift value
       end if;
       if(rising_edge(tick)) then
          if (current_s = wait_s) then -- transition on clock signal
               current_s <= transmit_s;
          elsif (current_s = transmit_s) then -- transition on clock signal
               if (count < 9) then
                   txd <= shift(0); -- output value
                   shift <= '0' & shift(9 downto 1); -- shift to next value
                   count <= count + 1; -- increment counter
                   current_s <= transmit_s; -- dont change state
               elsif (count = 9) then 
                   txd <= shift(0); -- send last element
                   count <= 0;
                   tx_busy <= '0'; -- reset busy signal
                   current_s <= idle_s; -- start process again
              end if;
          end if;
      end if;
   end process;
end architecture behaviour ;
4

2 に答える 2