Search code examples
if-statementvhdlclockfpgabit-shift

Shifting a logic vector to a bit


I have a 8-bit logic vector which should be shifted to an output.

constant CR:std_logic_vector:(7 downto 0):="11000000";

I'm trying to use an index for CR and each value belonging to the specified index...

Q<=CR(i);

I make count i for 0 to 7 by if statements to achieve shifting. But i have some doubts about that. Am i on the right way? Or is there a better way to do this like shifting functions. (Of course thiş operation should be synchronously with clock to be able to syntetize.)

I am so new at VHDL so thanks for the responses.


Solution

  • No, really, my comment to your question wasn't a solicitation for your accept an answer, I'm not that hard up for reputation points, honest.

    I meant it was hard for the potential question answerer to put any effort into your questions, plus your reputation won't increase either.

    It seem's a bit awkward putting a clock condition inside a loop statement (as opposed to a generate statement, so let's try a separate counter instead:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity shft_log_vec is
        port (
            rst:    in  std_logic;
            clk:    in  std_logic;
            Q:      out std_logic
        );
    end entity;
    
    architecture foo of shft_log_vec is
        constant CR:       std_logic_vector (7 downto 0) := "11000000";
        signal bit_ctr:  natural range CR'REVERSE_RANGE;  
    
    begin
    
        Q <= CR(bit_ctr);
    
    INDEX_CTR:
        process (clk, rst)
    
                               -- uninitialized default value is 0
        begin
            if rst = '1' then  -- will only run after a rst after the first time, use reset
               bit_ctr <= 0;
            elsif bit_ctr < CR'HIGH and rising_edge(clk) then  -- you could add an enable
               bit_ctr <= bit_ctr + 1;  -- integer arithmetic and comparison.
            else
            end if;
            -- because you need clock evaluation  for sequential operation in there, no loop 
            -- statement.  Reverse the bit order by using 'RANGE instead.
    
        end process;
    
    end architecture;
    
    library ieee;
    use ieee.std_logic_1164.all;
    
    entity tb_shft_log_vec is
    end entity;
    
    architecture foo of tb_shft_log_vec is
        signal rst: std_logic := '0';
        signal clk: std_logic := '0';
        signal Q:   std_logic;
    begin
    
    DUT:
        entity work.shft_log_vec 
            port map (
                rst => rst,
                clk => clk,
                Q  => Q
            );
    
    CLOCK:
        process 
        begin
            wait for 20 ns;
            clk <= not clk;
            if Now > 360 ns then
                wait;
            end if;
        end process;
    
    STIMULUS:
        process
        begin
            wait for 1 ns;
            rst <= '1';
            wait for 20 ns;
            rst <= '0';
            wait;
        end process;
    
    end architecture;
    

    Notice the pointer for CR is bit_ctr which is a constrained integer That counts from 0 to 7 then stops.

    If you wanted CR to come out in the reverse order (7 first) use 'RANGE and 'LOW instead of 'REVERSE_RANGE and 'HIGH.

    When the test bench is simulated we see the values of Q take on CR(0) to CR(7) each clock rising edge and stop waiting on a reset.

    tb_shft_log_vec.png (the image is a link to itself full size)

    Using a reset, there's an implication both the generator and the recipient know which clock edges to sample Q on. It may be prudent to switch to a synchronous reset share between both the generator and the recipient, depending on how far the signal Q is being routed (as across clock tree boundaries).

    Notice the similarities and differences to the answer to your previous question in the comment links. This way using attributes allows you to change the size of CR easily.