title: VHDL Program counter using signals and previously made components?
body: <p>I am currently in the middle of a project where I am attempting to design a single cycle cpu. I am doing this without any pipe-lining, since that would greatly add to the complexity of the design. I am simply taking baby steps as I learn this. I find myself stuck at this portion where I am simply attempting to code a Program Counter(PC) using previously made components.</p>
  
  <p>The model of my design looks like this <a href="http://imgur.com/qaSp6y5" rel="nofollow">picture here</a>. Sorry, no idea why it came out dark, but if you click on it it shows correctly. The PC and theMUX are both 32 bit components, so I assume the adder is as well.</p>
  
  <p>Here is the code I have been given, my implementation begins at the begin statement on line 41.
  Pay no attention to it for now, its just a bunch of random gibberish I was attempting.</p>
  
  <pre><code>library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_arith.all;
  use ieee.std_logic_unsigned.all;
  ---------------------------------------------------
  entity pc_update is
      port( clk: in std_logic; -- clock
          incH_ldL: in std_logic; -- increment PC = PC + 4 when high,
                                  -- load PCInput when low
      PCInput: in std_logic_vector(31 downto 0); -- external input for PC
      InstrAddr: out std_logic_vector(31 downto 0) ); -- instruction address
  end entity pc_update;
  ----------------------------------------------------
  architecture pc_update_arch of pc_update is
      component register32 is
          port( clr: in std_logic; -- async. clear
                clk: in std_logic; -- clock
                 ld: in std_logic; -- load  
                  D: in std_logic_vector(31 downto 0); -- data input
                  Q: out std_logic_vector(31 downto 0) ); -- data output
      end component register32;
  
      component mux2to1_32 is
          port( sel: in std_logic; -- selection bit input
                 X0: in std_logic_vector(31 downto 0); -- first input
                  X1: in std_logic_vector(31 downto 0); -- second input
                   Y: out std_logic_vector(31 downto 0)); -- output
      end component mux2to1_32;
  
      signal PC_current: std_logic_vector(31 downto 0); -- the current state of PC reg        
      signal PC_add_4: std_logic_vector(31 downto 0); -- output from the adder 
      signal PC_next: std_logic_vector(31 downto 0); -- output from the MUX
  
      begin
  
      PC: register32 Port Map(
          clk, Q, clr, D);    
      MUX: mux2to1_32 Port Map(
          X0,sel,X1,Y);
  
      process (incH_ldL)
          begin
          wait until (clk = '1');
          if  incH_1dL = '0' then
              InstrAddr &lt;= X0;
          else InstrAddr &lt;= X1;
          end if;
      end process;
  
  end architecture pc_update_arch;
  </code></pre>
  
  <p>I am fairly new to this so I have only a faint idea of how signals work, and no idea how I am supposed to implement the components into the design. I am also confused that I wasnt asked to build the adder ahead of time. Is it now necessary to use it as a component im guessing?</p>
  
  <p>Anyhow, I have attempted different things that stumbled upon searching, such as the port mapping you see. But I always get some sort of error, currently the error im receiving is that objects Q, clr, and D are used but not declared. How do I declare them?
  If I get rid of those statements, the error simply repeats for objects X0, X1, and Y.
  Any help in the right direction would be greatly appreciated. Thanks guys!</p>
  
  <p>Also, just in case you need them,
  The register</p>
  
  <pre><code>library ieee ;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_unsigned.all;
  
  ---------------------------------------------------
  
  entity register32 is port( 
  clr: in std_logic; -- async. clear
  clk: in std_logic; -- clock
  ld: in std_logic; -- load
  D: in std_logic_vector(31 downto 0); -- data input
  Q: out std_logic_vector(31 downto 0) ); -- data output
  end entity register32;
  
  ----------------------------------------------------
  
  architecture register32_arch of register32 is
  
  begin 
      process(clk, clr)
      begin
          if clr = '1' then
              q &lt;= x"00000000";
          elsif rising_edge(clk) then
             if ld = '1' then
                 q &lt;= d;
             end if;
          end if;
      end process;
  END register32_arch;
  </code></pre>
  
  <p>and the MUX</p>
  
  <pre><code>library ieee ;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_unsigned.all;
  
  ---------------------------------------------------
  
  entity mux2to1_32 is
  port( sel: in std_logic; -- selection bit input
  X0: in std_logic_vector(31 downto 0); -- first input
  X1: in std_logic_vector(31 downto 0); -- second input
  Y: out std_logic_vector(31 downto 0)); -- output
  
  end entity mux2to1_32;
  
  ----------------------------------------------------
  
  architecture mux2to1_32_arch of mux2to1_32 is
  begin
  
      Y &lt;= X1 when (SEL = '1') else X0;
  
  end architecture mux2to1_32_arch; 
  </code></pre>
  
  <p><strong>EDIT</strong>
  Ok, NO idea if I did this correctly, but I rewrote the portmaps. I was having errors of port names (sel, clk, X0, X1..etc) being "used but not initialized. So that is why clr, clk and ld have initial values. Once again, no idea if that is correct, but it made the errors go away. I also realized I never added the register32 and mux2to1_32 VHDL files to my project, and after doing so got rid of the other errors I was having.</p>
  
  <p>So as stands, the code compiles, I have included in the project a VWF simulation file for testing, but I KNOW the results are gonna be incorrect.</p>
  
  <p>I dont know everything that is wrong yet, but I know I need to do something with PC_add_4. THis value needs to basically be (PC_current + 4), but Im not sure how to do this. </p>
  
  <p>Here is the updated portion of code(everything else is the same)</p>
  
  <pre><code>PC: register32 Port Map(
      clr =&gt; '0', 
      clk =&gt; '0',
       ld =&gt; '1',  
        Q =&gt; PC_current, 
        D =&gt; PC_next 
        );
  
  MUX: mux2to1_32 Port Map(
      sel =&gt; incH_ldL, 
      X0 =&gt; PCInput ,
      X1 =&gt; PC_add_4,
      Y =&gt;  PC_next 
      );
  
  process (incH_ldL)
      begin
      if (rising_edge(clk)) then
          if  incH_ldL = '0' then
              InstrAddr &lt;= PC_current;
          else InstrAddr &lt;= PC_add_4;
          end if;
      end if;
  end process;
  </code></pre>
  
  <p>And, in case they help, my list of errors..im guessing the pin related errors are because I dont have any hardware assignments made yet.</p>
  
  <ol>
  <li><p>Warning (10541): VHDL Signal Declaration warning at pc_update.vhd(38): used implicit default value for signal "PC_add_4" because signal was never assigned a value or an explicit default value. Use of implicit default value may introduce unintended design optimizations.</p></li>
  <li><p>Warning (10492): VHDL Process Statement warning at pc_update.vhd(61): signal "clk" is read inside the Process Statement but isn't in the Process Statement's sensitivity list</p></li>
  <li><p>Warning: Output pins are stuck at VCC or GND</p></li>
  <li><p>Warning: Design contains 34 input pin(s) that do not drive logic</p></li>
  <li><p>Warning: Found 32 output pins without output pin load capacitance assignment</p></li>
  <li><p>Warning: The Reserve All Unused Pins setting has not been specified, and will default to 'As output driving ground'.</p></li>
  <li><p>Warning: Can't generate programming files because you are currently using the Quartus II software in Evaluation Mode</p></li>
  <li><p>Warning: No paths found for timing analysis</p></li>
  <li><p>Critical Warning: No exact pin location assignment(s) for 66 pins of 66 total pins</p></li>
  </ol>
  
  <p><strong>SECOND EDIT</strong>
  So yeah I fixed up my code by adding
      PC_add_4 &lt;= (PC_current + 4 );
  after the port mappings, and adding "clk" to the process sensitivity list.
  However my waveforms in my simulation are still wrong I believe, as shown <a href="http://imgur.com/XGU8AmF" rel="nofollow">here</a>. </p>
  
  <p>It appears to be treating incH_lDL as a clear signal, rather than simply passing PCInput to InstrAddr. This is most likely due to my setting of it to a default '0' in the port map. I did this earlier because it was giving me "used but not declared" errors. Ill try messing with it and post my findings.</p>
  
  <p><strong>Third EDIT</strong></p>
  
  <p>I have edited my code as such:</p>
  
  <pre><code>process (incH_ldL, clk)
      begin
      if rising_edge(clk) then
          if  (incH_ldL = '0') then
              InstrAddr &lt;= PCInput ;
          else InstrAddr &lt;= PC_add_4;
          end if;
      end if;
  end process;
  </code></pre>
  
  <p>My simulation now shows that when incH_lDL = 0, PCInput is loaded into InstrAddr, however, when incH_lDL = 1, it simply loads the value '4', and doesnt increment at the start of every clock cycle like its supposed to...I need to make use of PC_current, but I am not sure how....sicne you cant assign one signal to another like "PC_current &lt;= PCInput". I will try some more things,in the mean time, any pointers would be greatly appreciated.</p>
  
  <p><strong>FOURTH EDIT</strong>
  THanks to anyone still reading this, and bearing through all the reading.</p>
  
  <p>I have attempted to use PC_next and PC_current in my implementation, but have run into "multiple constant drivers for net "PC_next" errors. </p>
  
  <p>MY process code:</p>
  
  <pre><code>process (incH_ldL, clk, PC_next, PC_current)
      begin
      if rising_edge(clk) then
          if  (incH_ldL = '0') then
              PC_next &lt;= PCInput;
          else PC_next  &lt;= PC_add_4;
          end if;
      end if; 
      InstrAddr &lt;= PC_current;    
  end process;
  </code></pre>
  
  <p>I am aware that this error comes when these assignments are made within loops? I am truly at a loss here at what to try next.</p>