Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17093 Discussions

Issues with making a pipeline register in VHDL

Altera_Forum
Honored Contributor II
11,848 Views

I am currently having an issue with making a pipeline register in VHDL. A pipeline register is simply a register that connects two portions of a CPU pipeline together. It is easier to explain in code then on text in terms of its functions, so here is the code.  

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity IF_to_ID_registers is port ( fetched_instruction : in std_logic_vector(31 downto 0); clear: in std_logic; writeregister : in std_logic; send_zeros_instead : in std_logic; clk : in std_logic; output_instruction : out std_logic_vector(31 downto 0) ); end IF_to_ID_registers; architecture Behavioral of IF_to_ID_registers is signal instruction_register : std_logic_vector(31 downto 0); -- The internal register begin process(fetched_instruction, writeregister, clk, send_zeros_instead) begin if ( clk = '0' AND writeregister = '1') then instruction_register <= fetched_instruction; -- Write the value into the register end if; if (rising_edge(clk)) then if (send_zeros_instead = '1') then output_instruction <= (others => '0'); -- Output zeros instead else output_instruction <= instruction_register; -- Output the register end if; end if; if (clear = '1') then instruction_register <= (others => '0'); -- Clear the register end if; end process; end Behavioral;  

 

The issue I have with this code is that during compilation I get the following error messages. 

 

Warning (10492): VHDL Process Statement warning at PipelineRegisters.vhd(42): signal "clear" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10631): VHDL Process Statement warning at PipelineRegisters.vhd(25): inferring latch(es) for signal or variable "instruction_register", which holds its previous value in one or more paths through the process Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled Warning (14025): LATCH primitive "IF_to_ID_registers:inst10|instruction_register" is permanently disabled  

 

I am wondering what I did wrong. It seems like the issue stems from the instruction_register signal, but I cant tell what the issue is.
0 Kudos
43 Replies
Altera_Forum
Honored Contributor II
2,360 Views

may be this will answer your question: 

 

if clear = '1' then output_instruction <= (others => '0'); elsif rising_edge(clk) then if send_zeros_instead = '1' then output_instruction <= (others => '0'); elsif write_register = '1' then output_instruction <= fetch_instruction; end if; end if;
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

It does not. I need the register to be connected to a 2way_mux that chooses between sending the contents of the register or just to send zeros.

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

Well to me it does either send zeros or the register value. You need to explain what actually you want the circuit to do in clear description otherwise we keep going in circles.

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

I decided to attach an image showing what I want done. All I want is the second register gone. Then it will work properly.

(Virus scan in progress ...)
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

Here we go: 

 

signal instruction_register : std_logic_vector(31 downto 0); begin process(clear,clk) begin if clear = '1' then instruction_register <= (others => '0'); elsif rising_edge(clk) then if write_register = '1' then instruction_register <= fetched_instruction; end if; end if; end process; output_instruction <= (others => '0') when send_zeros_instead = '1' else instruction_register;
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

Thanks, rtl viewer is good now. Time to see if my timing issue is fixed

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

I am still getting bad timing issues. Is there any way how I can modify the code so that it writes whenever the clock is 0, so it is a level based write. 

 

EDIT: I changed the if rising_edge(clk) then to if clk = '0' then

 

I now get latches. Is that ok, or should I change it back.
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

if clock='0' then 

 

Is very very bad design practice. You're creating no registers at all, just latches like you saw.
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

What is the issue with using latches though?

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

What do mean by having timing issues. You only have 32 registers in the above code. your final output is not registered. Moreover, the 32 registers are not fed from any other registers as far as above code tells so Quartus can't report on any timing violations.

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

By timing issues I don't mean in context of the register but in context of my whole design. Since I am making a pipelined CPU, timing is crucial. I currently have an issue that causes my processor to output a certain number sequence forever after a certain point. I am checking right now if the issue is from the General purpose register file.

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

Ok I found the issue. The register file is stuck. It continues to read the same value every clock cycle even though the register_to_read is 0. Here is the register code I have. 

 

ibrary IEEE; use IEEE.STD_LOGIC_1164.ALL; entity default_registers is port ( input : in std_logic_vector(31 downto 0); register_to_write : in std_logic_vector (4 downto 0); write_to_register : in std_logic; register_to_read_a : in std_logic_vector (4 downto 0); register_to_read_b : in std_logic_vector (4 downto 0); clk : in std_logic; output0 : out std_logic_vector(31 downto 0); output1 : out std_logic_vector(31 downto 0) ); end default_registers; architecture Behavioral of default_registers is signal register1 : std_logic_vector (31 downto 0); signal register2 : std_logic_vector (31 downto 0); signal register3 : std_logic_vector (31 downto 0); signal register4 : std_logic_vector (31 downto 0); signal register5 : std_logic_vector (31 downto 0); signal register6 : std_logic_vector (31 downto 0); signal register7 : std_logic_vector (31 downto 0); signal register8 : std_logic_vector (31 downto 0); signal register9 : std_logic_vector (31 downto 0); signal register10 : std_logic_vector (31 downto 0); signal register11 : std_logic_vector (31 downto 0); signal register12 : std_logic_vector (31 downto 0); signal register13 : std_logic_vector (31 downto 0); signal register14 : std_logic_vector (31 downto 0); signal register15 : std_logic_vector (31 downto 0); signal register16 : std_logic_vector (31 downto 0); signal register17 : std_logic_vector (31 downto 0); signal register18 : std_logic_vector (31 downto 0); signal register19 : std_logic_vector (31 downto 0); signal register20 : std_logic_vector (31 downto 0); signal register21 : std_logic_vector (31 downto 0); signal register22 : std_logic_vector (31 downto 0); signal register23 : std_logic_vector (31 downto 0); signal register24 : std_logic_vector (31 downto 0); signal register25 : std_logic_vector (31 downto 0); signal register26 : std_logic_vector (31 downto 0); signal register27 : std_logic_vector (31 downto 0); signal register28 : std_logic_vector (31 downto 0); signal register29 : std_logic_vector (31 downto 0); signal register30 : std_logic_vector (31 downto 0); signal register31 : std_logic_vector (31 downto 0); begin process(clk) begin --output0 <= (others => '0'); --output1 <= (others => '0'); if (rising_edge(clk)) then if write_to_register = '1' then case register_to_write is when "00000" => -- Do nothing since register0 is always zero when "00001" => register1 <= input; when "00010" => register2 <= input; when "00011" => register3 <= input; when "00100" => register4 <= input; when "00101" => register5 <= input; when "00110" => register6 <= input; when "00111" => register7 <= input; when "01000" => register8 <= input; when "01001" => register9 <= input; when "01010" => register10 <= input; when "01011" => register11 <= input; when "01100" => register12 <= input; when "01101" => register13 <= input; when "01110" => register14 <= input; when "01111" => register15 <= input; when "10000" => register16 <= input; when "10001" => register17 <= input; when "10010" => register18 <= input; when "10011" => register19 <= input; when "10100" => register20 <= input; when "10101" => register21 <= input; when "10110" => register22 <= input; when "10111" => register23 <= input; when "11000" => register24 <= input; when "11001" => register25 <= input; when "11010" => register26 <= input; when "11011" => register27 <= input; when "11100" => register28 <= input; when "11101" => register29 <= input; when "11110" => register30 <= input; when "11111" => register31 <= input; end case; end if; elsif(falling_edge(clk)) then case register_to_read_a is when "00000" => -- Do nothing since register0 is always zero when "00001" => output0 <= register1; when "00010" => output0 <= register2; when "00011" => output0 <= register3; when "00100" => output0 <= register4; when "00101" => output0 <= register5; when "00110" => output0 <= register6; when "00111" => output0 <= register7; when "01000" => output0 <= register8; when "01001" => output0 <= register9; when "01010" => output0 <= register10; when "01011" => output0 <= register11; when "01100" => output0 <= register12; when "01101" => output0 <= register13; when "01110" => output0 <= register14; when "01111" => output0 <= register15; when "10000" => output0 <= register16; when "10001" => output0 <= register17; when "10010" => output0 <= register18; when "10011" => output0 <= register19; when "10100" => output0 <= register20; when "10101" => output0 <= register21; when "10110" => output0 <= register22; when "10111" => output0 <= register23; when "11000" => output0 <= register24; when "11001" => output0 <= register25; when "11010" => output0 <= register26; when "11011" => output0 <= register27; when "11100" => output0 <= register28; when "11101" => output0 <= register29; when "11110" => output0 <= register30; when "11111" => output0 <= register31; end case; case register_to_read_b is when "00000" => -- Do nothing since register0 is always zero when "00001" => output1 <= register1; when "00010" => output1 <= register2; when "00011" => output1 <= register3; when "00100" => output1 <= register4; when "00101" => output1 <= register5; when "00110" => output1 <= register6; when "00111" => output1 <= register7; when "01000" => output1 <= register8; when "01001" => output1 <= register9; when "01010" => output1 <= register10; when "01011" => output1 <= register11; when "01100" => output1 <= register12; when "01101" => output1 <= register13; when "01110" => output1 <= register14; when "01111" => output1 <= register15; when "10000" => output1 <= register16; when "10001" => output1 <= register17; when "10010" => output1 <= register18; when "10011" => output1 <= register19; when "10100" => output1 <= register20; when "10101" => output1 <= register21; when "10110" => output1 <= register22; when "10111" => output1 <= register23; when "11000" => output1 <= register24; when "11001" => output1 <= register25; when "11010" => output1 <= register26; when "11011" => output1 <= register27; when "11100" => output1 <= register28; when "11101" => output1 <= register29; when "11110" => output1 <= register30; when "11111" => output1 <= register31; end case; end if; end process; end Behavioral;
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

I have come to believe you mean your logic is not working rather than you have register timing violations and that you can only correct your design logic by latching when clock = 0 .etc. 

 

In principle with so much resource as in any modern fpga you should be able to do anything on clock edge except the impossible!! 

 

You should avoid latches in FPGAs. FPGAs are designed for logic decisions to be sampled on clock edge to avoid glitches in between edges. Some advanced designers may go for few latches but I don't see any clear reason to believe that you must have a latch instead of register.  

 

You will need to rethink of all your logic in terms of clock edge and manage accordingly. Yes you will have latency problems but this can be tackled through the way you design what you want to achieve. 

 

I will be surprised if a latch based design in the hands of a beginner will work.
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

Well in this case, what do you believe is the solution to fix the problem?

0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

First I don't recommend using rising edge and falling edge unless there is good reason. Second you better not use elsif but start a new process or use same one process. 

 

But most important issue which may be not what you actually intend is that you are assigning to same outputs in a case statement for register_to_read_a 

and then another case statement on register_to_read_b.  

Being sequential the last case takes priority. Is that what you wanted? 

 

edit: sorry you have two outputs and not one as I thought....
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

you don't have register 0 so when reg_to_write is 0 what should be the value? 

it will just stay at its last value.
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

You were right. Once I changed the assignment, I managed to get that to work. Now I have another problem. Since I need to register file to write on the first half of the clock and read on the second half. I am wondering how to do it. So far I have this code: 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity register_32bit is port ( input : in std_logic_vector(31 downto 0); writeregister : in std_logic; clk : in std_logic; output : out std_logic_vector(31 downto 0) ); end register_32bit; architecture Behavioral of register_32bit is begin process(input, writeregister, clk) begin if (rising_edge(clk) and writeregister = '1') then output <= input; end if; end process; end Behavioral; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity default_registers is port ( input : in std_logic_vector(31 downto 0); register_to_write : in std_logic_vector (4 downto 0); write_to_register : in std_logic; register_to_read_a : in std_logic_vector (4 downto 0); register_to_read_b : in std_logic_vector (4 downto 0); clk : in std_logic; output0 : out std_logic_vector(31 downto 0); output1 : out std_logic_vector(31 downto 0) ); end default_registers; architecture Behavioral of default_registers is signal register1 : std_logic_vector (31 downto 0); signal register2 : std_logic_vector (31 downto 0); signal register3 : std_logic_vector (31 downto 0); signal register4 : std_logic_vector (31 downto 0); signal register5 : std_logic_vector (31 downto 0); signal register6 : std_logic_vector (31 downto 0); signal register7 : std_logic_vector (31 downto 0); signal register8 : std_logic_vector (31 downto 0); signal register9 : std_logic_vector (31 downto 0); signal register10 : std_logic_vector (31 downto 0); signal register11 : std_logic_vector (31 downto 0); signal register12 : std_logic_vector (31 downto 0); signal register13 : std_logic_vector (31 downto 0); signal register14 : std_logic_vector (31 downto 0); signal register15 : std_logic_vector (31 downto 0); signal register16 : std_logic_vector (31 downto 0); signal register17 : std_logic_vector (31 downto 0); signal register18 : std_logic_vector (31 downto 0); signal register19 : std_logic_vector (31 downto 0); signal register20 : std_logic_vector (31 downto 0); signal register21 : std_logic_vector (31 downto 0); signal register22 : std_logic_vector (31 downto 0); signal register23 : std_logic_vector (31 downto 0); signal register24 : std_logic_vector (31 downto 0); signal register25 : std_logic_vector (31 downto 0); signal register26 : std_logic_vector (31 downto 0); signal register27 : std_logic_vector (31 downto 0); signal register28 : std_logic_vector (31 downto 0); signal register29 : std_logic_vector (31 downto 0); signal register30 : std_logic_vector (31 downto 0); signal register31 : std_logic_vector (31 downto 0); begin process(clk, register_to_write, register_to_read_a, register_to_read_b, write_to_register) begin --output0 <= (others => '0'); --output1 <= (others => '0'); if falling_edge(clk) then if write_to_register = '1' then case register_to_write is when "00000" => -- Do nothing since register0 is always zero when "00001" => register1 <= input; when "00010" => register2 <= input; when "00011" => register3 <= input; when "00100" => register4 <= input; when "00101" => register5 <= input; when "00110" => register6 <= input; when "00111" => register7 <= input; when "01000" => register8 <= input; when "01001" => register9 <= input; when "01010" => register10 <= input; when "01011" => register11 <= input; when "01100" => register12 <= input; when "01101" => register13 <= input; when "01110" => register14 <= input; when "01111" => register15 <= input; when "10000" => register16 <= input; when "10001" => register17 <= input; when "10010" => register18 <= input; when "10011" => register19 <= input; when "10100" => register20 <= input; when "10101" => register21 <= input; when "10110" => register22 <= input; when "10111" => register23 <= input; when "11000" => register24 <= input; when "11001" => register25 <= input; when "11010" => register26 <= input; when "11011" => register27 <= input; when "11100" => register28 <= input; when "11101" => register29 <= input; when "11110" => register30 <= input; when "11111" => register31 <= input; end case; end if; case register_to_read_a is when "00000" => output0 <= (others => '0'); when "00001" => output0 <= register1; when "00010" => output0 <= register2; when "00011" => output0 <= register3; when "00100" => output0 <= register4; when "00101" => output0 <= register5; when "00110" => output0 <= register6; when "00111" => output0 <= register7; when "01000" => output0 <= register8; when "01001" => output0 <= register9; when "01010" => output0 <= register10; when "01011" => output0 <= register11; when "01100" => output0 <= register12; when "01101" => output0 <= register13; when "01110" => output0 <= register14; when "01111" => output0 <= register15; when "10000" => output0 <= register16; when "10001" => output0 <= register17; when "10010" => output0 <= register18; when "10011" => output0 <= register19; when "10100" => output0 <= register20; when "10101" => output0 <= register21; when "10110" => output0 <= register22; when "10111" => output0 <= register23; when "11000" => output0 <= register24; when "11001" => output0 <= register25; when "11010" => output0 <= register26; when "11011" => output0 <= register27; when "11100" => output0 <= register28; when "11101" => output0 <= register29; when "11110" => output0 <= register30; when "11111" => output0 <= register31; end case; case register_to_read_b is when "00000" => output1 <= (others => '0'); when "00001" => output1 <= register1; when "00010" => output1 <= register2; when "00011" => output1 <= register3; when "00100" => output1 <= register4; when "00101" => output1 <= register5; when "00110" => output1 <= register6; when "00111" => output1 <= register7; when "01000" => output1 <= register8; when "01001" => output1 <= register9; when "01010" => output1 <= register10; when "01011" => output1 <= register11; when "01100" => output1 <= register12; when "01101" => output1 <= register13; when "01110" => output1 <= register14; when "01111" => output1 <= register15; when "10000" => output1 <= register16; when "10001" => output1 <= register17; when "10010" => output1 <= register18; when "10011" => output1 <= register19; when "10100" => output1 <= register20; when "10101" => output1 <= register21; when "10110" => output1 <= register22; when "10111" => output1 <= register23; when "11000" => output1 <= register24; when "11001" => output1 <= register25; when "11010" => output1 <= register26; when "11011" => output1 <= register27; when "11100" => output1 <= register28; when "11101" => output1 <= register29; when "11110" => output1 <= register30; when "11111" => output1 <= register31; end case; end if; end process; end Behavioral;  

 

I am wondering if the pipeline register solution you made before (To solve the send_zeros_instead problem) could be modified to make it work.
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

 

--- Quote Start ---  

...Now I have another problem.... 

I am wondering if... could be modified to make it work. 

--- Quote End ---  

 

 

I guess you're trying to do the second step before the first. 

 

Remember one of the first replies to your request: 

 

 

--- Quote Start ---  

 

... 

First draw schema 

Second, describe it in VHDL 

... 

--- Quote End ---  

 

 

Imho a successful RTL has to be done by a Top-Down approach. 

With that in mind the components should fit exactly together, comprising the solution. 

 

1. Make a high-level concept/specification 

I guess you did that 

 

2. Make a detailled concept/specification (schematic and/or timing diagram) 

I guess you lack on that 

 

3. Implement the detailled concept/specification in HDL 

This is where you're actually a bit lost (because of lacking a clear specification) 

 

4. Verify your design against your specification 

This would be done after accomplishing the steps mentionend before 

 

 

Since you've "timing issues" I recommend to you to draw a timing diagram (i.e. in Visio) of the intended behaviour. 

 

 

- That way you'll communicate your specification clearly. 

- The forum can comment/help on that. 

- The forum can help to suggest correct respective alternative implementions 

- The forum respective you will be able to verify a concrete implementation. 

 

Maybe that looks like a step back at the current completion of your project but I'm pretty sure it isn't. ;)
0 Kudos
Altera_Forum
Honored Contributor II
2,360 Views

The specification for the register file calls for a write on the first half of the clock and a read for the second half. By using the falling clk edge I can get the write done succesfully, however my read won't function properly if it reads from the register the is going to be written. It will read the previous value. 

 

I will make a timing diagram of the current register file and how I want the register file to actually be.
0 Kudos
Altera_Forum
Honored Contributor II
2,293 Views

In that case write first on one edge then read on next edge. Use two separate processes for that but remeber to define what the output should be if wr_to_reg = 0

0 Kudos
Altera_Forum
Honored Contributor II
2,293 Views

The issue is that I cant make it read the edge after, because then it won't make it to the next pipeline register. It seems like that I have to make the read level-based

0 Kudos
Reply