I am trying to make the generation of FSM state parametric or automatic.
I tried many ways and seems there is no way to generate the code I need.
Can someone help please?
The Code which I need to generate is part of FSM state machine, for the ST_DATA_CHECK state:
always #(posedge ui_clk_sync_rst or posedge ui_clk)
begin
if (rst) begin
s_app_cmd <= 3'b111;
s_app_en <= 1'b0;
end
end else begin
case (ddr3_state)
ST_INIT :
….
ST_DATA_CHECK : // This part of the code, needs to make parameteric
if (~dwfifo_ef[0]) begin
s_data_write_active[0] <= 1'b1 ;
end else if (~dwfifo_ef[1]) begin
s_data_write_active[1] <= 1'b1 ;
end else if (~dwfifo_ef[2]) begin
s_data_write_active[2] <= 1'b1 ;
end else if (~d_rfifo_ef[0]) begin
s_data_read_active[0] <= 1'b1 ;
end else if (~d_rfifo_ef[1]) begin
s_data_read_active[1] <= 1'b1 ;
end
ST_WRITE :
…
endcase
Please notice that for example dwfifo_ef[0] and dwfifo_ef[1] bits can be 0 at the same time, so that’s why I need to use priority encoder here.
Any help/idea/suggestion is welcomed about how I can make the code parametric.
Thanks
Hayk
You want a for loop with a break statement:
ST_DATA_CHECK :
for (int i=0;i<$bits(dwfifi_ef);i++)
if (~dwfifo_ef[i]) begin
s_data_write_active[i] <= 1'b1 ;
break;
end
#dave_59 has just about solved your problem, but as you say "in my if statement there are 2 signals s_data_write_active and s_data_read_active", how about trying something like this?
ST_DATA_CHECK :
if (|dwfifo_ef == 1'b1)
for (int i=0;i<$bits(dwfifi_ef);i++)
if (~dwfifo_ef[i]) begin
s_data_write_active[i] <= 1'b1 ;
break;
end
else
for (int i=0;i<$bits(d_rfifo);i++)
if (~d_rfifo[i]) begin
s_data_read_active[i] <= 1'b1 ;
break;
end
(I have not tried to compile, simulate or synthsise this, hence my phrase something like.)
Related
I got a problem when bistreaming. The project is to create a clock with a 1:2 duty cycle. There are no problems during Synthesis and Implementation. I tried a few ways to solve it. But they didn't work well.
module clock_div(clk, clk_out);
input clk;
output reg clk_out;
integer count1, count2;
reg clk_div;
always#(posedge clk)
begin
count1 <= count1 + 1;
if(count1 == 16666667)
begin
count1 <= 0;
clk_div <= ~clk_div;
end
end
always#(clk_div)
begin
count2 <= count2 + 1;
if(count2 == 1)
begin
clk_out <= ~clk_out;
end
else if(count2 == 3)
begin
count2 <= 0;
clk_out <= ~clk_out;
end
end
endmodule
The message that Vivado gave is as follows:
[DRC 23-20] Rule violation (LUTLP-1) Combinatorial Loop - 231 LUT
cells form a combinatorial loop.
This can create a race condition.
Timing analysis may not be accurate.
The preferred resolution is to modify the design to remove
combinatorial logic loops.
To allow bitstream creation for designs with combinatorial logic loops
(not recommended), use this command: set_property SEVERITY {Warning}
[get_drc_checks LUTLP-1].
NOTE: When using the Vivado Runs infrastructure (e.g. launch_runs Tcl
command), add this command to a .tcl file and add that file as a pre-
hook for write_bitstream step for the implementation run.
clk_out_reg_i_3, clk_out_reg_i_4, clk_out_reg_i_5, clk_out_reg_i_7,
clk_out_reg_i_8, clk_out_reg_i_10, clk_out_reg_i_11, clk_out_reg_i_12,
clk_out_reg_i_13, clk_out_reg_i_14, clk_out_reg_i_15,
clk_out_reg_i_16, clk_out_reg_i_17, clk_out_reg_i_20, clk_out_reg_i_21
(the first 15 of 231 listed).
I would appreciate it if someone can help me.
This is wrong:
always#(clk_div) // <<== WRONG!!!!
begin
count2 <= count2 + 1;
if(count2 == 1)
begin
clk_out <= ~clk_out;
end
else if(count2 == 3)
begin
count2 <= 0;
clk_out <= ~clk_out;
end
end
You are using an incomplete sensitivity list. This gives a mismatch between simulation and synthesis. For all code that you want to synthesize use a complete sensitivity list or even easier use :always#( * )
If you use that in the section above you will find that your simulation no longer works. It will get in an infinite loop. Which is exactly the combinatorial loop the tool is complaining about.
To solve this you should put all code into the top section:
always#(posedge clk)
begin
count1 <= count1 + 1;
if(count1 == 16666667)
begin
count1 <= 0;
// Here you should make your 2:1 clock(s!)
// I leave that as an exercise to you
end
end
Problem:
As you divide by 16666667 you will not get a 2:1 clock but more a 33333334:1 clock.
Unless you wanted a 2:1 clock between clk_div and clk_out, but clk_div is not coming out. In that case make both clk_div and clk_out in the above marked section
I will get straight to the point. I have a simple counter that is trying to
mimic how a clock works pretty much. I have a module called counter60sec and another one called counter12hr
counter12hr
module counter12hr(reset, hourInc, overflowOut, hrCounter);
input reset;
input hourInc;
output overflowOut;
output [3:0] hrCounter;
reg overflowOut;
reg [3:0] hrCounter; //0'b1101 == 13 hours
//Initialize counter
initial begin
overflowOut = 1'b0;
hrCounter = 4'b0; //once hour reaches 12:59:59, it is supposed to go back to zero
end
//Everytime hrInc is one, increment hrCounter
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
if(reset == 1'b0) begin
overflowOut = 1'b0;
hrCounter = 4'b0;
end
else begin
if (hourInc == 1'b1) begin
hrCounter = hrCounter + 1'b1;
end
end
end
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
hrCounter = 4'b0;
end
end
endmodule
counter60sec
module counter60sec(reset, secInc, minOut, secCounter);
input reset;
input secInc;
output minOut;
output [5:0] secCounter;
reg [5:0] secCounter; //0'b111100 == 60 seconds.
reg minOut;
//Initialize counter
initial begin
minOut = 1'b0;
secCounter = 6'b0;
end
//Everytime secInc is one, increment secCounter
always#(posedge secInc or negedge reset) begin
minOut = 1'b0;
if(reset == 1'b0) begin
minOut = 1'b0;
secCounter = 6'b0;
end
else begin
if (secInc == 1'b1) begin
secCounter = secCounter + 1'b1;
end
end
end
//output minOut to 1 to signal minute increase when secCounter hits 111100 in binary
always#(negedge secCounter) begin
if(secCounter == 6'b111100) begin
minOut = 1'b1;
secCounter = 6'b0;
end
end
endmodule
I have test bench set up for both. The counter60sec one works fine (Where when secCounter is at value of 60, the minOut becomes 1). The counter12hr follows the same concept, but the value of overflowOut never becomes 1.
For my hrCounter conditional statement in counter12hr.v, I have tried both 4'b1101 and 4'b1100 and neither of them worked. (Trying to get the overflowOut to become one when the hrCounter hits 13)
I've spent hours on this, taking break to relax my eyes etc. I still can't see where I am going wrong. Any help would be appreciated
you have a few issues. The main one is that you have a multiple-driven register in both cases:
always#(negedge reset or posedge hourInc) begin
overflowOut = 1'b0;
...
always#(negedge hrCounter) begin
if (hrCounter == 4'b1100) begin
overflowOut = 1'b1;
the overflowOut is driven from 2 different alsways blocks. Same as minOut in the second counter. The order in which those statements are executed is undefined and the resulting value would depend on the order.
You need to restructure your program in such a way that the registers are assigned in a single always block only.
Secondly, i think, that you have a logic bug, assigning your overflow to '0' in the first statement of the first block (same as in the second one).
Thirdly, you should have uset non-blocking assighments '<=' in finlal assignments to the registers.
something like the following should work.
always#(negedge reset or posedge hourInc) begin
if(reset == 1'b0) begin
hrCounter <= 4'b0;
overflowOut <= 1'b0;
end
else begin
if (hrCounter == 4'b1100) begin
overflowOut <= 1'b1;
hrCounter <= 4'b0;
end
else
hrCounter <= hrCounter + 1'b1;
overflowOut <= 1'b0;
end
end
end
Your code is wrong in so many ways...
Most likely it does not work because of:
#(negedge hrCounter)
You are using a vector but #... works with bits. So it will look at the LS bit only.
As to your code:first and most start using a clock. Do not use posedge and negedge of your signals to drive the other signals.
You use:
always#(posedge secInc ...
...
if (secInc == 1'b1)
Remove the 'if'. you have that condition already in your always statement. (But the signal should not be the 'always' anyway, it should be your clock)
Remove the 'initial' sections You have a reset which defines the start condition.
If you have an active low reset reflect that in the name. Call it reset_n or n_reset anything but 'reset' which is per convention a positive reset signal.
If your drive ANYTHING from an edge, be it from a clock or from other signals, use non-blocking assignments "<="
Do not use your generated signal edges to generate other signals. As mentioned use a clock for everything an in the clocking section use an if. Also do not drive signals from different 'always'. You can never know in which order they are executed and then you have a race condition. Thus the clear and the increment are all in one always block:
if (secCounter == 6'b111100) begin
minOut <= 1'b1;
secCounter <= 6'b0;
end
else
secCounter <= secCounter + 6'b000001;
Because of the timing aspect you now have to go to 59 not 60. Which is as you should expect as digital clocks and watches run from 00 to 59, not 00 to 60. You are allowed to use decimal numbers which will, again, make the code more readable: 6'd59, 4'd11
I currently have this code(below) for a debouncer for a button on an fpga, however I am getting an error that says "Multiple event control statements in one always/initial process block are not supported in this case." whenever I try to synthesize the desgin. The line that causes the problem is the #(posedge clk) but I'm wondering how exactly to replace this logic. What I essentially require is always # (quarter & posedge clk)as the sensitivity list for the first always block but this does not work either. I am fairly new to the language so I'm still working out a few syntax kinks.Snippet of Code is below:
always #(quarter)
begin
#(posedge clk)
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
end
instead of always
#(posedge event1)
#(posedge event2)
create aflag (1bit reg) event2done : reg event2done; initial event2done=0;
always#(posedge event1)
begin if (!event2done & event 2)
// event2done=1; + type ur code
else if(event2done & !event 2)
event2done =0; end
pseudo code:
always#(something1)
#(something2)
do something
Look in the comments to see explanation as to why this isn't synthesizable
always #(posedge clk)
/* over here you'll have to set the default values
for everything that's being changed in this always block,
you'll otherwise generate latches. Which is likely
not what you want */
begin
if (quarter != new) begin new <= quarter; count <= 0; end
else if (count == DELAY) cleanq <= new;
else count <= count+1;
end
I don't have access to my verilog rig at the moment so I can't confirm the syntax correctness
I would like to generate a number of statements inside a clocked process, seen below:
parameter C_INPUT_LENGTH = 32;
parameter C_OUTPUT_NUM_BITS = 5;
reg [C_OUTPUT_NUM_BITS-1:0] address;
reg [C_INPUT_LENGTH-1:0] vector_i;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
if (vector_i[0] == 1) begin
address <= 0;
end
if (vector_i[1] == 1) begin
address <= 1;
end
...
if (vector_i[C_INPUT_LENGTH-1] == 1) begin
address <= C_INPUT_LENGTH-1;
end
end
end // always# (posedge clk)
I did so like this:
integer forcount;
always#(posedge clk) begin
if(rst) begin
address <= 0;
end
else begin
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin <--
address <= forcount;
end
end
end
end // always# (posedge clk)
Xilinx vivado (2014.1) gives the following error, referring to the line indicated above:
[Synth 8-903] failed to generate logic
I've done this before using a similar method in the past and it has worked, what am I doing wrong? How do I generate these if statements?
According to Xilinx, this is a known bug documented under CR 801365. The use of an integer as a loop counter causes this issue in some cases. It's due to be fixed in vivado 2014.3.
The solution is to replace the integer with a signal type reg of appropriate size.
Is your input vector_i one-hot? The code you wrote doesn't guarantee that address will only be written to one value. Try this:
for (forcount = 0;forcount <= C_INPUT_LENGTH-1 ;forcount = forcount + 1) begin
if (vector_i[forcount] == 1) begin
address <= forcount;
break;
end
end
Adding the break statement will break out of the for loop the first time the condition is true. Note that this will generate some carry-chain logic and you might get better results with a case statement.
As a temporary work-around, you could consider using a generate statement.
For example:
genvar i;
always #(posedge clk) begin
if (rst) begin
address <= 0;
end else begin
generate
for (i = 0; i < C_INPUT_LENGTH; i = i + 1) begin: foreach_input
if (vector_i[i]) address <= i;
end
endgenerate
end // if (rst)
end // always #(posedge clk)
edit: oh, never mind -- I missed the bit above where Xilinx's recommended workaround is to simply use a dimensioned variable rather than "integer" for the iterator. That would be easier!
I am trying to pass an integer value to a module, but the IF statement does not work with the parameter. It throws the following error. I am new to Verilog so I have no idea how to make this work.
Error (10200): Verilog HDL Conditional Statement error at clock_divider.v(17):
cannot match operand(s) in the condition to the corresponding edges in the enclosing
event control of the always construct
clock_divider.v module
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(clockHandler == 0)
begin div_helper = DIV_CONST;
end
else
begin div_helper = DIV_CONST_faster;
end
if (!rst_n)
begin div <= 0;
en <= 0;
end
else
begin
if (div == div_helper)
begin div <= 0;
en <= 1;
end
else
begin div <= div + 1;
en <= 0;
end
end
end
always # (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
clk_o <= 1'b0;
end
else if (en)
clk_o <= ~clk_o;
end
endmodule
main.v module
reg clockHandler = 1;
// 7-seg display mux
always # (*)
begin
case (SW[2:0])
3'b000: hexdata <= 16'h0188;
3'b001: hexdata <= register_A ;
3'b010: hexdata <= program_counter ;
3'b011: hexdata <= instruction_register ;
3'b100: hexdata <= memory_data_register_out ;
3'b111: hexdata <= out;
default: hexdata <= 16'h0188;
endcase
if(SW[8] == 1)
begin
clockHandler = 1;
end
else
begin
clockHandler = 0;
end
end
HexDigit d0(HEX0,hexdata[3:0]);
HexDigit d1(HEX1,hexdata[7:4]);
HexDigit d2(HEX2,hexdata[11:8]);
HexDigit d3(HEX3,hexdata[15:12]);
clock_divider clk1Hzfrom50MHz (
clockHandler,
CLOCK_50,
KEY[3],
clk_1Hz
);
It's my understanding that the first statement in a verilog always block must be the if(reset) term if you're using an asynchronous reset.
So the flop construct should always look like this:
always # (posedge clk or negedge rst_n) begin
if(~rst_n) begin
...reset statements...
end else begin
...all other statements...
end
end
So for your case you should move the if(clockHandler==0) block inside the else statement, because it is not relevant to the reset execution. Even better would be to move it into a separate combinational always block, since mixing blocking and nonblocking statements inside an always block is generally not a good idea unless you really know what you're doing. I think it is fine in your case though.
To add to Tim's answer - the original code (around line 17, anyway) is valid Verilog.
What it's saying is "whenever there's a rising edge on clk or a falling edge on rst_n, check clockHandler and do something" (by the way, get rid of the begin/ends; they're redundant and verbose). The problem comes when you want to implement this in real hardware, so the error message is presumably from a synthesiser, which needs more than valid Verilog. The synth suspects that it has to build a synchronous element of some sort, but it can't (or won't, to be precise) handle the case where clockHandler is examined on an edge of both clk and rst_n. Follow the rules for synthesis templates, and you won't get this problem.
is this a compilation error or synthesis error? i used the same code to see if it compiles fine, and i din get errors.. Also, it is recommended to use "<=" inside synchronous blocks rather than "="
You're using the same flop construct for two different things. Linearly in code this causes a slipping of states. I always place everything within one construct if the states rely on that clock or that reset, otherwise you require extra steps to make sure more than one signal isn't trying to change your state.
You also don't need the begin/end when it comes to the flop construct, Verilog knows how to handle that for you. I believe Verilog is okay with it though, but I generally don't do that. You also don't have to use it when using a single statement within a block.
So your first module would look like this (if I missed a block somewhere just let me know):
clock_divider.v module (edited)
module clock_divider (clockHandler, clk, rst_n, clk_o);
parameter DIV_CONST = 10000000 ; // 1 second
parameter DIV_CONST_faster = 10000000 / 5;
input clockHandler;
input clk;
input rst_n;
output reg clk_o;
reg [31:0] div;
reg en;
integer div_helper = 0;
always # (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
div <= 0;
en <= 0;
clk_o <= 1'b0;
end
else if(en)
begin
clk_o <= ~ clk_o;
if(clockHandler == 0)
begin
div_helper = DIV_CONST;
end
else
begin
div_helper = DIV_CONST_faster;
end
else
begin
if (div == div_helper)
begin
div <= 0;
en <= 1;
end
end
else
begin
div <= div + 1;
en <= 0;
end
end
end
end module
If that clk_o isn't meant to be handled at the same time those other operations take place, then you can separate everything else with a general 'else' statement. Just be sure to nest that second construct as an if-statement to check your state.
And also remember to add always # (posedge clk or negedge rst_n) to your main.v module as Tim mentioned.