Search code examples
vhdlquartus

VHDL count and shift


8-bit input value is transferred from Data to A when load is 1. And when S becomes 1, if A(0) is 1, the value of B is increased by 1, and A is shift right. When the value of A becomes 00000000, we make done 1 and escape. Therefore, the number of 1's in the input value is displayed in 4-bit B. What should I do? I tried to code, but I can't until 1 week.

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;

Solution

  • According your specifications you should process one bit only per clock cycle (if S is asserted high), while your code tries to process all bits at once. Moreover you did not understand yet the VHDL semantics: during the execution of your while loop the value of signal A does not change, you are always processing the same bit and if A is not null the loop is infinite. You should probably read a book about VHDL to better understand how and when signals are updated.

    Anyway, the translation of your specifications into VHDL looks quite straightforward, as they are in the form if condition do that, else do this. Example of translation into VHDL 2008, assuming done shall be asserted high when a is all zeros (even after reset):

    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;
    

    Note: it is better to not use the resolved std_logic and std_logic_vector types if you do not want to model a multiple drive situation (tri-state buffers...). Prefer the unresolved std_ulogic and std_ulogic_vector types. For the details see, for instance, this Q&A.

    Note: avoid IEEE.STD_LOGIC_ARITH and IEEE.STD_LOGIC_UNSIGNED, they are not standard. Prefer ieee.numeric_std_unsigned.

    Note: if the behaviour of done shall be different (e.g. not asserted high after reset, or asserted high during only one clock period, or both) you will need one more bit of storage to remember that a load occurred. Adapt to your exact specifications.

    Note: output is also reset when load is asserted high; this was missing in your own attempt but seems logical.