2014-07-11 5 views
0

UART 송신기에 대한 일반적인 보오율 생성기 프로세스를 구축하려고합니다.Baud Rate Clock VHDL - 부동 소수점 예외 오류 및/또는 스타일 문제

전송률 분배기를 무시하고 민감도 목록의 clk 신호를 전달하면 송신기가 정상적으로 작동합니다. 하지만 구분선을 구현하려고하면 오류가 발생합니다 (코드 주석에 설명되어 있음). 나는 두 가지 다른 방법을 시도했는데 둘 다 오류를 주거나 예상 된 결과를 얻지 못했습니다. 네, fbaud를 두 번 할당했기 때문에 게시 된 정확한 코드는 작동하지 않습니다.

아마도 보오드 생성기가 어떻게 작동하는지 이해할 수 없습니다. 내 이해에서, FPGA 클럭 rs232 통신을위한 빠른 50mHz에서 실행됩니다. 그래서 우리는 우리의 성격을 전달하기 전에 일정한 클럭주기를 기다려야합니다.

이 경우 우리는 변수 보 (baud)을 가지고 있으므로 baud generator를 통해 주식 시계를 나눠서 송신 상태 머신에 'tick'신호를 보내기 전에 기다려야하는 클럭 사이클 수를 얻습니다.

baud divider는 테스트 벤치에서 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 ; 
+0

시험용 벤치도 함께 보여주십시오. metavalue detected warning은 일반적으로 브레드 입력이 테스트 벤치에서 제대로 구동되지 않는다는 것을 의미합니다 (적어도 시간 0은 아님). 또한, 클록 라우팅이나 MMCM/PLL을 사용하여 살펴 보는 것만으로는 회의 타이밍이 더 어려워 지므로 (시계 라우팅을 사용하지 않기 때문에) 이런 방식으로 시계를 생성하는 것은 나쁜 습관으로 간주됩니다. 또한 상태, tx_busy 및 시프트 플롭에서 비동기식 세트 및 재설정을 사용하는 것 같습니다. 이것이 심지어 합성을 허용한다면 하드웨어가 작동하는 방식과 일치하지 않기 때문에 나쁜 습관으로 간주됩니다. – QuantumRipple

답변

1

당신은이이 코드 몇 가지 잠재적 인 문제가있다,하지만 당신의 실패가 더 비판적으로 정수로하지만 지정되지 범위 제한으로 fbaud_counter를 선언하고있는 것입니다 야기 된 것으로 판단 귀하의 fbaud 카운트 값에 도달했을 때이를 지우지 않았습니다. 카운트에 도달 한 후에는 결코 값을 재설정하지 않으므로 다시 감싸기 전에 모든 2^32 값을 통해 계속 계산되어 fbaud과 다시 일치합니다. 어쨌든 범위 제한은 아마도 좋은 생각 일 수 있지만, 재설정하지 않으면 통신 속도가 올바르지 않습니다. 예를 들어 :

정말하지 그렇지 않으면 '0'tick을 설정하거나 수를 증가 싶어 조건이없는 한, 정말 거기에 elsif 조건에 대한 필요가 없다는 것을
if (rising_edge(clk)) then 
    if (fbaud_counter = fbaud - 1) then 
    tick <= '1'; 
    fbaud_counter <= 0; 
    else 
    tick <= '0'; 
    fbaud_counter <= fbaud_counter + 1; 
    end if; 
end if; 

참고. fbaud - 1도 계산에 유의하십시오. 0에서 시작하면 fbaud까지 계산하면 요금이 매우 약간 떨어질 수 있습니다.

편집 나는 과정에 권장 변경 사항으로 위의 시뮬레이션, 그리고 나는 txd에 응답 (뿐만 아니라 꾸준한 tick)을 얻었다. 충분히 오래 시뮬레이션하고 있습니까? 귀하의 코드가 50 MHz로 설정되어 있다고 가정하면 코드가 있어야한다고 나타내며, brdx"000008"으로 설정하면 엄청나게 느린 틱 속도 (8 Hz, 이상하게)가 발생합니다. 나는 조금 속도를 높이기 위해 분자를 5000으로 줄였습니다.

나는 또한 부동 소수점 예외 (가리키는 주셔서 감사)를 커버하지 않았다는 것을 깨닫는다.

경고는 오류에 대한 힌트입니다. "metavalue가 감지되어 0을 반환합니다." 경고는 to_integer이 1 또는 0으로 변환 할 수없는 값 (예 : 'X' 또는 다른 std_logic 값)을 변환하려고 시도하고 있음을 나타내며 물론 0으로 나눌 수 없습니다. 이는 초기화 문제 일 가능성이 큽니다 (치명적인 오류는 Time: 0 ns Iteration: 0라고 표시합니다). 테스트 벤치에서 처음에 brd은 어떻게 구동됩니까? 기본 값을 줄 수 있습니까? 그렇지 않다면이 조건을 다른 방법으로 경계해야합니다.

+0

나는 이해하지 못할까 두렵다. – user3120471

+0

너무 빨리 입력하고 편집 시간이 다되었습니다. fbaud - 1 라인을 추가하고 카운터를 다시 0으로 설정하려고 시도했지만 동일한 결과 - 전환 없음이 있습니다. 그리고 (50000000)/to_integer (signed (brd))를 사용하여 문제를 해결할 수있는 방법도 없습니다. 오류. – user3120471

+0

죄송합니다. 잠시 동안 오프라인 상태입니다. 당신 말이 맞아, 나는 첫 번째 오류를 언급하지 않았다. 나는 나의 대답을 업데이트하려고 노력할 것이다. 두 번째는 자극에 따라 달라질 수 있습니다. 다시 살펴 봐야합니다. – fru1tbat

0

입력이 초기화되지 않은 것처럼 들리면 U0으로 바뀌고 0으로 나누기 때문에 예외가 발생합니다.

또한,이 자원이 많다는 매우 큰 무언가를 합성하는 것이 큰 하드웨어에서 질문입니다 매 클럭 사이클을 계산하기 위해 당신은 요구하고있다

fbaud <= (50000000)/to_integer(signed(brd)); 

.

일반적인 방법은 터미널 카운트 (fbaud)를 입력으로 받아들이고 제어 소프트웨어가 값을 알아내는 것입니다. 또는 컴파일 할 때 상수로 계산하십시오. 얼마나 유연해야하는지에 따라 다릅니다.