Search code examples
vhdlfpgamodelsimquartus

Can signals be used instead of hard coding values multiple times?


I'm a student learning VHDL and have a pretty basic question.

I've read that signal assignments don't take place immediately. So the following would not work as expected:

x <= y;
z <= not x;

So I understand that assignments are not immediate / don't happen sequentially, but I have a question about passing signals to entities. Supposed I have the following code:

architecture struct of mips is
begin
    controller: entity work.controller port map(opD         => instrD(31 downto 26),          
                                                functD      => instrD(5 downto 0));   

    datapath:   entity work.dataPath port map(opD         => instrD(31 downto 26),                      
                                              functD      => instrD(5 downto 0));

end;

I'm used to trying to avoid code duplication and hard coding things in other languages, so hard coding the opD and functD values in the above code bothers me.

What I'm wondering is if I can assign those values to an internal signal, like this:

architecture struct of mips is
    signal opD:    STD_LOGIC;
    signal functD: STD_LOGIC;
begin
    signal opD    <= instrD(31 downto 26);
    signal functD <= instrD(5 downto 0);

    controller: entity work.controller port map(opD         => opD,          
                                                functD      => functD);

    datapath:   entity work.dataPath port map(opD         => opD,                      
                                              functD      => functD);    
end;

Would that work as expected (i.e. work exactly the same as the above code block), or would there be some sort of "delay" caused by the use of the signals that would make the two code blocks function differently?


Solution

  • I've read that signal assignments don't take place immediately.

    This is true, but I think you miss an important point, which is to know when they take place. Signals are updated when the process that generates them encounter a wait statement, or end (since there is an implicit wait on the process sensitivity list at the end of processes).

    So your example wouldn't work like you expect if you put it in a clocked process, but is perfectly valid in a combinational process with correct sensitivity list.

    architecture rtl of example is
        signal y_r : std_logic;
        signal z_r : std_logic;
        signal y   : std_logic;
        signal z   : std_logic;
     begin
        y <= x; -- immediately updated when x changes
        z <= not y; -- immediately updated when y changes, equivalent to z <= not x
    
        process(clk)
        begin
            if rising_edge(clk) then
                y_r <= x; -- y is updated when the clock rise, once this process finishes
                z_r <= not y_r; -- y still have the value it had when the process started executing
             end if;
        end process;
    end architecture rtl;
    

    So your final example, apart from the syntax errors, would work as you intend. There is a neat syntax that is better IMHO for that though:

    architecture struct of mips is
        alias opD is instrD(31 downto 26);
        alias functD is instrD(5 downto 0);
    begin
    
        controller: entity work.controller port map(opD         => opD,          
                                                    functD      => functD   
    
        datapath:   entity work.dataPath port map(opD         => opD,                      
                                                  functD      => functD;     
    end;