【问题标题】:BCD Timer in VHDLVHDL 中的 BCD 定时器
【发布时间】:2018-05-26 20:11:58
【问题描述】:

不久前刚开始使用VHDL,出于好奇。

所以我试图在 spartan 3 board 上编写 BCD 计时器和

不知何故,我不知道为什么它一直显示“意外”错误。

所以如果我想拥有图片链接所示的功能, 如何修改代码?任何帮助将不胜感激。


(可点击)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity w3 is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           stp : in  STD_LOGIC;
           an : out  STD_LOGIC_VECTOR (3 downto 0);
           c : out  STD_LOGIC_VECTOR (6 downto 0));
end w3;

architecture timer of w3 is
signal div1 : integer range 0 to 499999 :=0; -- 100Hz
signal ck100hz : std_logic; -- 100Hz output
signal div2 : integer range 0 to 249999 :=0; -- 200Hz
signal ck200hz : std_logic; -- 200Hz output
signal div3 : integer range 0 to 124999 :=0; -- 400Hz
signal ck400hz : std_logic; -- 400Hz output
signal index : integer range 0 to 9 :=0;
signal scan : std_logic_vector (3 downto 0);
signal S : std_logic;
signal disp : std_logic_vector (3 downto 0);

begin
process begin
wait until rising_edge(clk);
if div1 < 499999 then
    ck100hz <= '0';
    div1 <= div1+1;
else 
    ck100hz <= '1';
    div1 <= 0;
end if;
if div2 < 249999 then
    ck200hz <= '0';
    div2 <= div2+1;
else
    ck200hz <= '1';
    div2 <= 0;
end if;
if div3 < 124999 then
    ck400hz <= '0';
    div3 <= div3+1;
else
    ck400hz <= '1';
    div3 <= 0;
end if;
end process;

process begin
wait until rising_edge(clk);
if rst = '1' then 
    index <= 0; 
end if;
if stp = '1' then 
    index <= index; 
end if;

if ck100hz = '1' then
    if index < 3 then index <= index+1;
        else index <= 0;
        if index < 4 and index > 7 then index <= index+1;
            else index <= 0;
            if index < 8 and index > 11 then index <= index+1;
                else index <= 0;
                if index < 12 and index > 15 then index <= index+1;
                    else index <= 0;
   end if;
      end if;
          end if;
             end if;
end if;
end process;

process begin
wait until rising_edge(clk);
if ck400hz = '1' then
    With scan select -- error unexpected With
        an <= an(0) when "00",
              an(1) when "01",
              an(2) when "10",
              an(3) when others;
end if;
end process;

process begin
wait until rising_edge(clk);
if ck200hz = '1' then
    With S select   -- error unexpected With
    disp <= index integer range 0 to 3 when "00",
            index integer range 4 to 7 when "01",
            index integer range 8 to 11 when "10",
            index integer range 12 to 15 when others;
end if;
end process;




with index select
    C <= "1000000" when 0, 
          "1111001" when 1, 
          "0100100" when 2, 
          "0110000" when 3, 
          "0011001" when 4, 
          "0010010" when 5, 
          "0000010" when 6,
          "1111000" when 7,       
          "0000000" when 8,
          "0011000" when 9;

end timer;

【问题讨论】:

  • with在顺序代码(例如进程)中不受支持。不需要那么多end if,使用elsif分支,尽量减少语句的深度。您不应该编写低活动代码。 scanS 没有驱动程序。
  • @Paebbels 我认为这是一个高活性代码?scanS 没有驱动程序是什么意思?我对elsif 不太熟悉,所以我使用了很多end if...好吧,如果with...select 不能在process 中使用,那么我可以使用什么来使该功能正常工作?感谢您的帮助。编辑:如果你不介意,请举个例子。
  • ISE 不支持 -2008 语法更改(顺序选择信号分配)。 ISE XST 也不支持并发选择信号分配。顺序选择的信号分配具有等效的 case 语句。这不是代码编写服务,也许您会问一个具体的问题? an 不对,一次只能有一个元素为真(分配整个事物)。 disp 未使用,您似乎没有 BCD 计数器,index 仅分配了 0 或其当前值。 div1div2div3 仅评估增量。

标签: timer vhdl counter bcd


【解决方案1】:

对于低活跃度:
如果是index = 0,您应该将0111111 分配给C。您必须启用几乎所有细分。现在您的内部计算将非常活跃。由于 PCB 布局,显示器本身是低活性的,因此在将其分配给 Cathode_n 端口之前,您应该反转整个 C 向量:Cathode_n &lt;= not C; 注意,我使用 _n 来指定低活性此端口的行为。

旧代码:

with index select
  C <= "1000000" when 0, 
       "1111001" when 1,
       -- ...
       "0011000" when 9;

这应该是编写纯高活性代码时的目标:

with index select
  C <= "0111111" when 0, 
       "0000110" when 1,
       -- ...
       "1100111" when 9;

  Cathode_n <= not C;

高活跃意味着:如果一个位是高的(1),那么一个东西是活跃的。在您的情况下,一个 7 段显示器的 LED 被激活。根据 PCB 设计,您必须驱动低电平 (0) 才能激活灯。这是低活跃度,因为低值会激活某些东西。

select 语句需要将位置分配给1 应该被启发,而不是要关闭的位置。更多的低活动信号应该被标记到代码中以表示不同的行为。只有顶级组件才能将高电平有效信号转换为低电平有效信号,反之亦然。这可确保您设计的内部部分是纯高活性的。


对于没有司机:
没有分配给Sscan。这两个信号分别是'U'"UUUU"

编辑:
每个信号分配都会在信号上创建一个驱动程序。目前,您的代码从未为Sscan 分配任何值。因此Sscan 的初始值成为信号的驱动值。您应该运行一个模拟并在您的波形中看到很多Us。

综合工具可能会报告:信号 S 已读取,但从未分配。


使用elsif

我重新格式化了你可怕的 if-then-else 结构:

if ck100hz = '1' then
  if index < 3 then
    index <= index+1;
  else
    index <= 0;
    if index < 4 and index > 7 then
      index <= index+1;
    else
      index <= 0;
      if index < 8 and index > 11 then
        index <= index+1;
      else
        index <= 0;
        if index < 12 and index > 15 then
          index <= index+1;
        else
          index <= 0;
        end if;
      end if;
    end if;
  end if;
end if;

现在我们看到,你的代码不能使用 elsif,因为你在下一个 if 语句之前的 else 分支中有赋值。另一方面,index &lt;= 0; 分配是多余的,可以删除:

if ck100hz = '1' then
  if index < 3 then
    index <= index+1;
  else
    if index < 4 and index > 7 then
      index <= index+1;
    else
      if index < 8 and index > 11 then
        index <= index+1;
      else
        if index < 12 and index > 15 then
          index <= index+1;
        else
          index <= 0;
        end if;
      end if;
    end if;
  end if;
end if;

现在我们可以将其转换为使用 elsif 分支:

if ck100hz = '1' then
  if index < 3 then
    index <= index + 1;
  elsif index < 4 and index > 7 then
    index <= index + 1;
  elsif index < 8 and index > 11 then
    index <= index + 1;
  elsif index < 12 and index > 15 then
    index <= index+1;
  else
    index <= 0;
  end if;
end if;

更具可读性,对吧?

接下来,让我们检查一下你在该语句中的表达式:

elsif index < 4 and index > 7 then

index 不能同时小于 4 和大于 7。所以让我们玩合成并优化掉无法到达的分支:

if ck100hz = '1' then
  if index < 3 then
    index <= index + 1;
  else
    index <= 0;
  end if;
end if;

好的,代码中的其他问题:

if rst = '1' then 
  index <= 0; 
end if;
if stp = '1' then 
  index <= index; 
end if;

if ck100hz = '1' then
  -- ...
end if;

重置应始终具有最高优先级。在你的情况下,例如stp 具有更高的优先级。在好的情况下,您只会浪费 FPGA 资源,在不好的情况下,综合无法将您的代码转换为 FPGA 中的原语。例如。具有匹配复位行为的触发器。

正确的实现:

if rst = '1' then 
  index <= 0; 
elsif stp = '1' then 
  index <= index; 
elsif ck100hz = '1' then
  -- ...
end if;

我认为现在,您有足够的输入来修复您的代码。

【讨论】:

  • @Paebbles 感谢您明确解释elsifrststp 问题,我现在得到了这些部分。但是我仍然不明白关于S 没有驱动程序的部分和scan,如果我想开这两个,我该怎么做?关于低活跃部分,Cathode_n &lt;= not C 这在代码中的什么位置?再次感谢您提出更具体的示例。
  • @doverdxJYGtw 我做了一些扩展。
  • @Paebbles 谢谢,我会继续努力的。谢谢你的解释让我有所收获。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多