How do I convert a tristate bus to 2-state logic for synthesis?
I've made a little test
module test1( inout tristate, output flattened);
assign flattened = tristate ? 1 : 0;
endmodule
module test2( inout tristate, output reg flattened);
always #(tristate) begin
case(tristate)
0: flattened = 0;
default: flattened = 1;
endcase
end
endmodule
`timescale 1ns / 1ps
module test_tb;
reg tristateEnable;
reg tristateValue;
wire tristate = tristateEnable ? tristateValue : 1'bz;
wire flattened1, flattened2;
test1 uut1(tristate, flattened1);
test2 uut2(tristate, flattened2);
initial begin
tristateValue = 1'b0;
tristateEnable = 1;
#10 tristateValue = 1'b1;
#10 tristateEnable = 1'b0;
end
endmodule
Simulating it I got that module test1 sets flattened to X and module test2 sets it to 1, the latter is what I wanted, but I haven't synthesized it yet. Is there a better / standard way of doing this?
You've asked two questions: (1) what is the difference between the conditional operator and the case statement, and (2) how to handle tri-state values.
On the language question:
In short, Verilog has a 4-state data type, and the operators handle the 4 states differently.
The case statement does a "4-state test", otherwise known as "case equality". The case expression (tristate in your example) is compared against 0, 1, x, and z. When it is z, the default branch is taken, so flattened is 1, as you found.
The conditional ('ternary') operator also does a 4-state test, and finds tristate as z. It doesn't know what to do now, so it combines the two values you supplied (0 and 1) into a resulting x, which is what you see. Basically, it's trying to be smart. See table 5-21 in the 2005 LRM.
Note that the if statement does not do a 4-state test.
Tristates: you're confused because your control signal (tristate) goes to z; it's the data signal (flattened) that should go to z.
You don't 'flatten' tristates for synthesis; you normally model a pull-up or pull-down. This will be specific to your technology, but you may just need to instantiate a pullup or pulldown component. Your synthesiser may or may not do this automatically for you if you have code like
assign sig_o = (ena == 1'b1)? sig_i : 1'bz;
You need to read your synthesiser docs to be sure. Note that you should only ever use a conditional operator like this if ena is guaranteed to be 2-state (0/1).
Related
I am trying to form a T flip-flop in Verilog. I am studying verilog from "Digital System Design with FPGA: Implementation using verilog and vhdl" and the code for T flip-flop is here below:
module t_flip_flop(t,clk,clr,q,qn);
input t,clk,clr;
output reg q,qn;
always #(posedge clk or negedge clr)
begin
if(clr==0)
q<=0;qn<=1;
else
q<=q^t;
qn<=~(q^t);
end
I understand the xor part that we use this because of the toggle operation. I tried to form it without using "clr", but it didn't work. (I am using "clr" as clear input which is for resetting the flip-flop). Can't I do it without using "clr"?
I tried to change code like this below:
module t_flip_flop(t,clk,q,qn);
input t,clk;
output reg q,qn;
always #(posedge clk)
if(t)
begin
q<=q^t;
qn<=~(q^t);
end
But in the simulation, I get "x" for both q and qn in Vivado. I was expecting to get the same results as the code with "clr".
The clr signal is used to properly initialize q and qn.
You declared q as a reg type. In Verilog simulations, reg is initialized to x (the "unknown" value).
Consider your code without clr. At time 0, q=x. Let's say the posedge of clk is at 10ns and t=1 at that time. The assignment:
q<=q^t;
is evaluated like:
q <= x ^ 1;
Verilog evaluates x ^ 1 as x. Since x could be 0 or 1, we don't know if the expression is 1^1 or 0^1, which means that we don't know what the result of the expression should be. This means that q will remain x for the rest of the simulation. There will be no way to change its value.
Using the clr signal fixes that problem. Typically, at the start of simulation (time=0), you would set clr=0 so that q is assigned a known value (0). That prevents the x.
Even if you didn't start with clr=0, as soon as you do set clr=0 at a later time, that will resolve the x.
All of this applies to the qn signal as well.
(Verilog) The following is a 32-bit Arithmetic Logic Unit (ALU) [see slides]. It has two 2-1 and one 3-1 MUX, a 32-bit Adder, a 32-bit subtractor, and a 16-bit multiplier. The function table shows different functions this ALU performs for different values of F (a 3-bit control signal). Notice the interconnect among different modules inside the ALU.
Please describe this ALU using Verilog. Your implementation should start with the smaller blocks showing in the ALU, and then using those smaller blocks to build the whole ALU. In other words, your implementation should promote reusability of smaller modules (i.e., modular). Optimize your implementation if possible.
function table in the image
module adding(r,a,b);
input[31:0] a;
input[31:0] b;
output[31:0] r;
assign r=a+b;
endmodule
module ALU(F,A,B,R);
input[2:0] F;
input[31:0] A;
input[31:0] B;
output[31:0] R;
reg R;
always #(F)
begin
if ( F == 3'b000 ) adding ad(R,A,B);
else if ( F == 3'b001 ) R = A+1;
else if ( F == 3'b010 ) R = A-B;
else if ( F == 3'b011 ) R = A-1;
else if ( F == 3'b10x ) R = A*B;
end
endmodule
this what I did so far but I got errors!! I will continue with the other statement as I know how to make the first small module
Notice some basic verilog syntax issues.
bit width mismatch in declaration of R.
sensitivity list not complete for the always block.
module instantiation is not allowed under a structural if.
I don't know if the undefined branches for F is intended, it is leading to behavior perhaps your don't want.
Since you are mainly working on module partition, it's related to the point 3. You will need to instantiate the basic (reusable) modules separately, and then select the outputs via F.
wire [31:0] adder_b;
wire [31:0] adder_result;
assign adder_b = F[0] ? 32'h1 : B; // select input outside 'adding'
adding ad (adder_result, A, ader_b);
always#(*)begin
if(F2:1] == 2'b00) R = adder_result;
...
end
There are many ways to write simple code in verilog.it depends on requirement some time here I presented different ways to write this code.
first by assign keyword and the second by case statements.
assign result = (opcode==3'b000) ? A+B :
((opcode==3'b001)? A+1 :
((opcode==3'b010)? A-B :
((opcode==3'b011)? A-1 : A*B)));
always #(*) begin
casex(opcode)
3'b000: result=A+B;
3'b001: result=A+1;
3'b010: result=A-B;
3'b011: result=A-1;
3'b1xx: result=A*B;
endcase
end
I wrote some verilog code about a 7-to-1 Multiplexer with "always" and "case" statements but when I made a simulation in ModelSim, the outcome seems to not work as expected
Part of multiplexer logic :
when SW[9:7] = 000, OUT = SW[0]
Contradiction :
In the simulation when SW[0] is changed to 1, the outcome stays at 0.
module SevenToOneMUX(SW, OUT);
input [9:0] SW;
output reg OUT;
always#(SW[9:7])
begin
case (SW[9:7])
3'b000: OUT = SW[0];
3'b001: OUT = SW[1];
3'b010: OUT = SW[2];
3'b011: OUT = SW[3];
3'b100: OUT = SW[4];
3'b101: OUT = SW[5];
3'b110: OUT = SW[6];
endcase
end
endmodule
The problem is that you only put the 3 most-significant bit of SW in the sensitivity list of your combinational block. This means that the compiler will only execute the always#(SW[9:7]) block if SW[9:7] changes.
If you want to the simulator to update OUT when any of SW's bits changed, change your sensitivity list to the following:
always#(*)
begin
/*...*/
end
It is also worth to note that always#(*), which was added in Verilog-2001, is usually used when creating synthesizable combinational logic. In hardware, the real logic will be "sensitive" to every right-hand side variable. That means: if any input of the logic you describe changes, the output will also change.
I designed an ALU that does 4 operation depends on the value of op-code, and i used generate for conditional calling of sub module that i have to according to the project specification.But how i change the value of the parameter to move from one operation to another??
Here the code:
module ALU (A4, B4,cin4);
input [7:0] A4, B4;
input cin4;
//input [1:0] opc;
wire [7:0]out4;
wire cout4;
parameter opc=0;
generate
case (opc)
0: alu_add u1(out4,cout4,A4,B4,cin4); //calling an alu_add module
1: alu_sub u2(out4,cout4,A4,B4,cin4);
2: alu_comp u3_1(B4,out4);
3: alu_xor u4 (A4,B4,out4);
endcase
endgenerate
Parameters are for constants, and therefore can not be changed during simulation. Parameters can be overridden during instantiation.
What concerns me though is the use of the term call in the question. Generates are used to generate hardware based upon constants, ie they do not dynamically create and destroy hardware.
u1 to u4 are instances, describing physical hardware, what you have written at the minute is a ALU which can only do one thing. The code is configurable and given the user a choice of 4 things but once instanced then it is fixed.
To make a generic Generic ALU with all four operations available operations you need to select the output from the required ALU ie:
module ALU (
input [7:0] A4,
input [7:0] B4,
input cin4,
input [1:0] opc;
);
wire [7:0]out4, out4_0, out4_1, out4_2, out4_3;
wire cout4 ,cout4_0, cout4_1;
alu_add u1(out4_0,cout4_0,A4,B4,cin4); //calling an alu_add module
alu_sub u2(out4_1,cout4_1,A4,B4,cin4);
alu_comp u3_1(B4,out4_2);
alu_xor u4 (A4,B4,out4_3);
always #* begin
case (opc)
0: out4 = out4_0;
1: out4 = out4_1;
2: out4 = out4_2;
3: out4 = out4_3;
endcase
case (opc)
0: cout4 = cout4_0;
1: cout4 = cout4_1;
default: cout4 = 'b0;
endcase
end
endmodule
You can override a parameter's value when you instantiate the module. For example:
ALU #(.opc(1)) i1 ();
ALU #(.opc(2)) i2 ();
Refer to IEEE Std 1800-2012, Section "23.10.2.2 Parameter value assignment by name".
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.