Simple "Assign" Function - verilog

i have just started to learn some verilog and came across a problem that would normally be solved using a for loop in other languages.
s2 s1 s0 m
0 0 0 u
0 0 1 v
0 1 0 w
0 1 1 x
1 0 0 y
1 0 1 z
This is the truth table of the problem where s2,s1,s0 are switches, (u,v,w,x,y,z) are inputs and if certain switches are set, the output(m) will be set as one of the inputs. However, this is only 1 bit wide and we can just assign each m to be one of the following inputs provided that s0,s1,s2 matches. If it were 3 bit wide input and output ex:(u0,u1,u2),(m0,m1,m2) but each of the variables still follows the same logic with one another(ex: u0,u1,u2 will all be the outputs m0,m1,m2 provided that all switches are 0) how can i shorten my code. Am i allowed to do:
assign m[3:0] = (~s0&~s1&~s2&u[3:0])

No, that is not a good solution. Verilog will extend your select signals to be the same width as m before performing the & operation, and the default behavior is to add zeros on the left to extend a signal. It might work if you declared the select signals to be signed but I think you can do better.
Furthermore, the example you provide only deals with the first row of your truth table. For the other seven combinations of s0, s1, and s2 you would be assigning all zeros to m. If you want to do this in a single combinational assignment then you would need 8 logical expressions like the one you have, all ORed together to get the final result.
A much cleaner way of doing this is with an if-then-else or case statement inside an always block.

Try a case statement:
always #* begin
case ({s2,s1,s0})
3'b000 : m = u;
3'b001 : m = v;
3'b010 : m = w;
3'b011 : m = x;
3'b100 : m = y;
3'b101 : m = z;
default: m = 0; /* <-- catch all */
endcase
end
Note: Use default if the truth table is incomplete. Otherwise a latch will be inferred.
Working example: http://www.edaplayground.com/s/6/187

Related

How to assign a dynamic range of bits

Assume I have three registers concatenated like so:
{C, A, Q}
Where C is one bit, and A and Q are, say, 8 bits.
I need to periodically perform a shift operation like so:
if (shift_regs) {C, A, Q} <= {C, A, Q} >> 1;
Another register, P, starts with a value equal to the number of bits in Q, in this case 8, and counts down by one every time a shift occurs. The whole sequence stops when P reaches 0, and the output result is 16 bits equal to {A, Q}.
However, I want perform an optimization by detecting the case where Q prematurely becomes zero before all its bits are shifted out, and assign the output result to {{8-bits_shifted_so_far{1'b0}}, A, Q[7:8-bits_shifted_so_far]} instead.
Example sequence:
C = 0, A = 8'b1101_0100, Q = 8'b0000_0011
1) after first shift, {C, A, Q} becomes {1'b0, 8'b0110_1010, 8'b0000_0001}.
2) after second shift, {C, A, Q} becomes {1'b0, 8'b0011_0101, 8'b0000_0000}.
3) Q is now zero, so assign output to {{8-bits_shifted_so_far{1'b0}}, A, Q[7:8-bits_shifted_so_far]}, i.e. {6'b00_0000, 8'b0011_0101, 2'b00}.
How can I implement this in verilog or systemverilog?
In keeping with your example, I will assume the output has a width of 16 bits.
Your problem can be simplified, since you are performing this operation at the point when Q == 8'h00, then your output does not need to contain Q[7:8-bits_shifted_so_far], it can be replaced with zeros. As Serge pointed out, dynamic ranges are not possible in verilog, but your problem has a simple solution:
//Note the blocking assignment
if(shift_regs) {C, A, Q} = {C, A, Q} >> 1;
//Set the output to A bit-shifted left by the desired amount
if(!Q) output = {8'h00, A} << (8-bits_shifted_so_far);
Essentially, all you are doing is outputting A bit shifted relative to how many shift operations have been performed.

when if(a) will return true in Verilog

I am new to Verilog and I had been asked the following question:
Consider a = reg[3:0], then what values can a have so if(a) will return true?
I have no idea where to start, tried to compile some examples but all failed syntax problem.
Writing if (a) is the same as writing if (a !=0). Since a is a 4-bit variable, you can expand that out to if (a[0] != 0 | a[1] ! = 0 | a[2] != 0 | a[3] !=0). So a 1 in any bit position makes the expression true. Note that an unknown value x or z as an operand with the equality/inequality operators results in an unknown and is considered false. But an unknown or'ed with true is true.
reg is a verilog keyword used to declare variable types, and the expression you provided is an illegal verilog expression. You can declare a to be a 4-bit reg as the following:
reg[3:0] a;
the above makes a a 4-bit vector. Now, verilog bits might have 4 states: 0, 1, x, and z. So, any one of 4 bits of a can be in any of those states. Now you have 256 possible combinations. If you ignore x and z states, you can get 16 combinations expressed in decimals as 0 to 15.
true means that at least one bit in a is 1. In all other cases it will be false.

The difference between x and z

While reading the syntax of Verilog, I came across the four logic values: 0 1 x z.
After searching the web, seeking to find the difference between x and z, I found only that x is unknown value and z is high impedance (tristate). I think that I understand the definition of x but didn't quite understood the one of z - what does it mean "high impedance (tristate)"?
I would like to see an example for each logic value out of the two: x z
Z means the signal is in a high-impedance state also called tri-state. Another signal connected to it can change the value: a 0 will pull it low, a 1 will pull it high.
To understand impedance (and thus high impedance) you should have some understanding of resistance, voltage and current and their relations as defined by Ohms law.
I can't give you an example of 'X' or 'Z', just as I can't give you an example of '1' or '0'. These are just definitions of signal states. In fact in Verilog there are more then four states. There are seven strengths.
(See this webpage).
Here is a principle diagram of how a chip output port makes a zero, one or Z. In reality the switches are MOSFETs.
Tri-state signals are no longer used inside chips or inside FPGA's. They are only used outside for connecting signals together.
x, as you had already found describes an unknown state. By default verilog simulation starts with all variables initialized to this value. One of the task of the designer is to provide correct reset sequences to bring the model into a known state, without 'x', i.e.
always #(posedge clk)
if (rst)
q <= 0;
In the above example initial value of q which was x is replaced by a known value of 0.
The difference between 'x' and 'z' is that 'z' is a known state of high impedance, meaning actually disconnected. As such, it could be driven to any other value with some other driver. It is used to express tri-state buses or some other logic.
wire bus;
assign bus = en1 ? value1 : 1'bz;
...
assign bus = en2 ? value2 : 1'bz;
In the above example the bus is driven by 2 different drivers. If 'en1' or 'en2' is high, the bus is driven with a real 'value1' or 'value2'. Otherwise its state is 'z'.
verilog has truth tables for every operator for all the values. You can check how they are used. i.e. for '&'
& 0 1 x z
0 0 0 0 0
1 0 1 x x
x 0 x x x
z 0 x x x
you can find for every other gate as well. Note that there are no 'z' in the result, just 'x's.
In system verilog X is treated like unconnected wire and Z is Weak HIGH.
Suppose a situation where you have wire connecting 2 modules m1 and m2.
If you are driving Z onto that wire from m1 then you can pull down this wire by assigning it to zero by m2.
As I figured out :
"tristate" or "high impedance" In transistors occures when you have "nothing" in the output.
that may occur, for example :
In a situation that you have an nMOS transistor let's call that T1:
the gate value of T1 is for example 0
so T1 would not conduct and there is no conduction path between your supply (probably 0 ) and the drain(output)
-that may occur a "Z" or tristate
--
It may occur for PMOS transistors with value -> 1 too.

How do you move non-zero elements in an array to the top in a single cycle?

I have the following 8-bit array:
0
4
0
0
5
0
2
0
How do I make it to the following in a single cycle (without iterating the element one by one)?
4
5
2
0
0
0
0
0
I know how to do it in software (MATLAB), but I'm not sure how to do it with combinational logic.
% initialise temporary vectors
TempType = zeros(maxType,1);
TempStart = zeros(maxType,1);
TempStop = zeros(maxType,1);
index = 1;
% remove zero elements from the middle
for j = 1:maxType
if (PreType(j) > 0 && PreStart(j) > 0 && PreStop(j) > 0)
TempType(index) = PreType(j);
TempStart(index) = PreStart(j);
TempStop(index) = PreStop(j);
index = index + 1;
end
end
I think any simplified sorting algorithm can do the job. For example, here is a modified bubble sort solution implemented in a single cycle:
module MoveZeros;
parameter W1 = 8;
parameter W2 = 10;
integer i, j;
logic [W1-1:0] array[W2-1:0] = {0,4,0,0,5,0,2,0,0,1};
logic [W1-1:0] temp;
always_comb begin
for (i=W2-1 ; i >=0 ; i=i-1)
for (j=W2-1 ; j >= 0 ; j=j-1)
begin
if (array[j]==0 && array[j-1] != 0) begin
temp = array[j];
array[j] = array [j-1];
array[j-1] = temp;
end
end
end
endmodule
output:
# array = '{4, 5, 2, 1, 0, 0, 0, 0, 0, 0}
Working example on edaplayground. Depending on your cycle time and the width of your input array (W2), you may want to break this algorithm into multiple cycles.
Synthesis tools unroll loops, therefore, the synthesized circuit will have O(W2^2) comparators and multiplexers, which can explode. Hence for bigger arrays, a multi-cycle solution is the way to go.
This is not an answer, which would take several hours of work, but SO's comments are not up to this sort of question. You should ask on comp.arch.fpga, if it's still alive.
Start by finding a datasheet for one of the old asynchronous fall-through FIFOs; these will include a circuit diagram. You don't really want to do anything like this, because the stage-to-stage handshaking is hairy, and you can't apply all 8 values simultaneously, but it'll give you ideas for a more synchronous implementation. Adapting a fall-through FIFO to do what you want is trivial - just ignore zero inputs.
If you can go up to 8 clock cycles, a more synchronous implementation is easy, with relatively limited hardware.
One cycle doesn't look too difficult, but will use more hardware. How sure are you that you must do it in one cycle? How much hardware can you use? If you've got a free PLL/DLL I'd be inclined to use that to get an 8x clock.
EDIT
Actually, with the benefit of more than 2 minutes thought, this seems pretty easy, even in one cycle.
Say you've got 8 registers with your 8 inputs (I0-I7), and 8 output registers (Q0-Q7). Each output register has associated logic which selects an input register for source data. The Q0 selector finds the lowest-numbered I register which contains non-zero data. The Q1 selector finds the next highest I register which contains non-zero data, and so on. Each selector drives a mux which loads the corresponding output register. Q0 requires an 8-1 mux (eight 8-bit inputs from I0-I7, one 8-bit output which goes to the input of Q0). Q1 requires a 7-1 mux (the inputs can only be I1-I7), and so on, until Q7, which doesn't require a mux at all (it can only be driven by I7).
The only smarts are in the selectors which find the source data for each output register. The Q7 selector is trivial; Q7 can only select I7, and only if all of I0-I7 contain non-zero data. Q6 is a bit more complicated, and so on.
If you can't see how to code a selector, ask specifically about that one in a new question, to avoid all the comments.

Verilog reg assignment to part of another reg

I am using Verilog with modelSim and I get the following errors when I try to assign reg variables to different parts of another reg variable:
** Error: Range width must be greater than zero.
** Error: Range width must be constant expression.
here is the relevant code:
integer f; //zd, qd, R and Q are regs
always # * begin
f = 52 - zd;
R = qd[f +:0];
Q = qd[63 -:f+1];
end
I want R to include qd (from 0 to f) and Q to be (the rest) qd (from f+1 to 63). How to do it? Thanks.
What you are trying to do is not legal in verilog 2001.
As your warning says, Range width must be constant expression, i.e. you cannot have variable length part selects.
You can have fixed length part select that varies the starting point (i.e. select 8 bits starting from f), but the syntax for that is this:
vector_name[starting_bit_number +: part_select_width]
vector_name[starting_bit_number -: part_select_width]
In hardware the size of a bus must be a fixed size, you cannot change the number of wires in silicon based on the contents of a register :)

Resources