VHDL 计数和移位

VHDL count and shift

当load为1时,8位输入值从Data传给A。当S为1时,若A(0)为1,则B的值加1,A右移。当 A 的值变成 00000000 时,我们 make done 1 并转义。因此,输入值中1的个数以4位B显示,怎么办? 我尝试编写代码,但要到 1 周才能完成。

library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 entity one_counter is
     port (
         Output :out std_logic_vector (3 downto 0);
            Done : out std_logic;
            Input : in std_logic_vector(7 downto 0);
        load :in  std_logic;  
            S: in std_logic;
        clk,reset_n  :in  std_logic                           
    );
end entity;

 architecture behav of one_counter is 
    signal A :std_logic_vector (7 downto 0); 
    signal B :std_logic_vector (3 downto 0); 
    signal D : std_logic;
    signal state_out:std_logic_vector ( 1 downto 0);
    begin 
    process (reset_n, clk) is begin
            if (reset_n = '0') then
                state_out <= "00";             
            elsif rising_edge(clk) then  
                case (state_out) is
                    when "00" => if  (load = '1') then
                            state_out <="01"; end if;
                     when "01" => A <= Input;
                                    if (S = '1') then
                                    state_out <="10";  end if;
                     when "10" =>  
                        WHILE (A /= 0)  loop
                            if A(0) = '1' then
                                B <=  B+1;
                                Output <= B;
                            end if;
                            A <= '0' & A(7 downto 1);

                        END loop;
                        D <= '1';
                        Done <= D;
                        state_out <= "11";
                    when "11" => if( D = '0') then state_out <= "00"; end if;                           
             end case;
          end if; 
    end process;
end architecture;

根据您的规范,您应该在每个时钟周期只处理一位(如果 S 被断言为高电平),而您的代码会尝试一次处理所有位。此外,您还不了解 VHDL 语义:在执行 while 循环期间,信号 A 的值不会改变,您始终处理相同的位,如果 A 不为空,则循环是无限的。您可能应该阅读有关 VHDL 的书籍,以更好地了解信号更新的方式和时间。

无论如何,将您的规范转换为 VHDL 看起来非常简单,因为它们的形式是 if condition do that, else do this。转换为 VHDL 2008 的示例,假设 done 应在 a 为全零时(即使在重置后)被置为高电平:

use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;

entity one_counter is
  port(
    clk, reset_n, load, s:  in std_ulogic;
    input:                  in std_ulogic_vector(7 downto 0);
    output:                out std_ulogic_vector(3 downto 0);
    done:                  out std_ulogic
    );
end entity one_counter;

architecture behav of one_counter is 
  signal a: std_ulogic_vector(7 downto 0);
begin
  process(reset_n, clk) is
  begin
    if reset_n = '0' then
      a      <= (others => '0');
      output <= (others => '0');
    elsif rising_edge(clk) then
      if load = '1' then
        a      <= input;
        output <= (others => '0');
      elsif s = '1' then
        a      <= a srl 1;
        output <= output + a(0);
      end if;
    end if;
  end process;

  done <= nor a;
end architecture behav;

注意:如果您不想模拟多驱动器情况(tri-state 缓冲区...),最好不要使用已解析的 std_logicstd_logic_vector 类型。首选未解析的 std_ulogicstd_ulogic_vector 类型。有关详细信息,请参阅 .

注意:避免IEEE.STD_LOGIC_ARITHIEEE.STD_LOGIC_UNSIGNED,它们不是标准的。更喜欢 ieee.numeric_std_unsigned.

注意:如果 done 的行为不同(例如,复位后不置为高电平,或仅在一个时钟周期内置为高电平,或两者兼而有之),您将需要多一位存储空间来记住这一点load 发生了。适应您的确切规格。

注意:当load置为高电平时,output也会被重置;这在您自己的尝试中遗漏了,但似乎合乎逻辑。