UART 接收器测试平台
UART Receiver Testbench
我是 VHDL 的新手,我想验证 UART 接收器是如何工作的。
我合成了下面的代码(从书中引用),它很好,但如果需要更多,请告诉我 :)。
我的板子的频率是 100 Mhz,我想要接收的数据是 8 位,波特率为 115200,时钟和滴答应该在测试台上如何,或者这里的正确测试台是什么?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity uart_rx is
generic(
data_bits: integer := 8; -- # d a t a b i t s
stop_bit_ticks: integer := 16 -- # t i c k s f o r s t o p b i t s
);
Port ( rx : in STD_LOGIC;
clk : in STD_LOGIC;
reset: in STD_LOGIC;
tick : in STD_LOGIC;
rx_done : out STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end uart_rx;
architecture arch of uart_rx is
type state_type is (idle, start, data, stop);
SIGNAL state_reg, state_next: state_type;
SIGNAL s_reg, s_next: UNSIGNED(3 downto 0);
SIGNAL n_reg, n_next: UNSIGNED(2 downto 0);
SIGNAL b_reg, b_next: STD_LOGIC_VECTOR(7 downto 0);
begin
-- FSMD s t a t e & d a t a r e g i s t e r s
process(clk, reset) -- FSMD state and data regs.
begin
if (reset = '1') then
state_reg <= idle;
s_reg <= (others => '0');
n_reg <= (others => '0');
b_reg <= (others => '0');
--rx_done <= '0';
-- rx <= '1';
elsif (clk'event and clk='1') then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
end if;
end process;
-- n e x t - s t a t e l o g i c & d a t a p a t h f u n c t i o n a l u n i t s / r o u t i n g
process (state_reg, s_reg, n_reg, b_reg, tick, rx)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
rx_done <= '0';
case state_reg is
when idle =>
if (rx = '0') then
state_next <= start;
s_next <= (others => '0');
end if;
when start =>
if (tick = '1') then
if (s_reg = 7) then
state_next <= data;
s_next <= (others => '0');
n_next <= (others => '0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
if (tick = '1') then
if (s_reg = 15) then
s_next <= (others => '0');
b_next <= rx & b_reg(7 downto 1);
if (n_reg = (data_bits - 1)) then
state_next <= stop;
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
if (tick = '1') then
if (s_reg = (stop_bit_ticks - 1)) then
state_next <= idle;
rx_done <= '1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
data_out <= b_reg;
end arch;
通常,UART 接收 运行 比特率的 8 倍。如果您的比特率为 115200,这意味着采样率为 921600。如果您在 100Mzh 运行ning,您将需要创建一个时钟分频器以使您从 100 MHz 达到所需的采样率。要从 921600 到 100 MHz,以下将起作用:
100 兆赫 = 100,000,000 赫兹
921600 samples/sec = 921,600 赫兹
除法器 = 100,000,000/921,600 = 108.51。
因此,您将需要一个计数器,它会在 rising_edge(时钟)上计数到 109(我们四舍五入,因为我们必须以时钟速率的整数进行采样),然后发出启用信号告诉您的组件是时候对线路进行采样并重置计数器了。上面的示例假定 8 samples/bit,据我所知这是典型的。因此,如果你在仿真中将主时钟的周期设置为1ns,并设置我上面描述的计数器电路,你应该得到你正在寻找的测试平台。
编辑:关于不均匀时钟分频的警告
差点忘了提这个。由于您的时钟速率不会平均分配给 UART 的比特率,因此在编写此电路时必须格外小心。使用我提出的方案,您的采样率将在传输中越来越晚。您可能需要添加一个简单的偏移量来将偶数位的计数器更改为 108,以使您与传入的数据位更加一致。
查看此处了解更多信息:https://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed
我是 VHDL 的新手,我想验证 UART 接收器是如何工作的。 我合成了下面的代码(从书中引用),它很好,但如果需要更多,请告诉我 :)。 我的板子的频率是 100 Mhz,我想要接收的数据是 8 位,波特率为 115200,时钟和滴答应该在测试台上如何,或者这里的正确测试台是什么?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
entity uart_rx is
generic(
data_bits: integer := 8; -- # d a t a b i t s
stop_bit_ticks: integer := 16 -- # t i c k s f o r s t o p b i t s
);
Port ( rx : in STD_LOGIC;
clk : in STD_LOGIC;
reset: in STD_LOGIC;
tick : in STD_LOGIC;
rx_done : out STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (7 downto 0));
end uart_rx;
architecture arch of uart_rx is
type state_type is (idle, start, data, stop);
SIGNAL state_reg, state_next: state_type;
SIGNAL s_reg, s_next: UNSIGNED(3 downto 0);
SIGNAL n_reg, n_next: UNSIGNED(2 downto 0);
SIGNAL b_reg, b_next: STD_LOGIC_VECTOR(7 downto 0);
begin
-- FSMD s t a t e & d a t a r e g i s t e r s
process(clk, reset) -- FSMD state and data regs.
begin
if (reset = '1') then
state_reg <= idle;
s_reg <= (others => '0');
n_reg <= (others => '0');
b_reg <= (others => '0');
--rx_done <= '0';
-- rx <= '1';
elsif (clk'event and clk='1') then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
end if;
end process;
-- n e x t - s t a t e l o g i c & d a t a p a t h f u n c t i o n a l u n i t s / r o u t i n g
process (state_reg, s_reg, n_reg, b_reg, tick, rx)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
rx_done <= '0';
case state_reg is
when idle =>
if (rx = '0') then
state_next <= start;
s_next <= (others => '0');
end if;
when start =>
if (tick = '1') then
if (s_reg = 7) then
state_next <= data;
s_next <= (others => '0');
n_next <= (others => '0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
if (tick = '1') then
if (s_reg = 15) then
s_next <= (others => '0');
b_next <= rx & b_reg(7 downto 1);
if (n_reg = (data_bits - 1)) then
state_next <= stop;
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
if (tick = '1') then
if (s_reg = (stop_bit_ticks - 1)) then
state_next <= idle;
rx_done <= '1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
data_out <= b_reg;
end arch;
通常,UART 接收 运行 比特率的 8 倍。如果您的比特率为 115200,这意味着采样率为 921600。如果您在 100Mzh 运行ning,您将需要创建一个时钟分频器以使您从 100 MHz 达到所需的采样率。要从 921600 到 100 MHz,以下将起作用:
100 兆赫 = 100,000,000 赫兹
921600 samples/sec = 921,600 赫兹
除法器 = 100,000,000/921,600 = 108.51。
因此,您将需要一个计数器,它会在 rising_edge(时钟)上计数到 109(我们四舍五入,因为我们必须以时钟速率的整数进行采样),然后发出启用信号告诉您的组件是时候对线路进行采样并重置计数器了。上面的示例假定 8 samples/bit,据我所知这是典型的。因此,如果你在仿真中将主时钟的周期设置为1ns,并设置我上面描述的计数器电路,你应该得到你正在寻找的测试平台。
编辑:关于不均匀时钟分频的警告
差点忘了提这个。由于您的时钟速率不会平均分配给 UART 的比特率,因此在编写此电路时必须格外小心。使用我提出的方案,您的采样率将在传输中越来越晚。您可能需要添加一个简单的偏移量来将偶数位的计数器更改为 108,以使您与传入的数据位更加一致。
查看此处了解更多信息:https://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed