Your clocks are all level sensitive and they are gated. To have edge sensitive clocks you should only have the clock in the if statement.
if rising_edge(clk) then
That will give you an edge triggered process.
Regards
process(clk, reset) -- reset only needed if it is asynchronous
begin
if reset = '1' then
--do async reset here
elsif rising_edge(clk) then
--synchronous code goes here
end if;
end process;
I highly suggest using the correct process templates for synchronous description:
Code:process(clk, reset) -- reset only needed if it is asynchronous begin if reset = '1' then --do async reset here elsif rising_edge(clk) then --synchronous code goes here end if; end process;
The reason you think your code works is that processes are only re-activated when a signal in the sensitivity list changes. Putting a signal in there that isnt even in the process makes it appear that you may be "clocking" the data, or making other things change only when you want them to, but in synthesis the sensitivity list is ignored and the logic is created only from the code inside the process. This is why you need to follow the correct templates from the start, or you end up having to re-write the lot when you want to put it in an FPGA.
There are plenty of textbooks and tutorials on the web about VHDL for logical design.
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 P_Fetch: Process (CLK) begin if (Reset /= '0') then PW <= "00000000000000000000000000000000"; --Set some initial register values here for simplicity & demonstration. -- PC <= "00000000000000000000000000000000"; Regfile(0) <="00000000000000000000000000000000"; --Register 0 gets the value '0' Regfile(1) <="00000000000000000000000000000111"; --Register 1 gets the value '7' Regfile(2) <="00000000000000000000000000101101"; --Register 2 gets the value '45' Regfile(3) <="00000000000000000000010000000000"; --Register 3 gets the value '1024' Regfile(4) <="00000000010001011010001000000000"; --Register 4 gets the value '4563456' Regfile(5) <="00000000000101010101010101001101"; --Register 5 gets the value '1398093' end if; if (Reset = '0' and rising_edge(CLK)) then PW <= Memory(CONV_INTEGER(s_PC)); s_PC <= s_PC + 1; PC <= s_PC; decodeReady <= '1', '0' after 15 ps; end if; end Process; P_Decode: Process(CLK) begin If reset='0' and rising_edge(CLK) and decodeReady = '1' then Instruction <= to_record (PW); --wait for 10 ps; exReady <= '1', '0' after 15 ps; end if; end Process; P_Execute: Process(CLK) variable temp: std_logic_vector (15 downto 0):= (others => '0'); begin If reset='0' and rising_edge(CLK) and exReady = '1' then B <= Regfile(CONV_INTEGER(Instruction.Rt)); Opcode <= Instruction.opcode; WrRdy <= not WrRdy; case Instruction.Opcode is when MSLL => A(4 downto 0) <= Instruction.SHAMT; A(31 downto 5)<= (others => '0'); Wrback <= '1'; when MSRL => A(4 downto 0) <= Instruction.SHAMT; A(31 downto 5)<= (others => '0'); Wrback <= '1'; when JR => PC <= Regfile(CONV_INTEGER(Instruction.Rs)); Wrback <= '0'; when LW => temp := (Instruction.Rs) + (Instruction.Immed); Wrback <= '0'; Regfile(CONV_INTEGER(Instruction.Rt)) <= Memory(CONV_INTEGER(temp)); when SW => temp := (Instruction.Rs) + (Instruction.Immed); Memory(CONV_INTEGER(temp)) := Regfile(CONV_INTEGER(Instruction.Rt)); Wrback <= '0'; when JUMP => PC(25 downto 0) <= Instruction.Address; Wrback <= '0'; when beq => if (Regfile(CONV_INTEGER(Instruction.Rs)) = Regfile(CONV_INTEGER(Instruction.Rt))) then PC(15 downto 0) <= s_PC(15 downto 0) + std_logic_vector(-1 + signed(Instruction.Immed)); end if; Wrback <= '0'; when bne => if (Regfile(CONV_INTEGER(Instruction.Rs)) /= Regfile(CONV_INTEGER(Instruction.Rt))) then PC(15 downto 0) <= s_PC(15 downto 0) + std_logic_vector(-1 + signed(Instruction.Immed)); end if; Wrback <= '0'; when others => A <= Regfile(CONV_INTEGER(Instruction.Rs)); Wrback <= '1'; end case; end if; end process; P_WriteBack: Process(CLK) begin If reset='0' and rising_edge(CLK) then if (Wrback = '1') then Regfile(CONV_INTEGER(Instruction.Rd)) <= Q(31 downto 0); --Wrback <= '1'; end if; end if; end Process;
Adam,
Barry and Tricky have both shown you multiple problems with your code. You keep refusing to change your code to use the correct templates for synthesizable VHDL code. On multiple occasions you've stated that your code is mostly working (in simulation), but doesn't update signal xxx properly and that changing it to use a proper template isn't important right now just fixing the update problem on those signals is important so you can hand your project in.
You've missed the point of your "project" it's not about handing in something that works in simulation (but isn't synthesizable or may not even work using another simulator). It's likely more about correctly using VHDL to model something. You can write models that are or are not synthesizable, either model is valid depending on the circumstances and when/how it is used. What you've written so far isn't even an accurate model.
The project you are trying to "fix" would result in an F grade, in my opinion, regardless of it simulating correctly and generating all the outputs. As written your code displays a complete misunderstanding of how to write VHDL processes. On a job interview if they ask you to write VHDL code for a resetable register with enable and you wrote down what you've posted. I would consider the interview to be over.
You should spend some time reading online VHDL tutorials. Many of them show examples of how to code registers/multiplexers/decodes/shifts etc.
Regards
If VHDL wasn't a prerequisite, why would you try to learn it "on-the-fly" for a project prior to final exams? You should have used a language you were already familiar with.
So the professor didn't specify that VHDL would be a requirement and the class wasn't a learning VHDL class. That professor is probably an example of how tenure is a bad thing.
Regardless I suggest you use the standard templates, you can look at the site with examples I posted in #13.
Regards
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 if (Reset /= '0') then PW <= "00000000000000000000000000000000"; --Set some initial register values here for simplicity & demonstration. PC <= "00000000000000000000000000000000"; Regfile(0) <="00000000000000000000000000000000"; --Register 0 gets the value '0' Regfile(1) <="00000000000000000000000000000111"; --Register 1 gets the value '7' Regfile(2) <="00000000000000000000000000101101"; --Register 2 gets the value '45' Regfile(3) <="00000000000000000000010000000000"; --Register 3 gets the value '1024' Regfile(4) <="00000000010001011010001000000000"; --Register 4 gets the value '4563456' Regfile(5) <="00000000000101010101010101001101"; --Register 5 gets the value '1398093' elsif rising_edge(CLK) then PW <= Memory(CONV_INTEGER(s_PC)); s_PC <= s_PC + 1; --PC <= s_PC; decodeReady <= '1'; end if; end Process; P_Decode: Process(CLK) begin If rising_edge(CLK) then If reset='0' and decodeReady = '1' then Instruction <= to_record (PW); --wait for 10 ps; exReady <= '1'; End if; end if; end Process;
For sync resets, the reset will only occur on a clock edge.
For async resets, the reset occurs as soon as the reset signal goes high.
THe problem with async resets, if they are connected to a truly async source (like a push button), when it comes out of reset it could then violate the setup and hold time of the register. So async resets are best avoided if they are truely asynchronous. If you synchronise the source reset, and connect it to the async resets of the registers, thats safe (and recommended in altera devices, as sync resets have to be emulated with a mux).
It is a massive improvement - it now uses the correct templates.
Now it is your job to debug why it doesnt work.
s_PC isn't in the reset condition therefore it will have no initial value
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if (Reset /= '0') then PW <= "00000000000000000000000000000000"; --Set some initial register values here for simplicity & demonstration. PC <= "00000000000000000000000000000000"; Regfile(0) <="00000000000000000000000000000000"; --Register 0 gets the value '0' Regfile(1) <="00000000000000000000000000000111"; --Register 1 gets the value '7' Regfile(2) <="00000000000000000000000000101101"; --Register 2 gets the value '45' Regfile(3) <="00000000000000000000010000000000"; --Register 3 gets the value '1024' Regfile(4) <="00000000010001011010001000000000"; --Register 4 gets the value '4563456' Regfile(5) <="00000000000101010101010101001101"; --Register 5 gets the value '1398093' elsif rising_edge(CLK) then PW <= Memory(CONV_INTEGER(s_PC)); s_PC <= s_PC + 1; --PC <= s_PC; decodeReady <= '1'; end if; end Process;
exReady will start out U or X and then will transition to 1 forever once the if condition is met. Don't you want it to go low again?
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 P_Decode: Process(CLK) begin If rising_edge(CLK) then If reset='0' and decodeReady = '1' then Instruction <= to_record (PW); --wait for 10 ps; exReady <= '1'; End if; end if; end Process;
s_PC isn't in the reset condition therefore it will have no initial value
Regfileisn't even used in the clocked portion of the IF, where is it used? If it's used in a different process then you need to remove it and put it in that other process.
PC also isn't used in this process.
decodeReady starts off U or X and then gets set to 1 permanently, don't you want it to return to 0 at some point?
exReady will start out U or X and then will transition to 1 forever once the if condition is met. Don't you want it to go low again?
PW will always be X as the PW in the first process will never be valid.
You should post all the code so we can look at more of the interaction between processes.
Regards,
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 entity MCProc is port (PC: out std_logic_vector (31 downto 0); PW: inout std_logic_vector (31 downto 0); CLK, Reset: in std_logic); end entity MCProc; Architecture First of MCProc is -- component ALU_32 port (A_bus, B_bus: in std_logic_vector(31 downto 0); Q_bus: out std_logic_vector(63 downto 0); Opcode: in Popcode; clk, reset: in std_logic); end component ALU_32; -- Signal A, B: std_logic_vector (31 downto 0):= (others => '0'); signal Q: std_logic_vector (63 downto 0):=(others => '0'); signal s_PC: std_logic_vector (31 downto 0):=(others => '0'); Signal Instruction: Tinstruction; Signal Opcode: Popcode; signal Wrback: bit; signal WrRdy: bit := '0'; signal decodeReady, exReady: bit := '0'; --Signal STATE: PSTATE; for ALU_32C: ALU_32 use entity work.ALU_32(Behavior); --INSTRUCTION CYCLE begin ALU_32C: ALU_32 port map (A, B, Q, Opcode, CLK, Reset); --PControl: Process P_Fetch: Process (CLK)
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 P_Execute: Process(CLK) variable temp: std_logic_vector (15 downto 0):= (others => '0'); begin If reset='0' and rising_edge(CLK) and exReady = '1' then B <= Regfile(CONV_INTEGER(Instruction.Rt)); Opcode <= Instruction.opcode; WrRdy <= not WrRdy; case Instruction.Opcode is when MSLL => A(4 downto 0) <= Instruction.SHAMT; A(31 downto 5)<= (others => '0'); Wrback <= '1'; when MSRL => A(4 downto 0) <= Instruction.SHAMT; A(31 downto 5)<= (others => '0'); Wrback <= '1'; when JR => PC <= Regfile(CONV_INTEGER(Instruction.Rs)); Wrback <= '0'; when LW => temp := (Instruction.Rs) + (Instruction.Immed); Wrback <= '0'; Regfile(CONV_INTEGER(Instruction.Rt)) <= Memory(CONV_INTEGER(temp)); when SW => temp := (Instruction.Rs) + (Instruction.Immed); Memory(CONV_INTEGER(temp)) := Regfile(CONV_INTEGER(Instruction.Rt)); Wrback <= '0'; when JUMP => PC(25 downto 0) <= Instruction.Address; Wrback <= '0'; when beq => if (Regfile(CONV_INTEGER(Instruction.Rs)) = Regfile(CONV_INTEGER(Instruction.Rt))) then PC(15 downto 0) <= s_PC(15 downto 0) + std_logic_vector(-1 + signed(Instruction.Immed)); end if; Wrback <= '0'; when bne => if (Regfile(CONV_INTEGER(Instruction.Rs)) /= Regfile(CONV_INTEGER(Instruction.Rt))) then PC(15 downto 0) <= s_PC(15 downto 0) + std_logic_vector(-1 + signed(Instruction.Immed)); end if; Wrback <= '0'; when others => A <= Regfile(CONV_INTEGER(Instruction.Rs)); Wrback <= '1'; end case; end if; end process;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 entity ALU_32 is port (A_bus, B_bus: in std_logic_vector(31 downto 0); Q_bus: out std_logic_vector(63 downto 0); Opcode: in Popcode; clk, reset: in std_logic); end entity ALU_32; -- architecture Behavior of ALU_32 is signal Overflow: std_logic; -- begin -- ALU_Exec: process(CLK)
I would start by making PW an in or an out. Inouts are only there for tri-state buffers and you only have those in FPGAs on the pins of the device. Internal connections should be in or out only. But from the code you've posted, I cannot see it used anywhere anyway.
Now we've given you instruction for the above code, you should be able to apply it all to your p_execute process.
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 begin if (Reset /= '0') then PW <= "00000000000000000000000000000000"; --HERE -- PC <= "00000000000000000000000000000000"; elsif rising_edge(CLK) then if (dojump = '1') then s_PC <= PC; else s_PC <= s_PC + 1; end if; PW <= Memory(CONV_INTEGER(s_PC)); --Here decodeReady <= '1'; end if; end Process;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 P_Decode: Process(CLK) begin If rising_edge(CLK) then If reset='0' and decodeReady = '1' then Instruction <= to_record (PW); -- function translates Program Word into decoded instruction exReady <= '1'; End if; end if; end Process;
Code VHDL - [expand] 1 If reset='0' and rising_edge(CLK) and exReady = '1' then
Code VHDL - [expand] 1 2 3 4 5 6 7 if reset = '1' then -- reset statements elsif rising_edge(clk) then if exReady then -- your enabled code end if; end if;
based on the two code snippets you should define a PW_int and use that instead. Then you add a PW <= PW_int and change PW to an output on the entity.
also this is a problem
Code VHDL - [expand] 1 If reset='0' and rising_edge(CLK) and exReady = '1' then
this is a gated clock and probably will throw and error in a synthesis tool. exReady should be in a if statement inside the rising_edge(CLK) if.
using an async reset the if structure should look something like this.
Code VHDL - [expand] 1 2 3 4 5 6 7 if reset = '1' then -- reset statements elsif rising_edge(clk) then if exReady then -- your enabled code end if; end if;
Regards
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?