Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
공지
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 토론

System Verilog: Can´t change value of a "struct" variable

Altera_Forum
명예로운 기여자 II
6,074 조회수

Hi, 

 

 

I´m newbie on Verilog, actually also in System Verilog, but worked long time ago with VHDL and C++ languages. 

I used a template of a Moore state machine from ALTERA for Verilog, and performed some changes in order to start the learning. 

 

However, during simulation, I can´t see any change at both the variables currentstate.level_main and currentstate.level_sub. I took the care to perform reset during simulation.  

 

module moore_mac ( input clk, data_in, reset, output reg data_out ); reg sub_state3, state ; parameter S0 = 3'b000, S1 = 3'b001, S2 = 3'b010, S3 = 3'b011 ; parameter S3_0 = 3'b100, S3_1 = 3'b101, S3_2 = 3'b110 ; typedef enum { SM0 , SM1 , SM2 , SM3 } STATE_MACHINE ; typedef enum { SM0_S, SM1_S, SM2_S, SM3_S } STATE_MACHINE_S ; typedef struct { reg Level_main ; reg Level_sub ; } FSM ; FSM CurrentState ; // Determine the next state always @ ( posedge clk or posedge reset ) begin if (reset) begin state <= S1 ; sub_state3 <= S3_0 ; CurrentState.Level_main <= S0 ; CurrentState.Level_sub <= S3_0 ; end else case (state) S0: state <= S1; S1: if (data_in) state <= S1; else state <= S2; S2: if (data_in) state <= S1; else state <= S3; S3: state <= next_state ( sub_state3 ) ; endcase end // Output depends only on the current state always @ (state) begin case (state) S0: data_out = S0 ; S1: data_out = S1 ; S2: data_out = S2 ; S3: data_out = S3 ; default: data_out = S0 ; endcase end // ******************************************************* // Gets next state, by assessing corresponding sub_state // ******************************************************* function next_state ; input reg valSubstateBefore ; reg valSubstateAfter ; if ( valSubstateBefore < S3_2 ) begin valSubstateAfter = valSubstateBefore + 1 ; state = state ; end else begin valSubstateAfter = S3_0 ; state = S0 ; end sub_state3 = valSubstateAfter ; next_state = state ; endfunction // ******************************************************* endmodule  

 

Thanks in advance. 

 

Andre
0 포인트
23 응답
Altera_Forum
명예로운 기여자 II
3,669 조회수

Thats because you only assign them values in the reset state.

0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Thanks Trcky, but after reset state, the registers wouldn´t not keep these values ? 

I mean, if I understood correctly, the code bellow stores some values that will remain after reset, or I´m wrong ? 

 

if (reset) begin CurrentState.Level_main <= S0 ; CurrentState.Level_sub <= S3_0 ; end 

 

If not, is there any way to do this in the synthesis?
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

There are no registers described here. CurrentState is a variable that is being set at reset, and then never changing again. So the synthesisor will just assign them as constants. 

Level_main and level_sub both initialise to 3'b0. At reset level_sub should be getting set to 3'b100 

 

What exactly is going wrong? in a synthesised system this variable would just dissapear as it has no effect on any output.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

 

--- Quote Start ---  

level_main and level_sub both initialise to 3'b0. At reset level_sub should be getting set to 3'b100 

What exactly is going wrong? 

--- Quote End ---  

 

 

That´s the problem: Running simulation, both these 2 variables show "0" on their contents. 

Once this is the first time I use the QuartusII IDE, I'm not sure if I´m doing something wrong in the code or just an inadequate use of the sotware. 

 

[EDIT] 

 

I´m starting reset with 1 for few nano seconds, releasing to 0 afterward.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

what are you simulating, RTL or gate netlist? 

are you using modelsim? 

where is the testbench?
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Hi Tricky, 

 

 

I´m using default simulator from QuartusII; in other words, I didn´t configured anyone, leaving as <NONE>, according to page 7 of this (ftp://ftp.altera.com/up/pub/tutorials/de2/digital_logic/tut_quartus_intro_verilog.pdf) tutorial, and the input signals are being generated directly on Waveform Editor. The file that contains the project files are attached, and output picture bellow. 

 

Please note that the whole design are working, except the above mentioned variables ( optimized as constants, as you said ) which are read on simulation as "0" value, wherever I place the cursor. 

 

http://www.alteraforum.com/forum/attachment.php?attachmentid=10190&stc=1
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Theres your problem. The quartus simulator simulates the netlist. And as your CurrentState variable does nothing, it is removed during synthesis.

0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Ok I got, but I´m not sure if this feature is useful during developing. 

There is some way for me to "force" such a synthesis ? 

Sometimes is quite useful perform simple constructs and simple simulations whose structure will be further improved.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

If you did an rtl simulation, with an rtl simulator (like modelsim that you can get for free with quartus) then you would see all of your variable work as you intended. 

 

The quartus simulator is very limited.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Fine, I´m currently downloading the Modelsim pack, but I confess that I didn't understand something: You said before on post# 7 that these unused states were removed during synthesis, but if Modelsim acts on scope of simulation which occurs sequentially after, how would both variables would be viewable if were supposedly removed ?

0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Modelsim simulates your code as you wrote it. So you can see all variables in the code. Its not synthesised at all, just compiled. 

Quartus simulates the synthesised version.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Ohh, sorry for mistake. I´ll install the Modelsim and will update here with results. 

Thanks for kind support.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

I had some problems to activate Modelsim license due to issues regarded to system environment variables. Anyway, I decided to work with the simulation performed on synthesised version of the code, due I´m assuming that this could yield a more realistic result, once runs directly into the technology on what will be assembled. 

 

Back to the code, I wish ask a new question, now related to struct usage on functions, more specifically:  

how to use a 'struct' variable into a function, either as input and output ? 

 

I´m using the code bellow, which has few enhancements on the other posted before. 

The function next_state instantiated at line 71, and declared at the line 97 which according to lines 115-116 has output of the type fsm_t, do not update correctly its values. I´m convinced that I did not performed the correct association of inputs at the lines 98-99. due do match to the same fsm_t type used at the output. 

 

Could so please inform what I´m doing wrong, or just suggest a link were I could learn how could I create and instantiate a function using a struct variable at input and output ? 

 

Many thanks in advance. 

//`define DEBUG_MODE module moore_mac ( input clk, data_in, reset, output reg data_out ); //******************************* Parameter definitions typedef enum logic { SM0, SM1, SM2, SM3, SM3_0, SM3_1, SM3_2, SM3_3 } fmstate ; fmstate nstate, pstate ; parameter S0 = 3'b000 ; parameter S1 = 3'b001 ; parameter S2 = 3'b010 ; parameter S3 = 3'b011 ; parameter S3_0 = 3'b100 ; parameter S3_1 = 3'b101 ; parameter S3_2 = 3'b110 ; parameter S3_3 = 3'b111 ; //******************************* Type declarations typedef struct packed { reg Level_main ; reg Level_sub ; } FSM ; typedef struct packed { bit Level_main_t ; bit Level_sub_t ; } FSM_t ; //******************************* Varable declarations FSM_t tempCurrentState ; // State machine index ( temporary ) FSM CurrentState ; // State machine index ( current ) //`ifdef DEBUG_MODE reg Debug_counter ; //`endif //********************************** Determine the next state always @ ( posedge clk or posedge reset ) begin if (reset) begin //`ifdef DEBUG_MODE Debug_counter <= 0 ; //`endif ; CurrentState.Level_main <= S0 ; CurrentState.Level_sub <= S3_0 ; end else begin //`ifdef DEBUG_MODE Debug_counter <= Debug_counter + 1 ; //`endif case (CurrentState.Level_main) S0: CurrentState.Level_main <= S1; S1: if (data_in) CurrentState.Level_main <= S1; else CurrentState.Level_main <= S2; S2: if (data_in) CurrentState.Level_main <= S1; else CurrentState.Level_main <= S3; S3: CurrentState <= next_state ( CurrentState.Level_main , CurrentState.Level_sub ) ; endcase end end //********************************** Determine the output value always @ ( CurrentState.Level_main ) begin case ( CurrentState.Level_main ) S0: data_out = S0 ; S1: data_out = S1 ; S2: data_out = S2 ; S3: data_out = S3 ; default: data_out = S0 ; endcase end // ******************************************************* // Gets next state, by assessing corresponding sub_state // ******************************************************* function FSM_t next_state ; input reg valStateBefore ; input reg valSubstateBefore ; reg valStateAfter ; reg valSubstateAfter ; if ( valSubstateBefore < S3_3 ) begin valStateAfter = valStateBefore ; valSubstateAfter = valSubstateBefore + 1 ; end else begin valStateAfter = S0 ; valSubstateAfter = S3_0 ; end next_state.Level_main_t = valStateAfter ; next_state.Level_sub_t = valSubstateAfter ; endfunction endmodule  

 

note: 

Please consider the fact that this code is only a temporary draft, so that some small problems flagged by the compiler as "Warnings" will be fixed later.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

I highly recommend you get modelsim working, as it allows you to put debug anywhere in your code, with system calls like $display, that you cannot do with synthesised code.  

Btw, you didnt instantiate a function - you called the function. Instantiation is only done on modules. 

Also, the reg type is pretty redundant in SV now. It's also a bit of a misnomer, as a reg variable doesnt neccessarily make a register. Much better to use the logic type. 

 

If you want to be sure you put stuff in the right order, use named association (and btw, your function definition is old style). I think it read better with: 

 

function FSM_t next_state( reg valStateBefore, reg valSubStateBefore); FSM_t my_return_variable; .... return my_return_variable; endfunction; // and then have explicit named association a_variable <= next_state( .valStateBefore( something), .valSubStateBefore( something_else) )  

 

and use an explicit return, but thats just mean coming from a VHDL background. 

 

 

Does this function really have any merit? this is really just another bit of code that could sit in the always block. Not eactly doing a lot. 

What exactly isnt working?
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Hi Tricky, 

 

 

 

Thanks for the quick reply; I changed the function declaration with the improvements that you suggested, and in fact now its constructs appears much more consistent with a good coding practice than the one I posted earlier; I´m coding based on several examples spread on the Web what explains the old style. 

 

However after compiling the changes on the function... 

 

 

--- Quote Start ---  

function FSM_t next_state( reg valStateBefore, reg valSubStateBefore ); FSM_t next_state_return ; ... return next_state_return ; endfunction 

 

  • Error (10170): Verilog HDL syntax error at moore_mac.sv(98) near text "reg"; expecting ")" 

 

 

--- Quote End ---  

 

...occurred the error highlighted on header above, which I could not determine how to fix it, although some most recent researches on the web. 

 

 

--- Quote Start ---  

I highly recommend you get modelsim working, as it allows you to put debug anywhere in your code 

--- Quote End ---  

 

With respect to Modelsim, I have not given up, I really need a more powerful tool, and have to solve the problem of installation, but I'm trying to compile the code in the meantime. 

 

 

--- Quote Start ---  

Btw, you didnt instantiate a function - you called the function. Instantiation is only done on modules. 

--- Quote End ---  

 

 

Ok, I had wrongly employed the term instantiation when I was actually referring to function call

Anyway, it was not what I done at the line 71 of the code posted above ? 

currentstate <= next_state ( ... ) ;  

 

 

--- Quote Start ---  

Does this function really have any merit? this is really just another bit of code that could sit in the always block. Not eactly doing a lot. 

What exactly isnt working? 

--- Quote End ---  

 

 

As I mentioned before, this is just a preliminary draft of a code whose purpose is to work as a template to a state machine which will work with 2 levels of states. Once the current state falls into certain states, there must run other another levels of state machines ( which I named as substates ).  

 

The application which is currently working, was wrote in C language and has dozens of states. In order to achieve a clean and structured code, I was wondering if I could create a skeleton for the code which would work as a template to insert the remaining system behaviors. Someone could suggest to me adopt a better approach such as using IP cores, but the purpose of such a development is mainly learning of the SV language features. 

 

Once again, thanks for the assistance.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

 

--- Quote Start ---  

Hi Tricky, 

Thanks for the quick reply; I changed the function declaration with the improvements that you suggested, and in fact now its constructs appears much more consistent with a good coding practice than the one I posted earlier; I´m coding based on several examples spread on the Web what explains the old style. 

 

However after compiling the changes on the function... 

 

...occurred the error highlighted on header above, which I could not determine how to fix it, although some most recent researches on the web. 

 

--- Quote End ---  

 

 

try putting the [] after the function parameter. 

 

(logic valStateBefore[2:0],...) 

 

 

 

--- Quote Start ---  

 

With respect to Modelsim, I have not given up, I really need a more powerful tool, and have to solve the problem of installation, but I'm trying to compile the code in the meantime. 

 

--- Quote End ---  

 

 

You will struggle to find one, modelsim is one of the most powerful simulators out there. You might use NCSim if you're doing asics, but modelsim has all sorts of features quartus and vivado (xilinx equivolent tool) will never have: 

RTL Simulation 

Gate level simulation 

Code coverage 

Mixed langauge simulation 

Design Profilers 

SV Assertions 

UVM Support 

 

ETc etc. 

 

 

 

 

 

--- Quote Start ---  

 

Ok, I had wrongly employed the term instantiation when I was actually referring to function call

Anyway, it was not what I done at the line 71 of the code posted above ? 

currentstate <= next_state ( ... ) ;  

 

--- Quote End ---  

 

 

No, this is just calling next_state function. You code has no instantitation. 

 

 

 

 

--- Quote Start ---  

 

As I mentioned before, this is just a preliminary draft of a code whose purpose is to work as a template to a state machine which will work with 2 levels of states. Once the current state falls into certain states, there must run other another levels of state machines ( which I named as substates ).  

 

The application which is currently working, was wrote in C language and has dozens of states. In order to achieve a clean and structured code, I was wondering if I could create a skeleton for the code which would work as a template to insert the remaining system behaviors. Someone could suggest to me adopt a better approach such as using IP cores, but the purpose of such a development is mainly learning of the SV language features. 

 

Once again, thanks for the assistance. 

--- Quote End ---  

 

 

This kind of explains alot. Direct ports of C to HDL never really work very well. It would be much better to try and re-enginner the system for a hardware platform. 

What are the end-goals? What is the source data? 

 

Have you got a circuit diagram of your intended architecture? This should be the first step before writing any HDL (its a description language after all, without the circuit, how do you expect to describe it?) 

 

As to this example, I would suggest forgetting about functions. Functions and tasks in HDL should only really be used to tidy away code that is repeated over and over. Given your description, I would forget about having a struct with two states, just have two discrete variables. Have one working in one always block, and the second in another always block that is only active when the first is in the correct state: 

 

always @(posedge clk) begin // Main state machine end always @(posedge clk) begin if (main_state == correct_state) begin //sub sstate machine end end  

 

But Persoanlly, I think a re-design is in order, as it is very rare that you need two state machines. Maybe you need two modules that handle two separate things?
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Hi Tricky, 

 

 

 

--- Quote Start ---  

try putting the [] after the function parameter 

--- Quote End ---  

 

I done that, but didn´t work yet; returns the same error as posted above (http://www.alteraforum.com/forum/showthread.php?t=47733&p=196390#post196390) on post# 16, even made all the changes proposed. 

It should not to be so hard to make a simple function in SV having the same struct type, either in Input and Output 

 

--- Quote Start ---  

Have you got a circuit diagram of your intended architecture? This should be the first step before writing any HDL (its a description language after all, without the circuit, how do you expect to describe it?) 

--- Quote End ---  

 

The operating principle is so simple, that is not even worthy of elaboration of a state diagram. Basically it is a state sequencer, a kind of up counter (represented by the main state in each case statement), which eventually in some states, must remain there, then running machines of internal states. 

 

--- Quote Start ---  

Given your description, I would forget about having a struct with two states, just have two discrete variables. Have one working in one always block, and the second in another always block that is only active when the first is in the correct state 

--- Quote End ---  

 

Note at this link here (http://www.mcu.net.br/phpbb/blog.php?action=view&article_id=13) ( not translated ) that there is state amount somewhat in the order of almost 100, what substantiate to me try to do something more elaborate, removing the working of substates processing from the allways block, and then putting it into specific functions (which as I said, is still in a draft form). 

 

The logic behind the encapsulation of the variables into a single type, it is because I intend to define States and Substates numerically so that with a simple math, it is possible to know when it was reached the end of Substates, and then be able to continue on to the next upper level state. This logic will not present here a while just for we focus the attention in the main question. 

 

I will certainly consider the suggestions that you put up on redesign, but the reason for what I insist on trying to solve the initial question (function with struct with in and out) is to allow me to learn the available resources SV language. 

 

 

--- Quote Start ---  

I would suggest forgetting about functions. Functions and tasks in HDL should only really be used to tidy away code that is repeated over and over 

--- Quote End ---  

 

This function will be used in several parts of the program. As I mentioned, the entire code above is just a template. 

 

Anway, now it has become a matter of honor, a personal challenge : Regardless if in the course of this project I will adopt another approach like the one you suggested, I really wish to know how to implement a struct based function, used at either input and output. 

 

 

Many thanks for your support. 

Andre.
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

Problem fixed, just to share ( not optimized ): 

 

 

--- Quote Start ---  

type declaration 

typedef struct packed { reg Level_main ; reg Level_sub ; } FSM ; typedef struct packed { bit Level_main_t ; bit Level_sub_t ; } FSM_t ; 

 

variable declaration 

FSM_t tempCurrentState ; // State machine index ( temporary ) FSM CurrentState ; // State machine index ( current ) 

function declaration 

function FSM_t next_state( input logic valStateBefore , input logic valSubstateBefore ); FSM_t next_state_return ; ... return next_state_return ; endfunction 

function call 

CurrentState <= next_state ( CurrentState.Level_main , CurrentState.Level_sub ) ; 

--- Quote End ---  

 

 

Thanks for your help. 

Andre
0 포인트
Altera_Forum
명예로운 기여자 II
3,669 조회수

I´m currently using the structure bellow at a function that handles both its inputs and outputs as type fsm_t

typedef struct packed { bit Level_main_t ; bit Level_sub_t ; bit Level_subcurr_t ; } FSM_t ; 

 

That is something like that:  

 

function FSM_t next_state ( input ...) FSM_t next_state_return ; ... return next_state_return ; endfunction 

 

Once I need to use at the block a reg variable having the same format to exchange values, I performed the following : 

 

typedef struct packed { reg Level_main ; reg Level_sub ; reg Level_subcurr ; } FSM ; 

 

...and created the variable bellow: 

 

FSM StateMachine ;  

 

However, I don´t like the above code arrangement, due I employed a structure duplicated with the same format. 

Does it have any way to perform such a declaration on a smarter way, as for example with only the type fsm_t ?
0 포인트
Altera_Forum
명예로운 기여자 II
3,579 조회수

why not just declare FSM_t as logic? (which is basically the same as reg).

0 포인트
응답