If I write the following code:
module POLY(CLK,RESET_n,IN_VALID,IN,OUT_VALID,OUT);
input CLK,RESET_n,IN_VALID;
input [ 3:0] IN;
output OUT_VALID;
output [12:0] OUT;
and then use it:
always #(*)
begin
.........
end
Does it mean that the input CLK,RESET_n,IN_VALID;input [ 3:0] IN; will trigger the always block or only the input that has used in the block will trigger the always block?
But it doesn't write posedge or negedge, so the two both edge will trigger the always block or not?
The (*) means "build the sensitivity list for me".
For example, if you had a statement a = b + c; then you'd want a to change every time either b or c changes. In other words, a is "sensitive" to b & c. So to set this up:
always #( b or c ) begin
a = b + c;
end
But imagine you had a large always block that was sensitive to loads of signals. Writing the sensitivity list would take ages. In fact, if you accidentally leave a signal out, the behaviour might change too! So (*) is a shorthand to solve these problems.
It considers that all the variable will be in sensitivity list. So, you don't need to worry about adding them in the sensitivity list.
It will behave like combinational logic.
Related
reg A,B,C;
always #(*)begin
//some other computations
C=B;
//some other computations
A=C;
end
always #(posedge clk)begin
B<=A;
end
Hi there,
In the code above, at the posedge of clk reg A changes the value of reg B and that starts the process of first always block since B is in the sensitivity list. My question is what will be happening at the line "C=B" since reg C is also in the sensitivity list? Will that start the process of the first loop again and causes an infinite loop?
I check that on simulation and it works fine. But I don't know want would happen on hardware.
My guess is it will not cause a problem. Since Verilog only creates a LUT to mimic the algorithm inside of the always block, that will not cause a problem on hardware. However, I am not sure so I would like to ask.
Thank you,
Remember that procedural code executes one statement at a time. Your code is effectively interpreted the same as
initial begin
#(B or C) // wait for a change on B or C
C = B;
A = C;
#(B or C) // wait for a change on B or C
C = B;
A = C;
#(B or C) // wait for a change on B or C
C = B;
A = C;
...
end
The assignment to C happens, but any change to C has already happened before you get to the next #. Synthesis interprets C as an intermediate value.
I have some combinational logic f that depends on a register r like this:
reg r;
assign output = f(r); // f is a complicated function of r
Now, I want to change r and use output. I want something like:
always begin
r = r + 1;
if(output) begin
// do something
end
end
In simulation, I could add #100, for example, between r = r + 1 and if(output) to achieve what I want. However, #100 is not synthesizable. Will the hardware have some sort of delay inserted automatically? If not, how can I wait for the combinational logic to finish?
In the very general case, you could set up your logic to behave asynchronously with respect to r and output where they have a combinational loop between them (ie, output is the output of a combinational function of r and r is the output of a combinational function of output, forming a loop). However, this design is hard to deal with for a number of reasons and requires very detailed and specific timing and other properties (things like stable states and glitch prevention). If you want to learn more about how this might work, do some research on asynchronous design.
However, based on how you seem to want this circuit to behave, you really want to make a synchronous design. In this case, you probably want to register r and run the system off a clock. Such a design might look like this:
input clk; // We need an input clock to run the design
output reg out; // Lets not call it output as thats a keyword in verilog
reg [3:0] r; // I assume you want r to do more than just flip between 1 and 0, so you need to give it a few more bits of width
assign out = f(r); // figure out the output
// Heres your combinational function of out which does more stuff, not sure if it belongs here or in the parent module, but you'd need to give more info on what you do with out
always #* begin
if (out) begin
// Do your thing
end
end
// The register for r (which acts as a counter in your design)
always #(posedge clk) begin
r <= r + 4'd1;
end
Without more details on your design, I cant really determine if you need more done, but this kind of synchronous design, based of a clock signal which provides your delay, is what you probably should be using.
I am trying to write an "inverter" function for a 2's compliment adder. My instructor wants me to use if/else statements in order to implement it. The module is supposed to take an 8 bit number and flip the bits (so zero to ones/ones to zeros). I wrote this module:
module inverter(b, bnot);
input [7:0] b;
output [7:0]bnot;
if (b[0] == 0) begin
assign bnot[0] = 1;
end else begin
assign bnot[0] = 0;
end
//repeat for bits 1-7
When I try and compile and compile it using this command I got the following errors:
vcs +v2k inverter.v
Error-[V2005S] Verilog 2005 IEEE 1364-2005 syntax used.
inverter.v, 16
Please compile with -sverilog or -v2005 to support this construct: generate
blocks without generate/endgenerate keywords.
So I added the -v2005 argument and then I get this error:
vcs +v2k -v2005 inverter.v
Elaboration time unknown or bad value encountered for generate if-statement
condition expression.
Please make sure it is elaboration time constant.
Someone mind explaining to me what I am doing wrong? Very new to all of this, and very confused :). Thanks!
assign statements like this declare combinatorial hardware which drive the assigned wire. Since you have put if/else around it it looks like you are generating hardware on the fly as required, which you can not do. Generate statements are away of paramertising code with variable instance based on constant parameters which is why in this situation you get that quite confusing error.
Two solutions:
Use a ternary operator to select the value.
assign bnot[0] = b[0] ? 1'b0 : 1'b1;
Which is the same as assign bnot[0] = ~b[0].
Or use a combinatorial always block, output must be declared as reg.
module inverter(
input [7:0] b,
output reg [7:0] bnot
);
always #* begin
if (b[0] == 0) begin
bnot[0] = 1;
end else begin
bnot[0] = 0;
end
end
Note in the above example the output is declared as reg not wire, we wrap code with an always #* and we do not use assign keyword.
Verliog reg vs wire is a simulator optimisation and you just need to use the correct one, further answers which elaborate on this are Verilog Input Output types, SystemVerilog datatypes.
I have the following code:
always # (clk) begin
for (1=0,i<150, i++) begin
abc[i] = xyz[i];
end
end
Question: If I want to get value of abc[8] (set of 8th iteration with the assign statement), how can I do that?
I did like below:
reg [31:0] abc;
wire [31:0] jkl;
always # (clk) begin
for (1=0,i<150, i++) begin
abc[i] = xyz[i];
end
end
assign jkl = abc[8];
$display ("value is 0x%x\n", jkl);
I have an error, can you please suggest me something?
Seems like you have misunderstanding of how for loops work in Verilog. In Verilog, you are defining hardware which operates in parallel at all times. The for loop is just a handy way to express something. You should not think of it as iterating.
What your expression means is something like this:
Assign abc[i] from xyz[i] for all values of i from 0 to 149, on every clock cycle
If you really want to iterate, you need to create a counter which increments on each cycles and use that instead of a for loop.
Now, you are probably getting error messages due to some of your other errors:
You cannot put a $display outside of a sequential code block. That is, it needs to be inside an always or forever block or similar.
You are assigning jkl (a 32-bit value) from abc[8] which is a single bit
You are assigning abc[0] to abc[149] in the for loop, but abc is only 32-bits wide
I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
if (a) begin
assign size = 14'h2222;
end
else begin
if (b) begin
assign size = 14'h1111;
end
else begin
if (c) begin
assign size = 14'h0777;
end
else begin
assign size = 14'h0333;
end
end
end
endmodule
Upon compilation, I receive the following error:
ERROR:HDLCompiler:44 - Line 67: c is not a constant
I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to
if (c == 1) begin
but to no avail.
Does anybody know how to solve this error? Thank you!
Two problems:
1) You need to put if statements inside an always block.
If you use verilog-2001, you can use
always #*
if ....
end
end
Otherwise specify all the inputs in the sensitivity list:
always #(a or b or c or d)
if ....
end
end
2) Constant assignments are not allowed inside if statements.
Remove the assign keyword from any statements inside the if block:
if (a) begin
size = 14'h2222;
end
You will also have to declare size as a reg type.
However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
assign size = a ? 14'h2222 :
b ? 14'h1111 :
c ? 14'h0777 :
14'h0333 ;
endmodule
As #Tim has already answered, using reg types inside always blocks or wire with assign.
#Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.
Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.
My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.
module select_size(
input a,
input b,
input c,
input d,
output logic [13:0] size //logic (SystemVerilog) or reg type
);
always #* begin
casez ({a,b,c})
3'b1?? : size = 14'h2222 ;
3'b01? : size = 14'h1111 ;
3'b001 : size = 14'h0777 ;
3'b000 : size = 14'h0333 ;
default: size = 'bx ;
endcase
end
endmodule