使用LED输出实现10位移位寄存器

时间:2017-03-24 19:43:47

标签: vhdl shift-register

我正在尝试实现以下移位寄存器

entity MyShiftRegister is
    port(
        clock:   in  std_logic;
        DataIn:  in  std_logic_vector (9 downto 0); 
        Left:    in  std_logic;  --synchronous left rotate
        Right:   in  std_logic;  --synchronous right rotate
        Load:    in  std_logic;  --synchronous parallel load
        Clear:   in  std_logic;  -- synchronous clear
        DataOut: out std_logic_vector (9 downto 0);     

这是我到目前为止所拥有的

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

entity question2 is
    Port (
        led: buffer std_logic_vector (9 downto 0);
        clk: in std_logic;
        btnu: in std_logic;
        btnL: in std_logic;
        btnR: in std_logic ; 
        btnD: in std_logic;
        btnC: in std_logic 
     );
end question2;

architecture Behavioral of question2 is
    constant active: std_logic :='1';
    constant inactive: std_logic :='0';

    constant step_zero:  std_logic_vector(9 downto 0) :="0000000000";  
    constant step_one:   std_logic_vector(9 downto 0) :="0000000001";
    constant step_two:   std_logic_vector(9 downto 0) :="0000000010"; 
    constant step_three: std_logic_vector(9 downto 0) :="0000000100";
    constant step_four:  std_logic_vector(9 downto 0) :="0000001000";
    constant step_five:  std_logic_vector(9 downto 0) :="0000010000";
    constant step_six:   std_logic_vector(9 downto 0) :="0000100000";    
    constant step_seven: std_logic_vector(9 downto 0) :="0001000000";
    constant step_eight: std_logic_vector(9 downto 0) :="0010000000";
    constant step_nine:  std_logic_vector(9 downto 0) :="0100000000";
    constant step_ten:   std_logic_vector(9 downto 0) :="0100000000";

    signal DataIn: std_logic_vector (9 downto 0):= "1111111111";  
    signal Load: std_logic := btnD;
    signal Reset: std_logic; 
    signal Left: std_logic:= btnL;
    signal Right: std_logic:= btnR;
    signal DataOut: std_logic_vector := led (9 downto 0);
    signal Clear: std_logic:= btnU;
    signal speed_enable: std_logic; 
begin
    SpeedControl: process (clk)
        variable counter: integer range 0 to 10000000;
    begin
        speed_enable<=not active;  
        if Reset = Active then
            counter:= 0; 
        elsif (rising_edge (clk)) then 
            counter := counter + 1; 
            if (counter=10000000) then 
                speed_enable<= Active; 
                counter:=0; 
            end if; 
        end if; 
    end process; 

    shiftregister: process(clk, clear)
    begin
        if rising_edge (clk) then 
            if clear= active then 
                DataOut <= (others => '0');  
            elsif load = active then 
                DataOut <= DataIn ; 
            elsif Left = active then 
                DataOut <= DataOut(8 downto 0) & "1" ;
                if DataOut = "1000000000" then 
                    clear <= active;   
                elsif Right = active then 
                    DataOut <= DataOut (9 downto 1) & "1" ;
                    if DataOut = "0000000001" then 
                        clear <= active; 
                    end if; 
                end if; 
            end if; 
        end if;  
end process;

with DataOut select
    led <= step_one   when "0000",
           step_two   when "0001",
           step_three when "0010",
           step_four  when "0011",
           step_five  when "0100",
           step_six   when "0101",
           step_seven when "0110",
           step_eight when "0111",
           step_nine  when "1000", 
           step_ten   when "1001", 
           step_zero  when others;     
end Behavioral;

我如何左右旋转位并将其与我的LED输出相连。我正在考虑使用一个计数器,只是递增和递减向左或向右移位,但我不确定它是否仍然被认为是移位寄存器。

感谢

1 个答案:

答案 0 :(得分:1)

开始:

constant step_nine:  std_logic_vector(9 downto 0) :="0100000000";
constant step_ten:   std_logic_vector(9 downto 0) :="0100000000";

不正确。它应该是

constant step_nine:  std_logic_vector(9 downto 0) :="0100000000";
constant step_ten:   std_logic_vector(9 downto 0) :="1000000000";

但无论如何,这种方法非常容易出错。让我们简化它:

process(sel)
    variable selected_led : natural;
begin
    led <= (others => '0');
    selected_led := to_integer(unsigned(sel));
    if selected_led < led'length then
        led(selected_led) <= '1';
    end if;
end process;

如果led(selected_led) <= '1';无法合成,您可能需要将其更改为

for i in 0 to led'length-1 loop
    if (i = selected_led) then
        led(i) <= '1';
    end if;
end loop;

至于使用buffer端口。别。最好只使用inout。如果要读取out端口,请使用VHDL-2008进行编译,或在两者之间使用临时信号。

然后请注意,rightleft是VHDL中的关键字。你不应该使用它们

你想要的是非常简单和基本的VHDL。示例(使用VHDL-2008):

process(clock)
begin
    if rising'edge(clock) then
        if clear = '1' then
            data_out <= (others => '0');
        elsif load = '1' then
            data_out <= data_in;
        elsif right_rotate = '1' then
            data_out <= data_out(0) & data_out(data_out'length-1 downto 1);
        elsif left_rotate = '1' then
            data_out <= data_out(data_out'length-2 downto 0) &
                data_out(data_out'length-1);
        end if;
    end if;
end process;