用于键盘接口的 vhdl 代码
Posted
技术标签:
【中文标题】用于键盘接口的 vhdl 代码【英文标题】:vhdl code for keypad interfacing 【发布时间】:2015-11-08 17:58:17 【问题描述】: entity hex_kp is
Port ( row : out STD_LOGIC_VECTOR (3 downto 0);
coloumn : in STD_LOGIC_VECTOR (3 downto 0);
sevenseg : out STD_LOGIC_VECTOR (7 downto 0);
ca : out STD_LOGIC_VECTOR (3 downto 0));
end hex_kp;
architecture Behavioral of hex_kp is
begin
ca <="0111";
if(row = "0111") then
if(coloumn = "0111") then sevenseg <= "00000110" ;
elsif (coloumn = "1011") then sevenseg <= "01011011" ;
elsif (coloumn = "1101") then sevenseg <= "01001111" ;
elsif (coloumn = "1110") then sevenseg <= "01110001" ;
end if;
end if;
这是我用于 Basys2 的 4x4 键盘扫描仪的 vhdl 代码的一部分。它给 "if(row = "0111") then" 语句一个错误。我找不到请帮忙的原因。
【问题讨论】:
读取“OUT”端口无效,除非您指定 VHDL-2008。 并且您不(应该)被允许根据 -2008 中的输出值对其他信号的值做出决定。这是一项旨在支持验证构造的功能。 信号row
的值在哪里赋值?
您是否将 Digilent 键盘用作 Pmod 设备?有浮动输入的可能性……您应该在 FPGA 的 IOB 中启用上拉。
我找到了 4×4 键盘的原始 Digilent 示例代码。您必须开车 column
并阅读 row
!这可以防止您使用浮动输入。
【参考方案1】:
可以使用条件信号赋值语句:
architecture behave of hex_kp is
begin
ca <="0111";
-- if(row = "0111") then
--
-- if(coloumn = "0111") then sevenseg <= "00000110" ;
-- elsif (coloumn = "1011") then sevenseg <= "01011011" ;
-- elsif (coloumn = "1101") then sevenseg <= "01001111" ;
-- elsif (coloumn = "1110") then sevenseg <= "01110001" ;
-- end if;
-- end if;
sevenseg <= "00000110" when coloumn = "0111" and row = "0111" else
"01011011" when coloumn = "1011" and row = "0111" else
"01001111" when coloumn = "1101" and row = "0111" else
"01110001" when coloumn = "1110" and row = "0111" else
"00000000" when row = "0111";
end architecture behave;
请注意,与您的 Stack Exchange 问题 (vhdl code interfacing keypad with fpga) 一样,sevenseg
上存在推断的闩锁,这是由于使用 row = "0111"
作为分配条件而引起的。
上述架构给出的结果与我对您的 Stack Exchange 问题 (vhdl code interfacing keypad with fpga) 的回答相同。
您修改后的代码分析、阐述和添加的测试平台模拟了上述架构:
摆脱闩锁就像从上面的条件信号分配中的最终选择中删除 row = "0111"
一样简单,或者在 Stack Exchange 示例中使用 case 语句,为封闭的 if 语句提供 else 。
以使用行作为输入为前提的整个代码,包括测试台和两种架构:
library ieee;
use ieee.std_logic_1164.all;
entity hex_kp is
port (
row: in std_logic_vector (3 downto 0);
coloumn: in std_logic_vector (3 downto 0); -- 'column 'is mispelled
sevenseg: out std_logic_vector (7 downto 0); -- why is 7 segs 8 long?
ca : out std_logic_vector (3 downto 0)
);
end entity hex_kp;
architecture behavioral of hex_kp is
-- signal row: std_logic_vector(3 downto 0); -- who drive row?
begin -- this was missing
UNLABELLED:
process(row, coloumn) -- was 'column' (didn't match declaration)
begin
ca <="0111";
if row = "0111" then
case coloumn is
when "0111" =>
sevenseg <= "00000110";
when "1011" =>
sevenseg <= "01011011";
when "1101" =>
sevenseg <= "01001111";
when "1110" =>
sevenseg <= "01110001";
when others =>
sevenseg <= (others => '0');
end case;
end if;
end process;
end architecture behavioral;
architecture behave of hex_kp is
begin
ca <="0111";
-- if(row = "0111") then
--
-- if(coloumn = "0111") then sevenseg <= "00000110" ;
-- elsif (coloumn = "1011") then sevenseg <= "01011011" ;
-- elsif (coloumn = "1101") then sevenseg <= "01001111" ;
-- elsif (coloumn = "1110") then sevenseg <= "01110001" ;
-- end if;
-- end if;
sevenseg <= "00000110" when coloumn = "0111" and row = "0111" else
"01011011" when coloumn = "1011" and row = "0111" else
"01001111" when coloumn = "1101" and row = "0111" else
"01110001" when coloumn = "1110" and row = "0111" else
"00000000" when row = "0111";
end architecture behave;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hex_kp_tb is
end entity;
architecture foo of hex_kp_tb is
signal row: std_logic_vector (3 downto 0);
signal coloumn: std_logic_vector (3 downto 0);
signal sevenseg: std_logic_vector (7 downto 0);
signal ca: std_logic_vector (3 downto 0);
signal count: unsigned (7 downto 0) := (others => '0');
begin
DUT:
entity work.hex_kp
port map (
row => row,
coloumn => coloumn,
sevenseg => sevenseg,
ca => ca
);
STIMULUS:
process
begin
row <= std_logic_vector (count(3 downto 0));
coloumn <= std_logic_vector (count(7 downto 4));
wait for 100 ns;
count <= count + 1;
if count = "11111111" then
wait;
end if;
end process;
end architecture;
【讨论】:
我假设sevenseg : out std_logic_vector (7 downto 0)
中的第 8 段/第 7 位是点:)。
那么,Paebbels 显示的字符是什么?
您的代码有注释:-- why is 7 segs 8 long?
我指的是。通常 7 段显示器有 7 个阴极引脚,命名为 a..g
(每个 LED 段一个)和一个用于点的第 8 个引脚。这可以解释为什么 OP 将端口声明为 7 downto 0
。
那么显示的字符是什么? Baysys2 UCF 显示 7 段输出、dp 和 4 个阴极。第一个是'1',第二个是'2',第三个是向后的'E',第四个是'E',假设一个是打开的,最左边是你的小数点,它是像共阴极一样的段和 g 是下一个最左边的。关键是它没有记录在案。【参考方案2】:
您正在尝试在并发上下文中使用if
语句。但是,if
语句需要在顺序上下文中 - 例如 process
语句:
process(row, column)
begin
if(row = "0111") then
if(coloumn = "0111") then
sevenseg <= "00000110";
elsif(coloumn = "1011") then
sevenseg <= "01011011";
elsif(coloumn = "1101") then
sevenseg <= "01001111";
elsif(coloumn = "1110") then
sevenseg <= "01110001";
end if;
end if;
end process;
但是 - 请注意,如果您综合上述内容,它很可能最终会为您提供一组不错的锁存器(您通常不想要),因为您没有在所有可能的情况下分配 sevenseg
(如果row
与 0111
不同,或者如果 coloumn
不匹配任何 if
语句)。
要修复它,要么 1) 使用时钟 process
,要么 2) 如果 row
和 coloumn
与指定情况之一不匹配,则将 sevenseg
分配给默认值。例如:
process(row, column)
begin
sevenseg <= (others => '0');
if(row = "0111") then
if(coloumn = "0111") then
sevenseg <= "00000110";
elsif(coloumn = "1011") then
sevenseg <= "01011011";
elsif(coloumn = "1101") then
sevenseg <= "01001111";
elsif(coloumn = "1110") then
sevenseg <= "01110001";
end if;
end if;
end process;
我添加了sevenseg <= (others => '0');
,这将使sevenseg
默认为所有0
,如果没有命中指定的情况-如果是,它们将覆盖添加的行,并设置@987654339 @ 到适当的值。
一个更好的方法是使用case
语句,因为这可能更好地描述了你真正想要的:
process(row, column)
begin
if(row = "0111") then
case coloumn is
when "0111" =>
sevenseg <= "00000110";
when "1011" =>
sevenseg <= "01011011";
when "1101" =>
sevenseg <= "01001111";
when "1110" =>
sevenseg <= "01110001";
when others =>
sevenseg <= (others => '0');
end case;
else
sevenseg <= (others => '0');
end if;
end process;
【讨论】:
我添加了进程,但是现在它给该行提供了错误。 if 语句是一个顺序语句,它不仅可以在进程中找到(例如子程序)。恰好 Ayca Ekin 试图在适合并发语句的地方使用 if 语句,这需要条件信号赋值语句或包含 if 语句或 case 语句的进程。 该错误与布赖恩对您的问题的评论有关。按照 Brian 在 Stack Exchange (vhdl code interfacing keypad with fpga) 上的建议显示错误消息。 啊-感谢您的详细说明,稍微调整了答案。以上是关于用于键盘接口的 vhdl 代码的主要内容,如果未能解决你的问题,请参考以下文章
VHDL串口通信 在FPGA开发板上测试 并解决没有识别到下载接口USB_Blaster(No Hardware问题)