发送16个字符字符串的VHDL uart

发送16个字符字符串的VHDL uart,vhdl,xilinx,Vhdl,Xilinx,我必须在Xilinx上用vhdl做UART,它将发送16个字符的字符串。我写了这样的代码 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.numeric_std.ALL; entity uartByJackob is Port ( CLK, A, B, C : in STD_LOGIC; RESET : in STD_LOGIC;

我必须在Xilinx上用vhdl做UART,它将发送16个字符的字符串。我写了这样的代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;


entity uartByJackob is
    Port ( CLK, A, B, C : in  STD_LOGIC;
       RESET : in  STD_LOGIC;
       TxD, TxDOSC : out  STD_LOGIC);
end uartByJackob;

architecture Behavioral of uartByJackob is
    signal K: std_logic_vector(14 downto 0);
    signal Q: std_logic_vector(3 downto 0);
    signal CLK_Txd: std_logic;
    signal ENABLE: std_logic;
    signal QTxD: std_logic_vector(9 downto 0);
    signal DATA : STD_LOGIC_VECTOR(7 downto 0);


-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
        K <= K + 1;
        CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
        K <= K + 1;
        CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
        K <= K + 1;
        CLK_Txd <= K(14);
else
    K <= (others => '0');
    end if;
    end if;
end process;

--counter
process(CLK_Txd, RESET, ENABLE)
 begin
if(RESET = '1' and ENABLE = '0') then
    Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
    Q <= Q + 1;
end if;
end process;

--comparator
ENABLE <= '1' when (Q > 4) else '0';

--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is 
 when "0001" => DATA <= x"40";
 when "0010" => DATA <= x"41";
 when "0011" => DATA <= x"42";
 when "0100" => DATA <= x"43";
 when "0101" => DATA <= x"44";
 when "0110" => DATA <= x"45";
 when "0111" => DATA <= x"46";
 when "1000" => DATA <= x"47";
 when "1001" => DATA <= x"48";
 when "1010" => DATA <= x"49";
 when "1011" => DATA <= x"50";
 when "1100" => DATA <= x"51";
 when "1101" => DATA <= x"52";
 when "1110" => DATA <= x"53";
 when "1111" => DATA <= x"54";
 when others => DATA <= x"55";
end case;
end if;
end process;

--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
        QTxD <= DATA & "01";    
elsif rising_edge(CLK_Txd) then
    QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.STD_LOGIC_UNSIGNED.ALL;
使用ieee.numeric_std.ALL;
实体uartByJackob是
端口(时钟、A、B、C:标准逻辑中;
复位:在标准逻辑中;
TxD、TxDOSC:输出标准逻辑);
结束uartByJackob;
uartByJackob的架构是
信号K:标准逻辑向量(14至0);
信号Q:std_逻辑_向量(3到0);
信号时钟Txd:标准逻辑;
信号启用:std_逻辑;
信号QTxD:std_逻辑_向量(9到0);
信号数据:标准逻辑向量(7到0);
--时钟频率
开始
过程(时钟、复位)
开始
如果上升沿(CLK),则
如果(A='1'和K<10416),则
K

你能给我看一段代码吗斯特凡

提供到Adrian Adamcyzk的代码()的链接的全部目的是提供一个带有位(波特率)计数器和触发器的示例,用于控制一次发送消息

这是Jackob的修改版:

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

entity uartbyjackob is
    port ( 
        clk, a, b, c:   in  std_logic;
        reset:          in  std_logic;
        txd, txdosc:    out std_logic
    );
end entity uartbyjackob;

architecture foo of uartbyjackob is
    -- signal k:       unsigned(14 downto 0); -- FOR simulation
    -- note if k were used in simulation it would require initialization
    signal q:       unsigned (3 downto 0);   -- WAS std_logic_vector
    signal clk_txd: std_logic;
    signal enable:  std_logic;
    signal qtxd:    std_logic_vector(9 downto 0);
    -- signal data:    std_logic_vector(7 downto 0);
    -- added:
    signal bdcnt:   unsigned (3 downto 0);
    signal ldqtxd:  std_logic;
    signal davl:    std_logic;

    type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
    constant data:  data_lut := (
            x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
            x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
        );
    signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
    -- -- freq of clock  -- NOTE k never in known binary state for simulation
    -- process (clk, reset)
    -- begin
    --     if rising_edge(clk) then
    --         if a = '1' and k < 10416 then
    --                 k <= k + 1;
    --                 clk_txd <= k(13);
    --         elsif b = '1' and k < 5208 then
    --                 k <= k + 1;
    --                 clk_txd <= k(12);
    --         elsif c = '1' and k < 20832 then
    --                 k <= k + 1;
    --                 clk_txd <= k(14);
    --         else
    --             k <= (others => '0');
    --         end if;
    --     end if;
    -- end process;

    clk_txd <= clk;     -- SHORTENS SIMULATION

DAVL_FF:                -- DATA_AVAILABLE to send
    process (clk_txd, reset)
    begin
        if reset = '1' then
            davl <= '0'; 
        elsif rising_edge (clk_txd) then
            if q = 15 and bdcnt = 9 then  -- a JK FF equivalent
                davl <= '0';
            elsif q = 0 then
                davl <= '1';             -- one clock holderover from reset
            -- else
                -- davl <= davl;
            end if;
        end if;
    end process;

    -- process(clk_txd, reset, enable)
    --  begin
    -- if reset = '1' and enable = '0' then
    --     q <= "0000";
    -- elsif rising_edge(clk_txd) then
    --     q <= q + 1;
    -- end if;
    -- end process;

QCNT:
    process (clk_txd, reset)
    begin
        if reset = '1' then
            q <= (others => '0');
        elsif rising_edge (clk_txd) then
            if enable = '1' then
                q <= q + 1;
            end if;
        end if;
    end process;

BAUD_COUNTER:
    process (clk_txd, reset)
    begin
        if reset = '1' then
            bdcnt <= (others => '0');
        elsif rising_edge (clk_txd) then
            if davl = '0' or bdcnt = 9 then
                bdcnt <= (others => '0');  
            else 
                bdcnt <= bdcnt + 1;
            end if;
        end if;
    end process;

    -- comparator
    -- enable <= '1' when (q > 4) else '0';

    enable <= '1' when bdcnt = 9 and davl = '1'  and q /= 15 else
              '0'; 
    -- q latches at 15;

    ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
              '0';

    datalut <= data(to_integer(q));  -- FOR SIMULATION VISIBILITIY

    --transcoder
    -- process(q, clk_txd)
    -- begin
    --     if rising_edge(clk_txd) then
    --         case q is
    --             when "0001" => data <= x"40";
    --             when "0010" => data <= x"41";
    --             when "0011" => data <= x"42";
    --             when "0100" => data <= x"43";
    --             when "0101" => data <= x"44";
    --             when "0110" => data <= x"45";
    --             when "0111" => data <= x"46";
    --             when "1000" => data <= x"47";
    --             when "1001" => data <= x"48";
    --             when "1010" => data <= x"49";
    --             when "1011" => data <= x"50";
    --             when "1100" => data <= x"51";
    --             when "1101" => data <= x"52";
    --             when "1110" => data <= x"53";
    --             when "1111" => data <= x"54";
    --             when others => data <= x"55";
    --         end case;
    --     end if;
    -- end process;

    -- uart
    -- process (clk_txd, enable, data)
    -- begin
    --     if enable = '0' then
    --         qtxd <= data & "01";
    --     elsif rising_edge(clk_txd) then
    --         qtxd <= '1' & qtxd(9 downto 1);
    --     end if;
    -- end process;

TX_SHIFT_REG:
    process (clk_txd, reset)  -- shift regiseter Tx UART
    begin
        if reset = '1' then
            qtxd <= (others => '1');  -- output mark by default
        elsif rising_edge (clk_txd) then
            if  ldqtxd = '1' then
                qtxd <= '1' & data(to_integer(q)) & '0'; 
                 -- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
            else
                qtxd <= '1' & qtxd(9 downto 1); -- shift out;
            end if;
        end if;
    end process;

    txd <= qtxd(0);

    txdosc <= qtxd(0);

end architecture foo;

library ieee;
use ieee.std_logic_1164.all;

entity uartbyjackob_tb is
end entity;

architecture foo of uartbyjackob_tb is
    signal clk:     std_logic := '0';
    signal reset:   std_logic := '0';
    signal txd:     std_logic;
begin
    DUT:
    entity work.uartbyjackob
        port map ( 
            clk => clk, -- clk_txd driven by clk
            a   =>  'X', 
            b   => 'X', 
            c   => 'X',     -- a, b, c aren't used
            reset => reset,
            txd => txd,
            txdosc => open
        );
CLOCK:
    process
    begin
        wait for 52.35 us;
        clk <= not clk;
        if now > 20000 us then
            wait;
        end if;
    end process;
STIMULUS:
    process
    begin
        wait for 104.7 us;
        reset <= '1';
        wait for 104.7 us;
        reset <= '0';
        wait;
    end process;
end architecture;
告诉您在何处查找选定字符的数据位(q(7到0))。在以下波形中,q显示为十六进制以匹配:


通过修复,您会发现传输的第一个字符是0x40,第二个字符是0x41,…

如果您在Adrian Adamczyk中查找,那么您的实现中缺少一个额外的计数器(tx.vhd中的bitindex)。还有一个txstart触发器。他从未发布过答案,但指向pastebin的链接仍处于活动状态。他的字符串是31个字符(可以更改)。基本上,你不会对一个字符增加一次q,也不会对每个字符加载一次QTxD。因此,在你看来,我应该在同一个过程中增加q和QTxD,在case之后?不,你需要一个与用来查找输出字符的指针分开的计数器。你能给我看一段代码吗?
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity uartbyjackob is
    port ( 
        clk, a, b, c:   in  std_logic;
        reset:          in  std_logic;
        txd, txdosc:    out std_logic
    );
end entity uartbyjackob;

architecture foo of uartbyjackob is
    -- signal k:       unsigned(14 downto 0); -- FOR simulation
    -- note if k were used in simulation it would require initialization
    signal q:       unsigned (3 downto 0);   -- WAS std_logic_vector
    signal clk_txd: std_logic;
    signal enable:  std_logic;
    signal qtxd:    std_logic_vector(9 downto 0);
    -- signal data:    std_logic_vector(7 downto 0);
    -- added:
    signal bdcnt:   unsigned (3 downto 0);
    signal ldqtxd:  std_logic;
    signal davl:    std_logic;

    type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
    constant data:  data_lut := (
            x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
            x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
        );
    signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
    -- -- freq of clock  -- NOTE k never in known binary state for simulation
    -- process (clk, reset)
    -- begin
    --     if rising_edge(clk) then
    --         if a = '1' and k < 10416 then
    --                 k <= k + 1;
    --                 clk_txd <= k(13);
    --         elsif b = '1' and k < 5208 then
    --                 k <= k + 1;
    --                 clk_txd <= k(12);
    --         elsif c = '1' and k < 20832 then
    --                 k <= k + 1;
    --                 clk_txd <= k(14);
    --         else
    --             k <= (others => '0');
    --         end if;
    --     end if;
    -- end process;

    clk_txd <= clk;     -- SHORTENS SIMULATION

DAVL_FF:                -- DATA_AVAILABLE to send
    process (clk_txd, reset)
    begin
        if reset = '1' then
            davl <= '0'; 
        elsif rising_edge (clk_txd) then
            if q = 15 and bdcnt = 9 then  -- a JK FF equivalent
                davl <= '0';
            elsif q = 0 then
                davl <= '1';             -- one clock holderover from reset
            -- else
                -- davl <= davl;
            end if;
        end if;
    end process;

    -- process(clk_txd, reset, enable)
    --  begin
    -- if reset = '1' and enable = '0' then
    --     q <= "0000";
    -- elsif rising_edge(clk_txd) then
    --     q <= q + 1;
    -- end if;
    -- end process;

QCNT:
    process (clk_txd, reset)
    begin
        if reset = '1' then
            q <= (others => '0');
        elsif rising_edge (clk_txd) then
            if enable = '1' then
                q <= q + 1;
            end if;
        end if;
    end process;

BAUD_COUNTER:
    process (clk_txd, reset)
    begin
        if reset = '1' then
            bdcnt <= (others => '0');
        elsif rising_edge (clk_txd) then
            if davl = '0' or bdcnt = 9 then
                bdcnt <= (others => '0');  
            else 
                bdcnt <= bdcnt + 1;
            end if;
        end if;
    end process;

    -- comparator
    -- enable <= '1' when (q > 4) else '0';

    enable <= '1' when bdcnt = 9 and davl = '1'  and q /= 15 else
              '0'; 
    -- q latches at 15;

    ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
              '0';

    datalut <= data(to_integer(q));  -- FOR SIMULATION VISIBILITIY

    --transcoder
    -- process(q, clk_txd)
    -- begin
    --     if rising_edge(clk_txd) then
    --         case q is
    --             when "0001" => data <= x"40";
    --             when "0010" => data <= x"41";
    --             when "0011" => data <= x"42";
    --             when "0100" => data <= x"43";
    --             when "0101" => data <= x"44";
    --             when "0110" => data <= x"45";
    --             when "0111" => data <= x"46";
    --             when "1000" => data <= x"47";
    --             when "1001" => data <= x"48";
    --             when "1010" => data <= x"49";
    --             when "1011" => data <= x"50";
    --             when "1100" => data <= x"51";
    --             when "1101" => data <= x"52";
    --             when "1110" => data <= x"53";
    --             when "1111" => data <= x"54";
    --             when others => data <= x"55";
    --         end case;
    --     end if;
    -- end process;

    -- uart
    -- process (clk_txd, enable, data)
    -- begin
    --     if enable = '0' then
    --         qtxd <= data & "01";
    --     elsif rising_edge(clk_txd) then
    --         qtxd <= '1' & qtxd(9 downto 1);
    --     end if;
    -- end process;

TX_SHIFT_REG:
    process (clk_txd, reset)  -- shift regiseter Tx UART
    begin
        if reset = '1' then
            qtxd <= (others => '1');  -- output mark by default
        elsif rising_edge (clk_txd) then
            if  ldqtxd = '1' then
                qtxd <= '1' & data(to_integer(q)) & '0'; 
                 -- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
            else
                qtxd <= '1' & qtxd(9 downto 1); -- shift out;
            end if;
        end if;
    end process;

    txd <= qtxd(0);

    txdosc <= qtxd(0);

end architecture foo;

library ieee;
use ieee.std_logic_1164.all;

entity uartbyjackob_tb is
end entity;

architecture foo of uartbyjackob_tb is
    signal clk:     std_logic := '0';
    signal reset:   std_logic := '0';
    signal txd:     std_logic;
begin
    DUT:
    entity work.uartbyjackob
        port map ( 
            clk => clk, -- clk_txd driven by clk
            a   =>  'X', 
            b   => 'X', 
            c   => 'X',     -- a, b, c aren't used
            reset => reset,
            txd => txd,
            txdosc => open
        );
CLOCK:
    process
    begin
        wait for 52.35 us;
        clk <= not clk;
        if now > 20000 us then
            wait;
        end if;
    end process;
STIMULUS:
    process
    begin
        wait for 104.7 us;
        reset <= '1';
        wait for 104.7 us;
        reset <= '0';
        wait;
    end process;
end architecture;
architecture behavioral of uartbyjackob is
    -- signal k:    std_logic_vector(14 downto 0);
    signal q:       unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
    signal clk_txd: std_logic;
    signal enable:  std_logic;
    signal qtxd:    std_logic_vector(7 downto 0); 
    -- using an 8 bit shift register requires a method of outputting a 
    -- synchronous start bit (the width is important for receive framing)
    -- and synchronous stop bit
    signal data:    std_logic_vector(7 downto 0);
    signal qprim:   std_logic_vector(3 downto 0);
    signal clear:   std_logic;           -- synchronous clear for start bit

begin
    -- let's keep this here for when you put it the FPGA
    -- -- freq of clock  -- NOTE k never in known binary state for simulation
    -- process (clk, reset)
    -- begin
    --     if rising_edge(clk then
    --         if a = '1' and k < 10416 then
    --                 k <= k + 1;
    --                 clk_txd <= k(13);
    --         elsif b = '1' and k < 5208 then
    --                 k <= k + 1;
    --                 clk_txd <= k(12);
    --         elsif c = '1' and k < 20832 then
    --                 k <= k + 1;
    --                 clk_txd <= k(14);
    --         else
    --             k <= (others => '0');
    --         end if;
    --     end if;
    -- end process;

    process (clk) -- , reset)
    begin
        clk_txd <= clk;  -- if simply a concurrent assignment statement this
    end process;         -- would look similar to the elaborated equivalent 
                         -- process. The difference, no sensitivity list and
                         -- an explict wait on clk statement at the end. 
                         -- This process wants to be removed and replaced by
                         -- the above commented out process for synthesis

    process (clk_txd, reset) -- , reset, enable) -- enable a reset?
    begin
        -- if enable = '0' then 
        if reset = '1' then     -- puts q counter in known state for simulation
            q <= "00000000";
        elsif rising_edge(clk_txd) then
            if q /= 255 then    -- stop after sending once
                q <= q + 1;
            end if;
        end if;
    end process;

    -- enable <= '1' when q <= 255 else '0';  -- this appears incorrect

    enable <= '1' when q(3 downto 0) = "0010" else
              '0';
    clear  <= '1' when q(3 downto 0) = "0001" else
              '0';

    -- USING ONE COUNTER requires some clocks output MARKS 
    -- (idle bits) each 16 clocks. It requires the load (enable)
    --  occur once every 16 clocks.

    -- q(3 downto 0) is selected for enable to prevent outputting spaces
    -- TxD during reset (q is reset to all '0's). This would cause a receive
    -- framing error.

    process (q(7 downto 4))
    begin
        case q(7 downto 4) is 
            when "0000" => data <= x"40";
            when "0001" => data <= x"41";
            when "0010" => data <= x"42";
            when "0011" => data <= x"43";
            when "0100" => data <= x"44";
            when "0101" => data <= x"45";
            when "0110" => data <= x"46";
            when "0111" => data <= x"47";
            when "1000" => data <= x"48";
            when "1001" => data <= x"49";
            when "1010" => data <= x"50";
            when "1011" => data <= x"51";
            when "1100" => data <= x"52";
            when "1101" => data <= x"53";
            when "1110" => data <= x"54";
            when "1111" => data <= x"55";
            when others => data <= x"56";
        end case;
    end process;

    process (clk_txd) -- , enable, data)  -- synchronous enable and clear
    begin
        -- if enable = '1' then  -- this appears incorrect
        --    qtxd <= data; 
        if reset = '1' then
            qtxd <= (others => '1'); -- outputs mark after reset 
        elsif rising_edge(clk_txd) then
            if  clear = '1' then     -- synchronous clear for start bit
                qtxd(0) <= '0';
            elsif enable = '1' then         -- synchronous load
                qtxd <= data;
            else
                qtxd <= '1' & qtxd(7 downto 1); -- shift right
            end if;
        end if;
    end process;

    -- the synchronous load prevents the first start bit from being stretched
    -- q(3 downto 0) the following in hex notation
    -- q(3 downto 0) = 2 is the start bit
    --               = 3 is data(0)
    --               ...
    --               = A is data(7)  
    --               = B is the stop bit
    --               = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
    --               = 1 enable occurs loading qtxd
    --
    -- The offset is caused by synchronous load (1 clk_txd) and the load point 
    -- (q(3 downto 0) = 1 in enable term).
    --
    -- The load point wants to occur in the first 6 counts of q(3 downto 0) to
    -- insure a trailing mark when q is stopped.
    --
    -- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces 
    -- during reset from causing a receive framing error.

    txd <= qtxd(0);
    txdosc <= qtxd(0);

end architecture behavioral;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
--               = 3 is data(0)
--               ...
--               = A is data(7)  
--               = B is the stop bit
--               = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
--               = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point 
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces 
-- during reset from causing a receive framing error.