下面是代码:这里没有计算奇偶校验位。可以使用for循环来计算奇偶校验位,但是在这种情况下是否有其他更短或更好的方法来计算偶校验位。考虑到在创建数组之后,我希望逐位访问8位8位信号的数组,以便在uart_tx端口中发送数据,是否可以使用数组而不是8 TxDataReg std_logic_vector?
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;发布于 2014-05-14 19:29:36
如果您创建了一个状态机,那么这个UART将更容易理解。状态机为您的代码提供了一个有组织的流程。这样的流程才更有意义。在VHDL语言中,你可以创建enumerated states,这意味着你可以给它们命名。我推荐这种方法。
在UART设计中,要准确知道何时插入奇偶校验位或何时插入2个停止位,在整个设计中保持计数器的难度要大得多。如果你有一个好的状态机,我相信它对你来说会更有意义。对于FPGA的新手来说,这是特别推荐的。
在计算奇偶校验时,只需保留一个运行的奇偶校验位,即可获得传出串行数据的XOR。创建一个状态以在正确的时间插入您的奇偶校验位,然后插入您的两个停止位。
有关这方面的示例,请查看此UART VHDL Code
发布于 2014-05-15 10:28:04
我赞同重新组织它的建议,以使用一次只处理一个字节的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等效于受控反转,您可以通过设置初始状态并执行一次额外的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库。它们是一种历史上的偏差,最好被遗忘。
https://stackoverflow.com/questions/23647844
复制相似问题