我有这个代码
Process(counter)
begin
case counter is
when 0 => countertonumber <= "11000000"; -- 0
when 1 => countertonumber <= "11111001" ; -- 1
when 2 => countertonumber <= "10100100" ; -- 2
when 3 => countertonumber <= "10110000" ; -- 3
when 4 => countertonumber <= "10011001" ; -- 4
when 5 => countertonumber <= "10010010" ; -- 5
when 6 => countertonumber <= "10000011" ; -- 6
when 7 => countertonumber <= "11111000" ; -- 7
when 8 => countertonumber <= "10000000" ; -- 8
when 9 => countertonumber <= "10010000" ; -- 9
when others =>
end case;
end process;
这段代码对于我的程序工作至关重要(在4 * 7段diplay上显示数字)。问题是Counter的Integer值从0到9999,我宁愿不写所有9999的可能性。 是否可以检查每个整数,从而使用它检查它应该写入引脚的值。
如果counter = 9999, 然后我可以在我的计数器值中为每个值切换大小写..
我对如何在VHDL中有效地做到这一点感到有点迷失......
完整的代码和我的想法。
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 23:52:28 03/05/2014
-- Design Name:
-- Module Name: Main - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
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;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Main is
PORT(
CLK: in std_logic;
-- LED: out std_logic_vector (7 downto 0);
Switch: in std_logic_vector(7 downto 0);
Segment: out std_logic_vector (7 downto 0);
AN: out std_logic_vector (3 downto 0)
);
end Main;
architecture Behavioral of Main is
signal counter_1000: integer range 0 to 10;
signal counter_100: integer range 0 to 10;
signal counter_10: integer range 0 to 10;
signal counter_1: integer range 0 to 10;
signal prescaler: integer range 0 to 50000000;
signal limit: integer range 0 to 50000000;
signal countertonumber: std_logic_vector (7 downto 0);
begin
ScalerChoice: Process(switch)
begin
CASE Switch IS
when "00000001" => limit <= 50000000/1; -- 1 Hz;
when "00000010" => limit <= 50000000/3; -- 3 HZ
When "00000100" => limit <= 50000000/10; -- 10 Hz
when "00001000" => limit <= 50000000/25; -- 25 Hz
When "00010000" => limit <= 50000000/50; -- 50 Hz;
when "00100000" => limit <= 50000000/100; -- 100 hz
when others => limit <= 50000000/50000000; -- 50 MHz
end case;
end process;
CounterProcess: process(CLK,Switch)
begin
if rising_edge(CLK) then
if prescaler < limit then
prescaler <= prescaler + 1;
else
prescaler <= 0;
counter_1 <= counter_1 + 1;
if (counter_1 > 9) then
counter_1 <= 0;
counter_10 <= counter_10 + 1;
if (counter_10 > 9) then
counter_10 <= 0;
counter_100 <= counter_100 + 1;
if (counter_100 > 9) then
counter_100 <= 0;
counter_1000 <= counter_1000 + 1;
if (counter_1000 > 9) then
counter_100 <= 0;
counter_10 <= 0;
counter_1 <= 0;
counter_1000 <= 0;
end if;
end if;
end if;
end if;
end if;
end if;
end process;
Process(counter_1, Counter_10,Counter_100,Counter_1000,clk)
begin
if rising_edge(cLK) then
An <= "1110";
case counter_1 is
when 0 => countertonumber <= "11000000"; -- 0
when 1 => countertonumber <= "11111001" ; -- 1
when 2 => countertonumber <= "10100100" ; -- 2
when 3 => countertonumber <= "10110000" ; -- 3
when 4 => countertonumber <= "10011001" ; -- 4
when 5 => countertonumber <= "10010010" ; -- 5
when 6 => countertonumber <= "10000011" ; -- 6
when 7 => countertonumber <= "11111000" ; -- 7
when 8 => countertonumber <= "10000000" ; -- 8
when others => countertonumber <= "11000000" ; -- 9
end case;
case counter_10 is
when 0 => countertonumber <= "11000000"; -- 0
when 1 => countertonumber <= "11111001" ; -- 1
when 2 => countertonumber <= "10100100" ; -- 2
when 3 => countertonumber <= "10110000" ; -- 3
when 4 => countertonumber <= "10011001" ; -- 4
when 5 => countertonumber <= "10010010" ; -- 5
when 6 => countertonumber <= "10000011" ; -- 6
when 7 => countertonumber <= "11111000" ; -- 7
when 8 => countertonumber <= "10000000" ; -- 8
when others => countertonumber <= "11000000" ; -- 9
end case;
segment <= countertonumber;
An <= "1011";
case counter_100 is
when 0 => countertonumber <= "11000000"; -- 0
when 1 => countertonumber <= "11111001" ; -- 1
when 2 => countertonumber <= "10100100" ; -- 2
when 3 => countertonumber <= "10110000" ; -- 3
when 4 => countertonumber <= "10011001" ; -- 4
when 5 => countertonumber <= "10010010" ; -- 5
when 6 => countertonumber <= "10000011" ; -- 6
when 7 => countertonumber <= "11111000" ; -- 7
when 8 => countertonumber <= "10000000" ; -- 8
when others => countertonumber <= "11000000" ; -- 9
end case;
segment <= countertonumber;
An <= "0111";
case counter_1000 is
when 0 => countertonumber <= "11000000"; -- 0
when 1 => countertonumber <= "11111001" ; -- 1
when 2 => countertonumber <= "10100100" ; -- 2
when 3 => countertonumber <= "10110000" ; -- 3
when 4 => countertonumber <= "10011001" ; -- 4
when 5 => countertonumber <= "10010010" ; -- 5
when 6 => countertonumber <= "10000011" ; -- 6
when 7 => countertonumber <= "11111000" ; -- 7
when 8 => countertonumber <= "10000000" ; -- 8
when others => countertonumber <= "11000000" ; -- 9
segment <= countertonumber;
end case;
end if;
end process;
end Behavioral;
答案 0 :(得分:1)
对于任何硬件问题,首先绘制硬件图片,然后编写代码。
我在您的代码中看到以下内容,一次只选择一个阳极,并将数字多路复用到阴极线上。我在代码中看不到清楚的是你如何选择特定的阳极和计数器(i)。根据您的“想法”代码,最后一个分配获胜,您最终选择counter(3)和AN&lt; =“1110”;总是
我建议您将问题的这一部分分解为两部分。第一部分选择选择哪个阳极和哪个计数器。第二部分解码活动计数器并将该值放在阴极上(countertonumber)。如果你这样做,你只需要编写(和调试)一个case语句来解码计数器。
您缺少的部分是阳极和活动计数器的选择。我用了一个额外的计数器来做到这一点。在完美的板上,计算0到3可以正常工作。在我使用的电路板上,连接到阳极的晶体管很慢,所以我使用值0到7.值0,阳极0打开而计数器(0)是活动计数器。值1,所有阳极关闭,计数器(0)是活动计数器。值1,阳极1打开,计数器(1)是活动计数器。值2,所有阳极关闭,计数器(1)是活动计数器。等等。
用于解码活动计数器的代码只是您在上面编写的代码。
如果使用多个进程,请使用有效计数器值的信号。如果使用单个进程,请使用变量作为活动计数器值。
答案 1 :(得分:1)
我认为你在相同的CLK边缘有多个计数器分配,加上在0-9范围内声明的计数器不能被测试为9以上。这是你的过程稍微重新审视。我没有测试,但我认为它可以完成你的任务。
CounterProcess: process(CLK,Switch)
begin
if rising_edge(CLK) then
if prescaler < limit then
prescaler <= prescaler + 1;
else
prescaler <= 0;
if (counter_1 < 9) then
counter_1 <= counter_1 + 1;
else
counter_1 <= 0;
if (counter_10 < 9) then
counter_10 <= counter_10 + 1;
else
counter_10 <= 0;
if (counter_100 < 9) then
counter_100 <= counter_100 + 1;
else
counter_100 <= 0;
if (counter_1000 < 9) then
counter_1000 <= counter_100 + 1;
else
counter_1000 <= 0;
counter_1 <= 0;
counter_10 <= 0;
counter_100 <= 0;
end if;
end if;
end if;
end if;
end if;
end if;
end process;
enter code here
答案 2 :(得分:0)
如果您担心性能,可以考虑将计数值保存在4个单独的数字中,从0到9,而不是取消单个大整数。您可以为此目的使用变量或信号。当其中一个数字溢出时,您应该增加下一个数字。要生成显示输出,您只需为每个数字复制相同的转换逻辑。您可以使用函数或单独的实体来避免重复代码。
如果你不担心性能,你可以看看我写的一个小型库。检查Decimal number on 7 segment display的答案。
答案 3 :(得分:0)
执行此操作的最佳方法取决于计数器值的表示。
如果它表示为4个十进制数字的数组(即使用BCD算术),那么您只需依次处理每个数字。
即使你的计数器是二进制的,你会发现除以10并计算余数并不是一个不可能的昂贵操作;特别是如果您不需要在单个时钟周期内得到结果:执行重复减法的状态机每个数字只需要10个时钟周期。按照你更新显示器的速度,我怀疑这种延迟很重要!
我会使用常量数组来显示我的显示解码值,并用数组中的简单查找替换每个大型case语句。
例如:
type Count_Value is natural range 0 to 9999;
type Digit is natural range 0 to 9;
type Digits is (thousands, hundreds, tens, units);
type Display_Data is std_logic_vector(7 downto 0);
constant Divisors : array (Digits) of Count_Value := (1000, 100, 10, 1);
constant Lookup : array (Digit) of Display_Data :=
("11000000", "11111001", ... 10010000");
signal Display : array(Digits) of Display_Data;
signal Count : Count_Value;
signal Start : std_logic;
...
Update : process (Clock) is
type State_Type is (idle, processing);
variable State : State_Type;
variable This_Digit : Digits;
variable This_Value : Digit;
variable Remaining : Count_Value;
begin
if rising_edge(Clock) then
if State = idle then -- convert when asked
if Start = '1' then
Remaining := Count;
This_Digit := thousands;
This_Value := 0;
State := processing;
end if;
else
-- process current digit
if Remaining < Divisors(This_Digit) then
-- finish this digit
Display(This_Digit) <= Lookup(This_Value);
-- done?
if This_Digit = Units then
State := idle;
else
-- move to next digit
This_Value := 0;
This_Digit := Digits'succ(This_Digit);
end if;
else
Remaining := Remaining - Divisors(This_Digit);
This_Value := This_Value + 1;
end if;
end if;
end if;
end process;
编辑:这个例子是一个过程,当Start被置位时,它将整数Count分成四个独立的数字,并将这些数字的7段解码值输出到Display
信号上。它可以很容易地适用于驱动多路复用显示器,或者添加诸如信号之类的功能,以指示何时完成生成显示值。
我将保留可选功能,例如前导零消隐,或者在处理完成后,如果Start仍然很高,则避免重新触发。