我在这个模拟中缺少什么?
What I'm missing in this simulation?
我正在尝试为键盘驱动程序编写 VHDL 代码,因为我需要从 11 位向量中读取 8 位,为了清楚起见,这里是读取输入信号的过程(有信号 CLK 和数据)。
KEYBOARD_SYNC : process(CLK,SYSRESET)
begin
if (CLK'event and CLK='1') then
KEYBOARD_CLK_VECTOR <= KEYBOARD_CLK_VECTOR( 6 downto 0 ) & KEYBOARD_CLK;
RECEIVING_FLAG <='0';
if ( KEYBOARD_CLK_VECTOR = x"F0" ) then -- Falling edge
KEYBOARD_DATA_VECTOR <= KEYBOARD_DATA_VECTOR( 9 downto 0 ) & KEYBOARD_DATA;-- shifting
BIT_COUNTER <= BIT_COUNTER + 1 ;
end if;
if( BIT_COUNTER = 11 ) then
RECEIVING_FLAG <='1';
TEMP_WORD <= KEYBOARD_DATA_VECTOR( 8 downto 1 );
BIT_COUNTER <=0 ;
KEYBOARD_DATA_VECTOR <= (others =>'1');
end if ;
end if ;
end process KEYBOARD_SYNC;
PROCESSING : process ( CLK ,SYSRESET )
begin
if ( CLK'event and CLK ='1') then
if ( RECEIVING_FLAG = '1') then
ACTUAL_WORD <= TEMP_WORD;
end if ;
end if ;
end process PROCESSING;
为了 运行 模拟,我写了一个应该发送 0xF0
的测试平台,这个值应该保存在 ACTUAL_WORD 中,这是测试平台的一部分应该这样做:
-- Timing variables
constant CLK_PERIOD: time := 10 ns;
constant KEYBOARD_CLK_PERIOD: time := 80 us;
...................................................
KEYBOARD_PROCESS : process
BEGIN
-- BREAK Code
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '0';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; --Start Bit always 0
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '1'; -- Sending a break code 0xF0
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 0 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 1 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 2 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 3 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_DATA<= '0';
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 4 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 5 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 6 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 7 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_DATA<= '1';
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- Parity Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- Stop Bit always 1
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
end process KEYBOARD_PROCESS;
结果是:
(可点击)
问题是我一直在阅读 0xE1
而不是 0xF0
其他所有内容都工作正常,我无法弄清楚为什么我错过了这个位。
将 0xF0 的周期模式读取为 0xE1 看起来像是 1 位移位,这可能是由于测试台生成时钟 (KEYBOARD_CLK
) 和数据 (KEYBOARD_DATA
) 在同时。
在硬件设计中,输出数据是由时钟产生的,因此时钟上升沿和新数据之间至少会有一个delta周期延迟,但目前的测试平台设计产生时钟和同时数据有:
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '0';
因此波形看起来很熟悉,但信号流实际上缺少时钟和数据之间的增量周期延迟,因此数据比预期的波形提前一个周期就绪,导致 1 位移位。然而,这并没有显示在当前的波形视图中,这可能是令人费解的部分。 ModelSim 可以显示缺少增量循环,但这不是默认设置。
在测试台架设计中也遵循通用设计方法通常是个好主意,以便保持单一的通用设计实践,从而更容易阅读代码和波形。
所以在测试台上,做一个产生时钟的过程,然后做一个根据时钟产生数据的过程,就像硬件设计一样。这可以像这样完成:
CLK_PROCESS : process
BEGIN
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
end process;
DATA_PROCESS : process
BEGIN
KEYBOARD_DATA <= '0';
for i in 1 to 5 loop -- Number of cycles with same data
wait until rising_edge(KEYBOARD_CLK);
end loop;
...
KEYBOARD_DATA <= '1';
for i in 1 to 5 loop -- Number of cycles with same data
wait until rising_edge(KEYBOARD_CLK);
end loop;
...
end process;
根据所需的测试模式适当调整重复数据的循环。
我正在尝试为键盘驱动程序编写 VHDL 代码,因为我需要从 11 位向量中读取 8 位,为了清楚起见,这里是读取输入信号的过程(有信号 CLK 和数据)。
KEYBOARD_SYNC : process(CLK,SYSRESET)
begin
if (CLK'event and CLK='1') then
KEYBOARD_CLK_VECTOR <= KEYBOARD_CLK_VECTOR( 6 downto 0 ) & KEYBOARD_CLK;
RECEIVING_FLAG <='0';
if ( KEYBOARD_CLK_VECTOR = x"F0" ) then -- Falling edge
KEYBOARD_DATA_VECTOR <= KEYBOARD_DATA_VECTOR( 9 downto 0 ) & KEYBOARD_DATA;-- shifting
BIT_COUNTER <= BIT_COUNTER + 1 ;
end if;
if( BIT_COUNTER = 11 ) then
RECEIVING_FLAG <='1';
TEMP_WORD <= KEYBOARD_DATA_VECTOR( 8 downto 1 );
BIT_COUNTER <=0 ;
KEYBOARD_DATA_VECTOR <= (others =>'1');
end if ;
end if ;
end process KEYBOARD_SYNC;
PROCESSING : process ( CLK ,SYSRESET )
begin
if ( CLK'event and CLK ='1') then
if ( RECEIVING_FLAG = '1') then
ACTUAL_WORD <= TEMP_WORD;
end if ;
end if ;
end process PROCESSING;
为了 运行 模拟,我写了一个应该发送 0xF0
的测试平台,这个值应该保存在 ACTUAL_WORD 中,这是测试平台的一部分应该这样做:
-- Timing variables
constant CLK_PERIOD: time := 10 ns;
constant KEYBOARD_CLK_PERIOD: time := 80 us;
...................................................
KEYBOARD_PROCESS : process
BEGIN
-- BREAK Code
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '0';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; --Start Bit always 0
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '1'; -- Sending a break code 0xF0
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 0 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 1 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 2 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 3 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_DATA<= '0';
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 4 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 5 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 6 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- 7 Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_DATA<= '1';
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- Parity Bit
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '0'; -- Stop Bit always 1
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
end process KEYBOARD_PROCESS;
结果是:
问题是我一直在阅读 0xE1
而不是 0xF0
其他所有内容都工作正常,我无法弄清楚为什么我错过了这个位。
将 0xF0 的周期模式读取为 0xE1 看起来像是 1 位移位,这可能是由于测试台生成时钟 (KEYBOARD_CLK
) 和数据 (KEYBOARD_DATA
) 在同时。
在硬件设计中,输出数据是由时钟产生的,因此时钟上升沿和新数据之间至少会有一个delta周期延迟,但目前的测试平台设计产生时钟和同时数据有:
KEYBOARD_CLK <= '1';
KEYBOARD_DATA <= '0';
因此波形看起来很熟悉,但信号流实际上缺少时钟和数据之间的增量周期延迟,因此数据比预期的波形提前一个周期就绪,导致 1 位移位。然而,这并没有显示在当前的波形视图中,这可能是令人费解的部分。 ModelSim 可以显示缺少增量循环,但这不是默认设置。
在测试台架设计中也遵循通用设计方法通常是个好主意,以便保持单一的通用设计实践,从而更容易阅读代码和波形。
所以在测试台上,做一个产生时钟的过程,然后做一个根据时钟产生数据的过程,就像硬件设计一样。这可以像这样完成:
CLK_PROCESS : process
BEGIN
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
KEYBOARD_CLK <= '1';
wait for (KEYBOARD_CLK_PERIOD/2);
end process;
DATA_PROCESS : process
BEGIN
KEYBOARD_DATA <= '0';
for i in 1 to 5 loop -- Number of cycles with same data
wait until rising_edge(KEYBOARD_CLK);
end loop;
...
KEYBOARD_DATA <= '1';
for i in 1 to 5 loop -- Number of cycles with same data
wait until rising_edge(KEYBOARD_CLK);
end loop;
...
end process;
根据所需的测试模式适当调整重复数据的循环。