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_logic
和 std_logic_vector
类型。首选未解析的 std_ulogic
和 std_ulogic_vector
类型。有关详细信息,请参阅 .
注意:避免IEEE.STD_LOGIC_ARITH
和IEEE.STD_LOGIC_UNSIGNED
,它们不是标准的。更喜欢 ieee.numeric_std_unsigned
.
注意:如果 done
的行为不同(例如,复位后不置为高电平,或仅在一个时钟周期内置为高电平,或两者兼而有之),您将需要多一位存储空间来记住这一点load
发生了。适应您的确切规格。
注意:当load
置为高电平时,output
也会被重置;这在您自己的尝试中遗漏了,但似乎合乎逻辑。
当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_logic
和 std_logic_vector
类型。首选未解析的 std_ulogic
和 std_ulogic_vector
类型。有关详细信息,请参阅
注意:避免IEEE.STD_LOGIC_ARITH
和IEEE.STD_LOGIC_UNSIGNED
,它们不是标准的。更喜欢 ieee.numeric_std_unsigned
.
注意:如果 done
的行为不同(例如,复位后不置为高电平,或仅在一个时钟周期内置为高电平,或两者兼而有之),您将需要多一位存储空间来记住这一点load
发生了。适应您的确切规格。
注意:当load
置为高电平时,output
也会被重置;这在您自己的尝试中遗漏了,但似乎合乎逻辑。