I am trying to use event triggering in my code (->). Will this get synthesized?
always #(posedge clk) begin
count <= count + 1;
-> x;
end
always #(x) flag = 1;
This is just a sample code. What i want to do is when ever there is an event in the count I want to make the flag high, else it should remain low. In my case the count value increases after every 7 clock cycles. Can i use event triggering for this? If not what can I do to meet my requirement?
Anything you can execute in simulation could be synthesized if tools choose to support it. But most RTL synthesis tools do not support this.
In your simple case, you could replace your event trigger with a task call (or void function call in SystemVerilog).
always #(posedge clk) begin
count <= count + 1;
x;
end
task x;
flag <= 1;
endtask
You should not do this in synthesizable code. While some tools may be able to create equivalent logic, there is almost always an alternative that should be used instead. For example, your code can be rewritten as:
always #(posedge clk) begin
count <= count + 1;
-> x;
end
always #(count) flag = 1;
Some software can maybe synthesize it, but it's not a good code. If you do that, your code is not synchronous.
To be synchronous, all «always» statement must toggle on the same edge of clk.
Related
now I know in Verilog, to make a sequential logic you would almost always have use the non-blocking assignment (<=) in an always block. But does this rule also apply to internal variables? If blocking assignments were to be used for internal variables in an always block would it make it comb or seq logic?
So, for example, I'm trying to code a sequential prescaler module. It's output will only be a positive pulse of one clk period duration. It'll have a parameter value that will be the prescaler (how many clock cycles to divide the clk) and a counter variable to keep track of it.
I have count's assignments to be blocking assignments but the output, q to be non-blocking. For simulation purposes, the code works; the output of q is just the way I want it to be. If I change the assignments to be non-blocking, the output of q only works correctly for the 1st cycle of the parameter length, and then stays 0 forever for some reason (this might be because of the way its coded but, I can't seem to think of another way to code it). So is the way the code is right now behaving as a combinational or sequential logic? And, is this an acceptable thing to do in the industry? And is this synthesizable?
```
module scan_rate2(q, clk, reset_bar);
//I/O's
input clk;
input reset_bar;
output reg q;
//internal constants/variables
parameter prescaler = 8;
integer count = prescaler;
always #(posedge clk) begin
if(reset_bar == 0)
q <= 1'b0;
else begin
if (count == 0) begin
q <= 1'b1;
count = prescaler;
end
else
q <= 1'b0;
end
count = count - 1;
end
endmodule
```
You should follow the industry practice which tells you to use non-blocking assignments for all outputs of the sequential logic. The only exclusion are temporary vars which are used to help in evaluation of complex expressions in sequential logic, provided that they are used only in a single block.
In you case using 'blocking' for the 'counter' will cause mismatch in synthesis behavior. Synthesis will create flops for both q and count. However, in your case with blocking assignment the count will be decremented immediately after it is being assigned the prescaled value, whether after synthesis, it will happen next cycle only.
So, you need a non-blocking. BTW initializing 'count' within declaration might work in fpga synthesis, but does not work in schematic synthesis, so it is better to initialize it differently. Unless I misinterpreted your intent, it should look like the following.
integer count;
always #(posedge clk) begin
if(reset_bar == 0) begin
q <= 1'b0;
counter <= prescaler - 1;
end
else begin
if (count == 0) begin
q <= 1'b1;
count <= prescaler -1;
end
else begin
q <= 1'b0;
count <= count - 1;
end
end
end
You do not need temp vars there, but you for the illustration it can be done as the following:
...
integer tmp;
always ...
else begin
q <= 1'b0;
tmp = count - 1; // you should use blocking here
count <= tmp; // but here you should still use NBA
end
I have some variables in an initial block
initial
begin
i = 32'b0;
j = 32'b1;
end
I want to initialize them with initial values like this every time I press a pushbutton
always #(posedge btn)
begin
i = 32'b0;
j = 32'b1;
end
Doing it like this gives the error "can't resolve multiple constant driver" and I know why it happens but, is there another way around??
It sounds like you are creating synthesizable code (based on your need to press a button). Initial blocks do not synthesize to logic, they are only used for simulation. Typically you use a reset signal to set initial values.
Also you generally want to keep the logic for any one signal in a single block, instead of separating it into separate blocks. (again, this is for synthesizeable code, for simulation this is not important)
Finally, You generally do not want to use outside async signals to clock some logic (unless you know what you are doing). You would instead code something like:
//---- detect rising edge of btn ----
reg btn_prev;
wire rising_edge_btn;
always #(posedge clk)
btn_prev <= btn;
assign rising_edge_btn = ~btn_prev & btn;
// ---- i and j logic --------------
always #(posedge clk) begin
if( rst || rising_edge_btn) begin
i <= 0;
j <= 1;
end
else
//some other logic here
end
end
the code above uses a synchronous reset signal "rst". You can also find designs with an asynchronous reset. It would be good practice to also synchronize your outside async btn signal with with 2 flip flops to avoid metastability.
In Verilog/VHDL, lets say I have a 4 bit counter, and a flag that should be asserted when the counter equals between 4 and 8. There are two ways to implement this
if((cntr>=4)&&(cntr<8))
flag <=1;
else
flag <= 0;
Or, I could do this
if(cntr==4)
flag<=1;
else if (cntr==8)
flag<=0;
It seems to me that functionally, these do the same thing.
Is there any reason one would be better than the other? style-wise? How about for synthesis/implementation?
In both examples, flag will be synthesised as a flip-flop. This is because (I assume) you are driving it from within a clocked always block, ie your two examples are:
always #(posedge clk)
if ((cntr>=4)&&(cntr<8))
flag <= 1;
else
flag <= 0;
and
always #(posedge clk)
if (cntr==4)
flag <= 1;
else if (cntr==8)
flag <= 0;
Both examples are simple (2-state) FSMs. There is little to choose between them. Both will be implemented by a flip-flop (flag) whose D-input is driven by a small amount of combinational logic. The only difference is that that combinational logic may be smaller with the second example than the first because implementing == generally requires less area than implementing < or >.
If I want statements to happen in parallel and another statement to happen when all other statements are done with, for example:
task read;
begin
if (de_if==NOP) begin
dp_op <= 3'b000;
dp_phase = EXEC;
end
else begin
if (de_if==EXEC_THEN) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else if (get_value(de_ctrl1,de_src1)==dp_mem[de_src2]) begin
dp_const <= de_src3[0];
dp_src <= de_src3;
dp_op <= {NOP,de_ctrl3};
dp_dest <= de_dest1;
end
else begin
dp_const <= de_src4[0];
dp_src <= de_src4;
dp_op <= {NOP,de_ctrl4};
dp_dest <= de_dest2;
end
#1 dp_phase=READ;
end
end
endtask
In this code I want the statement dp_phase = READ to only be executed after all other assignments are done, how do I do it?
As you can see what I did is wait 1 clock before the assignment but i do not know if this is how its done ...
You need a state machine. That's the canonical way to make things happen in a certain sequence. Try to remember that using a hardware description language is not like a regular programming language...you are just describing the kind of behavior that you would like the hardware to have.
To make a state machine you will need a state register, one or more flip-flops that keep track of where you are in the desired sequence of events. The flip-flops should be updated on the rising clock edge but the rest of your logic can be purely combinational.
Recently, I had seen some D flip-flop RTL code in verilog like this:
module d_ff(
input d,
input clk,
input reset,
input we,
output q
);
always #(posedge clk) begin
if (~reset) begin
q <= 1'b0;
end
else if (we) begin
q <= d;
end
else begin
q <= q;
end
end
endmodule
Does the statement q <= q; necessary?
Does the statement q <= q; necessary?
No it isn't, and in the case of an ASIC it may actually increase area and power consumption. I'm not sure how modern FPGAs handle this. During synthesis the tool will see that statement and require that q be updated on every positive clock edge. Without that final else clause the tool is free to only update q whenever the given conditions are met.
On an ASIC this means the synthesis tool may insert a clock gate(provided the library has one) instead of mux. For a single DFF this may actually be worse since a clock gate typically is much larger than a mux but if q is 32 bits then the savings can be very significant. Modern tools can automatically detect if the number of DFFs using a shared enable meets a certain threshold and then choose a clock gate or mux appropriately.
In this case the tool needs 3 muxes plus extra routing
always #(posedge CLK or negedge RESET)
if(~RESET)
COUNT <= 0;
else if(INC)
COUNT <= COUNT + 1;
else
COUNT <= COUNT;
Here the tool uses a single clock gate for all DFFs
always #(posedge CLK or negedge RESET)
if(~RESET)
COUNT <= 0;
else if(INC)
COUNT <= COUNT + 1;
Images from here
As far as simulation is concerned, removing that statement should not change anything, since q should be of type reg (or logic in SystemVerilog), and should hold its value.
Also, most synthesis tools should generate the same circuit in both cases since q is updated using a non-blocking assignment. Perhaps a better code would be to use always_ff instead of always (if your tool supports it). This way the compiler will check that q is always updated using a non-blocking assignment and sequential logic is generated.