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

How to latch a register value assigned in present state until next state?

Altera_Forum
Honored Contributor II
2,978 Views

Hi:):), 

I'll be grateful and appreciate if somebody can help me to solve my problem. 

 

I'm a dummy in verilog and FPGA. Currently, I'm using Altera Cyclone IV to develop a IO card with PCI bus interface. I develop my code using state machine.. 

In my design, there have a simple acknowledgement handshaking between the PC and my firmware. When there is a command received from PC, the command will be decode in firmware and doing a particular task. Once the task is completed, a specific value, e.g. 0x80 (defined as "acknowledgment" ) is assigned to a register. This register is expected to hold 0x80 value until this value is being read by PC. 

 

The problem that I facing is that: 

The register with value 0x80 can hold its value only in the state where it being assigned to this value. This value no longer valid for next state. 

 

As I understanding for reg data type in verilog/system verilog: 

They retain their value till next value is assigned to them. 

 

I wondering what's wrong in my code causing such weird behaviour of register. 

The original source code file and signaltap file are attached together in this thread.  

I'm really look forward and appreciate somebody can look into my code and point out the wrong part to clear my doubts. Thank you!:-P
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
1,762 Views

 

--- Quote Start ---  

Hi:):), 

I'll be grateful and appreciate if somebody can help me to solve my problem. 

 

I'm a dummy in verilog and FPGA. Currently, I'm using Altera Cyclone IV to develop a IO card with PCI bus interface. I develop my code using state machine.. 

In my design, there have a simple acknowledgement handshaking between the PC and my firmware. When there is a command received from PC, the command will be decode in firmware and doing a particular task. Once the task is completed, a specific value, e.g. 0x80 (defined as "acknowledgment" ) is assigned to a register. This register is expected to hold 0x80 value until this value is being read by PC. 

 

The problem that I facing is that: 

The register with value 0x80 can hold its value only in the state where it being assigned to this value. This value no longer valid for next state. 

 

As I understanding for reg data type in verilog/system verilog: 

They retain their value till next value is assigned to them. 

 

I wondering what's wrong in my code causing such weird behaviour of register. 

The original source code file and signaltap file are attached together in this thread.  

I'm really look forward and appreciate somebody can look into my code and point out the wrong part to clear my doubts. Thank you!:-P 

--- Quote End ---  

 

 

*Some information to add up: Quartus version that being used is 13.0.1
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

You didn't specify which is the register you have problems with. I guess you mean state_present/state_next 

Taking a look at your code I see you assign the state register in a asynchronous process (always@(<signals>)) which is reasonably used only for combinatorial logic 

You must change it with a clocked one: always@(posedge clk, negedge rstn) 

Also change state_next=... assignments with state_next <= ...
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

Hi Cris72, 

 

Thanks for advices.  

My state machine is working fine. 

The register that I had problem with is "ack_tmpReg".
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

I confirm you need to clock the state machine process. 

You are supposed to write a software program: you are describing hardware.
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

Hi Cris72, 

Thank you again for the advices^^. 

I had tried out your suggestion. 

There are three always block in my code: 

1. The 1st always block is updating the PRESENT STATE to NEXT STATE. 

2. The 2nd always block is assigning NEXT STATE based on input signals. 

3. The 3rd always block is processing the output based on PRESENT STATE. 

 

 

The trial that i had done: 

1. Clock the state machine process only by changing the sensitivity list of the 2nd always block to "posedge clk" and changed the all blocking assignment to non-blocking assignment in 2nd always block. 

2. a. Clock the state machine process only by changing the sensitivity list of the 2nd always block to "posedge clk" and changed the all blocking assignment to non-blocking assignment in 2nd always block. AND-> 

b. changing the sensitivity list of the 3rd always block to "negedge clk" and remained all the blocking assignment in 3rd always block . 

The source code file for the trial(2) is attached in this reply post. 

 

 

The reason that i didn't change the blocking assignment in 3rd always block to non-blocking assignment is because of I'm using function call in the 3rd always block, and there will be compilation error if i mixed using non-blocking assignment and blocking assignment for verilog function. 

 

 

The result of the trial: 

trial(1): Problem still remain the same where the "ack_tmpReg" register can't hold it value as described in this thread. 

trial(2): "ack_tmpReg" register can behave normally as it can latch its value until the next change of its value in the code. 

 

 

Hopefully that you can give me your advices to clear my doubts on: 

1. Is it a good verilog practice to change my code as in trial(2) where using the blocking assignment for a clock based always block? 

2. Can I process the output logic (the 3rd always block) as asynchronous process as in trial(1)? 

3. may i know why there is very important to clock the state machine? 

 

 

Thank a lot!^^
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

 

--- Quote Start ---  

 

1. Is it a good verilog practice to change my code as in trial(2) where using the blocking assignment for a clock based always block? 

 

--- Quote End ---  

 

The good verilog practice is: 

- clocking all the processes involving register assignments 

- use the same clock edge (i.e. posedge) for all processes, unless in very special cases 

- don't use blocking assignments. Use <= 

 

I have taken a look at your code, but I don't have the time to analyze it right now. 

From what I understand the 1st always process is useless. You probably can get rid of state_next and use only state_present. 

Moreover, processing state_next causes the state to change with one clock delay and this could affect the timing involved in the 3rd process. 

 

 

 

--- Quote Start ---  

 

2. Can I process the output logic (the 3rd always block) as asynchronous process as in trial(1)? 

3. may i know why there is very important to clock the state machine? 

 

--- Quote End ---  

 

With asynchronous assignments the synthesis tool is likely to generate purely combinatorial logic and this  

would lead to glitches in outputs, since not all signals change at the same time. 

This could be hidden during simulation, but will certainly get out on actual hardware and cause problems. 

Same applies to process sensitivity list: it serves mainly for simulation purposes and for code readibility.  

In the real world, when you synthesize verilog code and deploy it into actual hardware, it will behave according to the switching characteristics of the logic gates. 

For example, if you have R = a and (b or c and (...)) , R will always switch according to this rule, changing whenever one of the input signals changes: even if you specified only signal 'a' in the sensitivity list.
0 Kudos
Altera_Forum
Honored Contributor II
1,762 Views

Hi Cris72, 

 

Thanks again for your guidance!^^ 

I have change my code accordingly to your suggestion: 

1. Get rid of state_next and use only state_present. 

2. Clocking all the processes involving register assignments. 

3. Use non-blocking assignment [<=]. 

 

My code is working fine now in which the register value can be latched. 

 

 

--- Quote Start ---  

 

The reason that i didn't change the blocking assignment in 3rd always block to non-blocking assignment is because of I'm using function call in the 3rd always block, and there will be compilation error if i mixed using non-blocking assignment and blocking assignment for verilog function. 

 

--- Quote End ---  

 

 

Please ignore the above statement in my previous post. I have found out that I have mixed using the blocking "=" and non-blocking assignment "<=" to a same register, the same register is appear in an always block and a function, that register is being initialize/reset in an always block and it's assigned to a value when calling a particular function.  

 

The compilation error that i stated previously have been resolve by using a verilog task to initialize/reset the register. I'm not sure whether this is a correct way to using a verilog task or verilog function. I have solved this problem as described in this thread but I have facing another problem about the verilog function. I'll post and describe the verilog function problem in another thread.  

 

Anyway, thanks a lot!
0 Kudos
Reply