Многократное чтение регистра в VHDL и инкапсуляция приводят к неправильному значению
В настоящее время я сталкиваюсь с одной проблемой при чтении двух регистров и отправляю их значение через прокси на плитку на ПЛИС. Есть три входных канала для кодированных сигналов, которые состоят из импульсов с частотой 50 кГц, затем сигнал дискретизировался с помощью локальной тактовой частоты 100 МГц на плате FPGA. В модуле были подсчитаны два канала по их импульсам, и я использую битовое смещение для инкапсуляции, чтобы поместить значение чтения из двух счетчиков в один 32-битный std_bit_vector для отправки через прокси.
Если я передаю только счетные значения одного канала и отправляю их через прокси-сигналы, это ведет себя всегда правильно. Однако при считывании двух значений счета из двух регистров и выполнении инкапсуляции 16 старших бит сдвинутого значения всегда увеличиваются быстрее, чем должно быть. Другими словами, процесс подсчета, если сам является правильным, в то время как также нет проблем со связью между модулем подсчета и плиткой.
Я не знаю, что проблема вызвана слишком быстрым чтением процесса из двух регистров и приводит к проблеме синхронизации. Входной сигнал одного канала увеличивается только на один на 500 отсчетов, а другой - на 500 на оборот. Одно вращение контролируется вручную на энкодере (тогда вы можете представить себе низкую частоту входных сигналов)
Затем инкапсуляция была помещена в последние две строки модуля. Заранее спасибо.
Модуль подсчета имеет следующую конструкцию:
library rdt_dtl_proxy_targetlib;
use rdt_dtl_proxy_targetlib.rdt_dtl_proxy_target_cmp_pkg.all;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_ARITH.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity dtl_pmod_rotary is
generic (
WIDTH_DTL_CMD_ADDR : natural:= 32;
WIDTH_DTL_CMD_BLOCK_SIZE : natural:= 5;
WIDTH_DTL_DATA : natural:= 32;
WIDTH_DTL_WR_MASK : natural:= 4
);
port (
clk : in std_logic;
rst_n : in std_logic;
rotary_a : in std_logic;
rotary_b : in std_logic;
rotary_i : in std_logic;
dtl_cmd_valid_t_proxy0 : in std_logic;
dtl_cmd_accept_t_proxy0 : out std_logic;
dtl_cmd_addr_t_proxy0 : in std_logic_vector(WIDTH_DTL_CMD_ADDR - 1 downto 0);
dtl_cmd_read_t_proxy0 : in std_logic;
dtl_cmd_block_size_t_proxy0 : in std_logic_vector(WIDTH_DTL_CMD_BLOCK_SIZE - 1 downto 0);
dtl_wr_valid_t_proxy0 : in std_logic;
dtl_wr_last_t_proxy0 : in std_logic;
dtl_wr_accept_t_proxy0 : out std_logic;
dtl_wr_data_t_proxy0 : in std_logic_vector(WIDTH_DTL_DATA - 1 downto 0);
dtl_wr_mask_t_proxy0 : in std_logic_vector(WIDTH_DTL_WR_MASK - 1 downto 0);
dtl_rd_last_t_proxy0 : out std_logic;
dtl_rd_valid_t_proxy0 : out std_logic;
dtl_rd_accept_t_proxy0 : in std_logic;
dtl_rd_data_t_proxy0 : out std_logic_vector(WIDTH_DTL_DATA - 1 downto 0)
);
end dtl_pmod_rotary;
architecture rtl of dtl_pmod_rotary is
signal dtl_rd_data_15 : std_logic_vector(WIDTH_DTL_DATA - 1 downto 0);
signal dtl_rd_accept_14 : std_logic;
signal dtl_cmd_block_size_6 : std_logic_vector(WIDTH_DTL_CMD_BLOCK_SIZE - 1 downto 0);
signal dtl_wr_data_10 : std_logic_vector(WIDTH_DTL_DATA - 1 downto 0);
signal dtl_cmd_read_5 : std_logic;
signal dtl_rd_last_12 : std_logic;
signal dtl_rst_n_1 : std_logic;
signal dtl_wr_valid_7 : std_logic;
signal dtl_wr_accept_9 : std_logic;
signal dtl_wr_last_8 : std_logic;
signal dtl_cmd_addr_4 : std_logic_vector(WIDTH_DTL_CMD_ADDR - 1 downto 0);
signal dtl_cmd_valid_2 : std_logic;
signal dtl_clk_0 : std_logic;
signal dtl_rd_valid_13 : std_logic;
signal dtl_wr_mask_11 : std_logic_vector(WIDTH_DTL_WR_MASK - 1 downto 0);
signal dtl_cmd_accept_3 : std_logic;
-- signals for counting
signal cnt_r : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_r_a : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_r_b : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_r_i : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_nxt_a : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_nxt_b : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_nxt_i : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal cnt_ref_i : std_logic_vector(WIDTH_DTL_DATA-1 downto 0) := X"00000000";
signal rotary_a_r : std_logic; --register storing data from rotary_a.
signal rotary_a_2r : std_logic; --register storing data from rotary_a_r
signal rotary_b_r : std_logic; --register storing data from rotary_b.
signal rotary_b_2r : std_logic; --register storing data from rotary_b_r
signal rotary_i_r : std_logic; --register storing data from rotary_i.
signal rotary_i_2r : std_logic; --register storing data from rotary_i_r
begin
dtl_clk_0 <= clk;
dtl_rst_n_1 <= rst_n;
dtl_cmd_valid_2 <= dtl_cmd_valid_t_proxy0;
dtl_cmd_accept_t_proxy0 <= dtl_cmd_accept_3;
dtl_cmd_addr_4 <= dtl_cmd_addr_t_proxy0;
dtl_cmd_read_5 <= dtl_cmd_read_t_proxy0;
dtl_cmd_block_size_6 <= dtl_cmd_block_size_t_proxy0;
dtl_wr_valid_7 <= dtl_wr_valid_t_proxy0;
dtl_wr_last_8 <= dtl_wr_last_t_proxy0;
dtl_wr_accept_t_proxy0 <= dtl_wr_accept_9;
dtl_wr_data_10 <= dtl_wr_data_t_proxy0;
dtl_wr_mask_11 <= dtl_wr_mask_t_proxy0;
dtl_rd_last_t_proxy0 <= dtl_rd_last_12;
dtl_rd_valid_t_proxy0 <= dtl_rd_valid_13;
dtl_rd_accept_14 <= dtl_rd_accept_t_proxy0;
dtl_rd_data_t_proxy0 <= dtl_rd_data_15;
-- Begin child instances
proxy0 : rdt_dtl_proxy_target
generic map (
DTL_DATA_WIDTH => WIDTH_DTL_DATA,
DTL_ADDR_WIDTH => WIDTH_DTL_CMD_ADDR,
DTL_BLK_SIZE_WIDTH => WIDTH_DTL_CMD_BLOCK_SIZE,
DTL_WR_MASK_WIDTH => WIDTH_DTL_WR_MASK
)
port map (
dtl_clk => dtl_clk_0,
dtl_rst_n => dtl_rst_n_1,
dtl_cmd_accept_t => dtl_cmd_accept_3,
dtl_cmd_addr_t => dtl_cmd_addr_4,
dtl_cmd_block_size_t => dtl_cmd_block_size_6,
dtl_cmd_read_t => dtl_cmd_read_5,
dtl_cmd_valid_t => dtl_cmd_valid_2,
dtl_rd_accept_t => dtl_rd_accept_14,
dtl_rd_data_t => dtl_rd_data_15,
dtl_rd_last_t => dtl_rd_last_12,
dtl_rd_valid_t => dtl_rd_valid_13,
dtl_wr_accept_t => dtl_wr_accept_9,
dtl_wr_data_t => dtl_wr_data_10,
dtl_wr_last_t => dtl_wr_last_8,
dtl_wr_mask_t => dtl_wr_mask_11,
dtl_wr_valid_t => dtl_wr_valid_7,
cmd_accept => '1', --target accept handshake,input port of Proxy
cmd_addr => open,
cmd_block_size => open,
cmd_read => open, --output port of Proxy
cmd_valid => open, --output port of Proxy
rd_accept => open, --output port of Proxy, return the accept info from initializer
--rd_data => x"00000003", --test value
rd_data => cnt_r, --input port of proxy, for sending the counter value
rd_last => '1',
rd_valid => '1',
wr_accept => '0', --return value to Proxy indicating prepared for receiving written data from initiator
wr_data => open, --receive data from Proxy that written by initializer
wr_last => open,
wr_mask => open,
wr_valid => open
);
-- Counting pulses
-- combinatorial process
comb_counter_process_a : process(rotary_a_r, rotary_a_2r)
begin
if rotary_a_r = '1' and rotary_a_2r = '0' then
cnt_nxt_a <= cnt_r_a + 1;
else
cnt_nxt_a <= cnt_r_a;
end if;
end process;
-- sequential process with synchronous reset
seq_counter_process_a : process(clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
cnt_r_a <= (others => '0');
rotary_a_r <= '0';
rotary_a_2r <= '0';
else
-- registering
cnt_r_a <= cnt_nxt_a ;
rotary_a_2r <= rotary_a_r;
rotary_a_r <= rotary_a;
--cnt_r <= cnt_r_a(8 downto 0);
end if;
end if;
end process;
comb_counter_process_b : process(rotary_b_r, rotary_b_2r)
begin
if rotary_b_r = '1' and rotary_b_2r = '0' then
cnt_nxt_b <= cnt_r_b + 1;
else
cnt_nxt_b <= cnt_r_b;
end if;
end process;
-- sequential process with synchronous reset
seq_counter_process_b : process(clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
cnt_r_b <= (others => '0');
rotary_b_r <= '0';
rotary_b_2r <= '0';
else
-- registering
cnt_r_b <= cnt_nxt_b;
rotary_b_2r <= rotary_b_r;
rotary_b_r <= rotary_b;
--cnt_r(31 downto 16) <= X"ABCD";
end if;
end if;
end process;
comb_counter_process_i : process(rotary_i_r, rotary_i_2r)
begin
if rotary_i_r = '1' and rotary_i_2r = '0' then
cnt_nxt_i <= cnt_r_i + 1;
else
cnt_nxt_i <= cnt_r_i;
end if;
end process;
-- sequential process with synchronous reset
seq_counter_process_i : process(clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
cnt_r_i <= (others => '0');
rotary_i_r <= '0';
rotary_i_2r <= '0';
else
-- registering
cnt_r_i <= cnt_nxt_i;
rotary_i_2r <= rotary_i_r;
rotary_i_r <= rotary_i;
--cnt_r(15 downto 0) <= X"1234"; --the digits for cnt_r_i may change
end if;
end if;
end process;
cnt_r(31 downto 16) <= cnt_r_b(15 downto 0);
cnt_r(15 downto 0) <= cnt_r_i(15 downto 0);
end rtl;