Serial port VHDL RS232接收器在Xilinx ISE中工作不正常

Serial port VHDL RS232接收器在Xilinx ISE中工作不正常,serial-port,vhdl,Serial Port,Vhdl,所以我有RS232通信链路的接收器代码,我应该发送8位,1个起始位为“0”,1个停止位为“1”,没有奇偶校验位,我用了很多种方法尝试了这些代码,但模拟从来没有正确工作过,尽管有人告诉我,我的问题是测试台而不是代码,但它在FPGA实现上永远不起作用,但我发送的第一个信号总是错误的,因为之后的任何信号都是正确的 下面是代码 entity Rs232Rxd is port( Reset, Clock16x, Rxd: in std_logic; DataO

所以我有RS232通信链路的接收器代码,我应该发送8位,1个起始位为“0”,1个停止位为“1”,没有奇偶校验位,我用了很多种方法尝试了这些代码,但模拟从来没有正确工作过,尽管有人告诉我,我的问题是测试台而不是代码,但它在FPGA实现上永远不起作用,但我发送的第一个信号总是错误的,因为之后的任何信号都是正确的

下面是代码

    entity Rs232Rxd is

        port( Reset, Clock16x, Rxd: in std_logic; 

        DataOut1: out std_logic_vector (7 downto 0));

        end Rs232Rxd;

 architecture Rs232Rxd_Arch of Rs232Rxd is 

attribute enum_encoding: string;

-- state definitions

type stateType is (stIdle, stData, stStop, stRxdCompleted);

attribute enum_encoding of statetype: type is "00 01 11 10";

signal iReset : std_logic;

signal iRxd1, iRxd2 : std_logic := '1';

signal presState: stateType; 

signal nextState: stateType;

signal iClock1xEnable, iClock1x, iEnableDataOut: std_logic :='0' ; 

signal iClockDiv: std_logic_vector (3 downto 0) := (others=>'0') ;

signal iDataOut1, iShiftRegister: std_logic_vector (7 downto 0):= (others=>'0');

signal iNoBitsReceived: std_logic_vector (3 downto 0):= (others=>'0') ;

begin

process (Clock16x) begin

        if rising_edge(Clock16x) then 

            if Reset = '1' or iReset = '1' then

                iRxd1 <= '1';

                iRxd2 <= '1';

                iClock1xEnable <= '0'; 

                iClockDiv <= (others=>'0');

            else

                iRxd1 <= Rxd; 

                iRxd2 <= iRxd1;

            end if;

            if iRxd1 = '0' and iRxd2 = '1' then 

                iClock1xEnable <= '1';

            end if;

            if iClock1xEnable = '1' then

                iClockDiv <= iClockDiv + '1';

        end if;

        end if;

end process;


iClock1x <= iClockDiv(3);

process (iClock1xEnable, iClock1x) 

begin

    if iClock1xEnable = '0' then 

            iNoBitsReceived <= (others=>'0');

            presState <= stIdle;

    elsif rising_edge(iClock1x) then

                iNoBitsReceived <= iNoBitsReceived + '1';

                presState <= nextState;

                if iEnableDataOut = '1' then

                iDataOut1 <= iShiftRegister;

                --iShiftRegister <= (others=>'0');

                    else

                        iShiftRegister <= Rxd & iShiftRegister(7 downto 1);

            end if;
        end if;

end process;

DataOut1 <= iDataOut1;

process (presState, iClock1xEnable, iNoBitsReceived) 

begin

-- signal defaults 

iReset <= '0';

iEnableDataOut <= '0';


case presState is

    when stIdle =>

    if iClock1xEnable = '1' then

    nextState <= stData;

    else
        nextState <= stIdle;

    end if; 

    when stData =>

    if iNoBitsReceived = "1000" then

    iEnableDataOut <= '1';

    nextState <= stStop;

    else

    iEnableDataOut <= '0'; 

    nextState <= stData;

    end if; 
    when stStop =>   

    nextState <= stRxdCompleted; 

    when stRxdCompleted =>

    iReset <= '1';

    nextState <= stIdle;

    end case; 

end process;

end Rs232Rxd_Arch;
实体Rs232Rxd为
端口(复位,时钟16X,Rxd:在标准逻辑中;
DataOut1:out标准逻辑向量(7到0);
结束Rs232Rxd;
Rs232Rxd的架构Rs232Rxd
属性枚举编码:字符串;
--国家定义
类型stateType为(stIdle、stData、stStop、stRxdCompleted);
statetype的属性枚举编码:类型为“00 01 11 10”;
信号iReset:std_逻辑;
信号iRxd1,iRxd2:std_逻辑:='1';
信号压力状态:状态类型;
信号nextState:状态类型;
信号iClock1xEnable、iClock1x、IENABLEDATOUT:std_逻辑:='0';
信号iClockDiv:std_逻辑_向量(3到0):=(其他=>'0');
信号iDataOut1,iShiftRegister:std_逻辑_向量(7到0):=(其他=>'0');
接收到的信号位:标准逻辑向量(3到0):=(其他=>'0');
开始
进程(时钟16x)开始
如果上升沿(时钟16X),则
如果Reset='1'或iReset='1',则

iRxd1你的问题没有提出任何问题。如果不编写测试台,就无法复制问题,并且您的问题缺乏特殊性(“此处使用的信号”和“错误”是不精确的)

有一些观察结果

一个连续字符的停止位后跟一个开始位,不为状态strxdpompleted留下任何空间。此外,当iClock1xEnable无效时,iNoBitsReceived未设置为所有“0”,这意味着采样点不是由连续字符的起始位的下降沿确定的:

这是大写字母“a”,紧跟小写字母“a”,停止位紧跟第二个字符的开始位(这是合法的)

在第一个字符中,您可以看到起始位被计为字符位之一

您还可以看到,当启用无效时,位计数器不会重置,这将导致采样点漂移(并可能最终导致采样错误,具体取决于时钟差或传输失真以及缺少等同步采样点重置)

您还可以看到,在第一个字符的最后一个数据位中,PressState是stStop,而第二个字符是正确的。再近一点看,第一个字符的起始位出现在stData期间,而第二个字符则没有

当iClock1x停止时,状态数和状态转换存在一个基本问题

您不需要状态机,您有一个名为iNoBitsReceived的计数器,它可以存储所有状态,如果您还检测到帧错误,它的长度应足以容纳开始(可能还有停止)位

在没有单独状态机的情况下将操作绑定到特定计数,并在空闲时清除位计数器:

为我们提供了一些可以稍微降低复杂性的功能:

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

entity Rs232Rxd is
    port ( 
        Reset, 
        Clock16x, 
        Rxd:        in  std_logic; 
        DataOut1:   out std_logic_vector (7 downto 0)
    );
end entity Rs232Rxd;

architecture foo of Rs232Rxd is
    signal rxd1:                std_logic;
    signal rxd2:                std_logic;
    signal baudctr:             unsigned (3 downto 0);
    signal ctr16x:              unsigned (3 downto 0);
    signal enab1xstart:         std_logic;
    signal enable1x:            std_logic;
    signal ninthbit:            std_logic;
    signal sampleenab:          std_logic;
    signal shiftregister:       std_logic_vector(7 downto 0);

begin
CLOCK_DOMAIN:
    process (clock16x)
    begin
        if rising_edge(clock16x) then
            rxd1 <= rxd;
            rxd2 <= rxd1;
        end if;
    end process;

    enab1xstart <= not rxd1 and rxd2 and not enable1x;

ENABLE_1X:
    process (clock16x, reset)
    begin
        if reset = '1' then
            enable1x <= '0';
        elsif rising_edge(clock16x) then
            if enab1xstart = '1' then
                enable1x <= '1';
            elsif ninthbit = '1' then
                enable1x <= '0';
            end if;
        end if;
    end process;

SAMPLE_COUNTER:
    process (clock16x, reset, ninthbit)
    begin
        if reset = '1' or ninthbit = '1' then
            ctr16x <= (others => '0');   -- for simulation
        elsif rising_edge(clock16x) then
            if enab1xstart = '1' or enable1x = '1' then
                ctr16x <= ctr16x + 1;
            end if;
        end if;
    end process;

    sampleenab <= not ctr16x(3) and ctr16x(2) and ctr16x(1) and ctr16x(0);

BAUD_COUNTER:
    process (clock16x, reset)
    begin
        if reset = '1' then
            baudctr <= (others => '0');
        elsif rising_edge(clock16x) and sampleenab = '1' then
            if baudctr = 8 then
                baudctr <= (others => '0');
            else
                baudctr <= baudctr + 1;
            end if;
        end if;
    end process;

NINTH_BIT:  -- one clock16x period long, after baudctr changes 
    process (clock16x, reset)
    begin
        if reset = '1' then
            ninthbit <= '0';
        elsif rising_edge(clock16x) then
            ninthbit <= sampleenab and     baudctr(3) and not baudctr(2) and 
                                       not baudctr(1) and not baudctr(0);
        end if;
    end process;

SHIFT_REG:
    process (clock16x, reset)
    begin
        if reset = '1' then
            shiftregister <= (others => '0'); -- for pretty waveforms
        elsif rising_edge(clock16x) and sampleenab = '1' then
            shiftregister <= rxd2 & shiftregister(7 downto 1);
        end if;
    end process;

OUTREG:
    process (clock16x, reset)
    begin
        if reset = '1' then
            dataout1 <= (others => '0');
        elsif rising_edge(clock16x) and ninthbit = '1' then
            dataout1 <= shiftregister;
        end if;
    end process;

end architecture;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体Rs232Rxd为
港口(
重置,
时钟16X,
Rxd:标准逻辑中;
DataOut1:out标准逻辑向量(7到0)
);
终端实体Rs232Rxd;
Rs232Rxd的体系结构foo是
信号rxd1:std_逻辑;
信号rxd2:std_逻辑;
信号波特率:无符号(3至0);
信号ctr16x:无符号(3到0);
信号enab1xstart:std_逻辑;
信号启用1X:std_逻辑;
信号ninthbit:std_逻辑;
信号采样AB:std_逻辑;
信号移位寄存器:标准逻辑向量(7到0);
开始
时钟域:
进程(时钟16x)
开始
如果上升沿(时钟16X),则

rxd1你的问题没有提出任何问题。如果不编写测试台,就无法复制问题,并且您的问题缺乏特殊性(“此处使用的信号”和“错误”是不精确的)

有一些观察结果

一个连续字符的停止位后跟一个开始位,不为状态strxdpompleted留下任何空间。此外,当iClock1xEnable无效时,iNoBitsReceived未设置为所有“0”,这意味着采样点不是由连续字符的起始位的下降沿确定的:

这是大写字母“a”,紧跟小写字母“a”,停止位紧跟第二个字符的开始位(这是合法的)

在第一个字符中,您可以看到起始位被计为字符位之一

您还可以看到,当启用无效时,位计数器不会重置,这将导致采样点漂移(并可能最终导致采样错误,具体取决于时钟差或传输失真以及缺少等同步采样点重置)

您还可以看到,在第一个字符的最后一个数据位中,PressState是stStop,而第二个字符是正确的。再近一点看,第一个字符的起始位出现在stData期间,而第二个字符则没有

当iClock1x停止时,状态数和状态转换存在一个基本问题

您不需要状态机,您有一个名为iNoBitsReceived的计数器,它可以存储所有状态,如果您还检测到帧错误,它的长度应足以容纳开始(可能还有停止)位

在没有单独状态机的情况下将操作绑定到特定计数,并在空闲时清除位计数器:

给了我们一些使用较少c语言的东西
library ieee;
use ieee.std_logic_1164.all;

entity rs232rxd_tb is
end entity;

architecture foo of rs232rxd_tb is
    signal reset:       std_logic := '0';
    signal clock16x:    std_logic := '0';
    signal rxd:         std_logic := '1'; 
    signal dataout1:    std_logic_vector (7 downto 0);
begin
DUT:
    entity work.rs232rxd
        port map (
            reset => reset,
            clock16x => clock16x,
            rxd => rxd,
            dataout1 => dataout1
        );
CLOCK:
    process
    begin
        wait for 3.255 us;    -- 16X clock divided by 2, 9600 baud 104.16 us
        clock16x <= not clock16x;
        if now > 2.30 ms then
            wait;
        end if;
    end process;

   STIMULI:
    process
    begin
        wait for 6.51 us;
        reset <= '1';
        wait for 13.02 us;
        reset <= '0';
        wait for 13.02 us;
        wait for 40 us;
        rxd <= '0';
        wait for 104.16 us;  -- start bit
        rxd <= '1';
        wait for 104.16 us;  -- first data bit, bit 0 =  '1'
        rxd <= '0';
        wait for 104.16 us;  -- second data bit, bit 1 = '0'
        rxd <= '0';
        wait for 104.16 us;  -- third data bit, bit 2 = '0';
        wait for 104.16 us;  -- fourth data bit, bit 3 = '0';
        wait for 104.16 us;  -- fifth data bit, bit 4 = '0';
        wait for 104.16 us;  -- sixth data bit, bit 5 = '0';
        rxd <= '1';
        wait for 104.16 us;  -- seventh data bit, bit 6 = '1';
        rxd <= '0'; 
        wait for 104.16 us;  -- eigth data bit, bit 7 = '0';
        rxd <= '1'; 
        wait for 104.16 us;  -- stop bit ( = '1')
        --wait for 104.16 us;  -- idle 
        rxd <= '0';
        wait for 104.16 us;  -- start bit
        rxd <= '1';
        wait for 104.16 us;  -- first data bit, bit 0 =  '1'
        rxd <= '0';
        wait for 104.16 us;  -- second data bit, bit 1 = '0'
        rxd <= '0';
        wait for 104.16 us;  -- third data bit, bit 2 = '0';
        wait for 104.16 us;  -- fourth data bit, bit 3 = '0';
        wait for 104.16 us;  -- fifth data bit, bit 4 = '0';
        rxd <= '1';
        wait for 104.16 us;  -- sixth data bit, bit 5 = '1';
        wait for 104.16 us;  -- seventh data bit, bit 6 = '1';
        rxd <= '0'; 
        wait for 104.16 us;  -- eigth data bit, bit 7 = '0';
        rxd <= '1'; 
        wait for 104.16 us;  -- stop bit ( = '1')
        wait;
    end process;
end architecture;