以下是代码:在此,未完成奇偶校验位的计算。可以使用for循环计算奇偶校验位,但是在此上下文中是否存在任何其他短或更好的方法来计算偶校验位。 是否有可能使用数组而不是8 TxDataReg std_logic_vector考虑到在制作数组之后我希望逐位访问8位8位信号的数组,逐位用于在uart_tx端口发送数据?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Uart_tx is
Port (
tx_clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
tx : out STD_LOGIC;
Rx_Data_in : in STD_LOGIC_VECTOR(63 downto 0)
);
end Uart_tx;
architecture Behavioral of Uart_tx is
signal Tx_Data : STD_LOGIC_VECTOR(63 downto 0) := "00000000";
signal DataByteArray1 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray2 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray3 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray4 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray5 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray6 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray7 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray8 : std_logic_vector(7 downto 0) := (others => "00000000");
signal TxDataReg1 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg2 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg3 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg4 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg5 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg6 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg7 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg8 : std_logic_vector(10 downto 0) := (others => "00000000");
signal count : unsigned(2 downto 0) := (others => '0');
signal one_bit : std_logic := '0';
begin
Tx_Data <= Rx_Data_in;
DataByteArray1 <= Rx_Data_in(7 downto 0);
DataByteArray2 <= Rx_Data_in(15 downto 8);
DataByteArray3 <= Rx_Data_in(23 downto 16);
DataByteArray4 <= Rx_Data_in(31 downto 24);
DataByteArray5 <= Rx_Data_in(39 downto 32);
DataByteArray6 <= Rx_Data_in(47 downto 40);
DataByteArray7 <= Rx_Data_in(55 downto 48);
DataByteArray8 <= Rx_Data_in(63 downto 56);
Process (tx_clk_in)
begin
-- Calculate the parity bit
for i in 0 to 7 loop
one_bit = DataByteArray1(i);
if one_bit = '1' then
count = count + 1;
end if;
end loop;
-- For all the registers,one even parity & two stop bits I am trying to add in the end
if count mod 2 = 0 then
TxDataReg1 <= DataByteArray1&'0'&'11'; -- I am not so sure that this works or not
count <= "000";
else
TxDataReg1 <= DataByteArray1&'1'&'11';
count <= "000";
end if;
-- Send the uart data from TxDataReg1,TxDataReg2 ...
-- etc.
end process;
end behavioral;
答案 0 :(得分:1)
如果您创建了一个状态机,这个UART会更容易理解。状态机为您的代码提供有组织的流程。流程更有意义。在VHDL中,您可以创建enumerated states
,这意味着您可以为它们命名。我推荐这种方法。
在整个设计中保持计数器要确切知道何时插入奇偶校验位或何时在UART设计中插入2个停止位要困难得多。如果你有一台漂亮的状态机,那么我相信你会更有意义。这对于FPGA新手来说尤其适用。
计算奇偶校验时,只需保留一个运行的奇偶校验位,该位将获得带有输出串行数据的XOR
。创建一个状态以在正确的时间插入奇偶校验位,然后插入两个停止位。
有关此示例,请查看此UART VHDL Code
答案 1 :(得分:0)
我会建议重新组织它以使用一次只能处理一个字节的FSM。那么你将有一个通用的异步。另一个控制器可以根据需要发送字节的TX实体。
关于管理您的数据。如果你创建了一个字节数组数组会更简单:
subtype byte is std_logic_Vector(7 downto 0);
type byte_array is array(natural range <>) of byte;
signal data_byte_array : byte_array(1 to 8);
signal byte_index : unsigned(2 downto 0);
...
-- Select the current byte
cur_byte <= data_byte_array(to_integer(byte_index));
子类型不是必须的,但是使用常见的数据类型是一个好习惯,可以避免乱丢你的代码并使用如此多的硬编码数组边界。
为了计算奇偶校验,您需要采用实现逻辑门的硬件思维而不是计数设置位的软件方法。奇偶校验计算归结为应用于向量中所有位的XOR-reduce操作。对于偶校验,您对所有位进行异或。对于奇校验,您对所有位进行异或并反转结果。因为XOR等同于受控反转,所以您可以通过设置初始状态并执行一次额外的XOR来选择奇偶校验类型,以根据您对奇数或偶数的期望进行可选的反转。
-- Any VHDL:
variable parity : std_logic;
parity := '0'; -- Set to '1' to get odd parity
for i in cur_byte'range loop
parity := parity xor cur_byte(i);
end loop;
-- VHDL-2002
use ieee.reduce_pack.xor_reduce;
parity := xor_reduce(cur_byte);
-- VHDL-2008
parity := xor cur_byte;
在综合中,这些方法都归结为相同的逻辑,因此它们中的任何一个都适用于所有实际目的。这是一个明确的并行操作,您不必按计数器的不必要开销按位逐位执行该字节。
您已经承诺将非标准Synopsys库std_logic_unsigned,_signed和_arith与真正的标准数字库numeric_std混合在一起。切勿将它们混合在同一个文件中,更好的是,根本不要使用Synopsys库。他们是最遗忘的历史失常。