inout with reg type in verilog - verilog

I have used inout with c, but for c to be on the LHS of procedural assignment, it needs to be a reg type variable. Can anyone help me out with this code?
module multiedgeclk(input clk ,[7:0] a,b,d, inout [7:0] c, output reg [7:0]f);
always #(posedge clk)
c <= a + b;
always #(negedge clk)
f = c & d;
endmodule

In verilog inout is the direction of the port. wire or reg is the type of the signal.
If you want to drive a bi-directional port, it should be declare as inout wire or inout and drive it with enable signal
Here is a example of bi-directional port.
module ABC( inout [7:0] c );
reg [7:0] c_out;
reg out_en;
assign c = out_en ? 8'hz : c_out;
/* something here
...
*/
endmodule

An inout port cannot be procedurally assigned. There is nothing to indicate how long to hold that value on the port. This is the problem for any wire. But wires have a strength mechanism for multiple continuous drivers, the highest strength wins. So you can use a continuous assignment to selectively drive a value or turn it off by driving a z value.
wire c;
reg c_reg;
assign c = c_reg;
Now you can procedurally assign c_reg to a value or 8'bz
See my article for more info about wires and reg types.

Related

Verilog module instantiation reg input output

While implementing Verilog code in behavioral modeling we are using reg as output. But, when I have to use module instantiation and connect it using a wire, it's showing an error while implementation. Is there any other way where I can use module instantiation to connect outputs of different module instances to implement combinational logic as it's illegal to connect the reg output of the previous model to a wire? Note that I have to apply behavioral modeling hence no assignment statements are allowed. This is an example to connect two half adders to one full adder.
module half_adder(input wire a,b,output reg sum,output reg carry);
always#(a or b)
begin
sum = a^b ;
carry= a & b ;
end
endmodule
module full_adder(input wire a,b,c,output reg sum,output reg carry);
wire s1,c1,c2;
half_adder gate1(a,b,s1,c1);
half_adder gate2(s1,c,sum,c2);
always#(a or b or c)
begin
carry = c1|c2;
end
endmodule
Error (10663): Verilog HDL Port Connection error at full_adder.v(14):
output or inout port "sum" must be connected to a structural net
expression
In standard old verilog a reg cannot be connected to a reg using module connection or a continuous assignment. System verilog allows it. So, one of the solutions could be to switch to system verilog.
As for verilog, in half_adder port sum is declared as a reg. Instance gate2 connects variable of type reg to the port of type reg. This is illegal. This type of an assignment can only happen inside a procedural (i.e. always) block. Instance gate1 bypasses this issue by connecting port to the wire s1.
So, you can follow the similar path. Create another wire s2 as in the following example.
module full_adder(input wire a,b,c,output reg sum,output reg carry);
wire s1,c1, s2, c2;
half_adder gate1(a,b,s1,c1);
half_adder gate2(s1,c,s2,c2); // use s2 here
always#*
carry = c1|c2;
always #*
sum = s2; // now you can s2 assign to the 'sum' port
endmodule
Another way is to declare the 'sum' port as a wire. A register can be connected to a wire, using port connections or continuous assignment.
module full_adder(input wire a,b,c,
output sum, // declares it as a wire
output reg carry);
...
half_adder gate2(s1,c,sum,c2); // now it works this way.
And btw, do not use #(a,b,c). It is always error prone and is just wrong in your case. It should be #(c1,c2). But it is much better to use #*.
You should not declare sum as a reg in the full_adder module because it is not being assigned inside a procedural block (such as always). A reg is not a "net" type. Change:
module full_adder(input wire a,b,c,output reg sum,output reg carry);
to:
module full_adder(input wire a,b,c,output sum,output reg carry);
You also have an incorrect sensitivity list. Change:
always#(a or b or c)
to:
always #*
Now, the always block will trigger when the signals on the RHS of the assignments change.

I am getting unknown value when doing a 4 bit shifter verilog (gate level)

I am trying to implement a 4 bit right shifter using gate level but i got unknown result for some reason, my mux work ok but when i try testbench for my shifter it give back something like this:
a=0010 b=01 c=0000
a=1111 b=01 c=00xx
Please help!!!! Thank you very much
module mux2(a,b,sel,c);
output c;
input a,b,sel;
wire net0,net1,net2;
not m1(net0,sel);
and m2(net1,a,net0);
and m3(net2,b,sel);
or m4(c,net1,net2);
endmodule
module mux4(a,sel,c);
output c;
input [1:0]sel;
input[3:0]a;
wire mux_1,mux_2;
mux2 m1(a[3],a[2],sel[0],mux_1);
mux2 m2(a[1],a[0],sel[0],mux_2);
mux2 m3(mux_1,mux_2,sel[1],c);
endmodule
module shift4bitright(c,a,b);
output [3:0]c;
input [3:0]a;
input [1:0]b;
wire [3:0]d=4'h0,d1=4'h0,d2=4'h0,d3=4'h0;
assign d[0]=a[3];
assign d1[0]=a[2]; assign d1[1]=a[3];
assign d2[0]=a[1]; assign d2[1]=a[2]; assign d2[2]=a[3];
assign d3[0]=a[0]; assign d3[1]=a[1];assign d3[2]=a[2];assign d3[3]=a[3];
mux4 m1(d,b,c[3]);
mux4 m2(d1,b,c[2]);
mux4 m3(d2,b,c[1]);
mux4 m4(d3,b,c[0]);
endmodule
`timescale 10ns/1ns
module shift4bitright_tb;
wire [3:0]c;
reg [3:0]a;
reg [1:0]b;
shift4bitright s1(.c(c),.a(a),.b(b));
initial begin
$monitor("a=%b b=%b c=%b",a,b,c);
a=4'h2;
b=2'd1;
#50
a=4'hf;
b=2'd1;
end
endmodule
This statement declared a wire type signal d as well as its driver cone (NOT initial value), which is a constant 0 in this case:
wire [3:0]d=4'h0;
Just below it, there's another a[3] driving d[0]:
assign d[0]=a[3];
This creates a multi-driven logic, hence x occurs.
To solve it, change it similar to:
wire [3:0] d;
assign d = {3'h0, a[3]};

Leaving some bits in the port vector disconnected. Verilog module instantiation

Lets say I have a Verilog module with bit vector ports. How do I
instantiate it with some bits left unconnected?
I tried something like this but it didn't work:
module sub (in,out)
input [3:0] in;
output [3:0] out;
endmodule
module top;
wire [1:0] a1;
wire [1:0] c1;
sub Sub1(
.in[2:1](a1[1:0]),
.out[2:1](c1[1:0])
);
endomdule
It would be much easier to just declare signals of the correct size and use a continuous assignment
module top;
wire [1:0] a1;
wire [1:0] c1;
wire [3:0] pin;
wire [3:0] pout;
assign pin[2:1] = a1;
assign c1 = pout[2:1];
sub Sub1(
.in(pin),
.out(pout)
);
endomdule
In general, it is not a good idea to leave input ports floating. You could use a concatenation in the assignment, or directly in the port connection.
sub Sub1(
.in({1'b0,a1,1'b0}),
.out({pout[3],c1,pout[0]})
);
SystemVerilog has a net aliasing construct that makes thing even simpler
module top;
wire [3:0] pin;
wire [3:0] pout;
alias pin[2:1] = a1;
alias pout[2:1] = c1;
sub Sub1(
.in(pin),
.out(pout)
);
endomdule
Found LRM reference on why you cannot connect parts of ports.
LRM 1800-2012 Section 23.3.2.2 Connecting module instance ports by name:
The port_name shall be the name specified in the module declaration. The port name cannot be a bit-select, a part-select, or a concatenation of ports.
you cannot connect/disconnect parts of a port. You can do it with the whole port though. so, in your case you nedd to split your port in several parts, something like the following:
module sub (in1, in2, out1, out2);
input [2:1] in1;
input [1:0] in2;
output [2:1] out1;
output [1:0] out2;
endmodule
module top;
wire [1:0] a1;
wire [1:0] c1;
sub Sub1(
.in1(a1[1:0]),
.in2(),
.out1(c1[1:0]),
.out2()
);
endmodule
My code connect 4-bits to module's 8-bit outputs, upper/lower even middle part.
It does work, but what the hell is the 's'(or anything)?
It works in both Quartus Prime 18.0pro and Lattice Diamond 3.10(Symplify Pro).
module dff8
(
input clk,
input [7:0] a,
output reg [7:0] b
);
always # (posedge clk) begin
b <= a;
end
endmodule
module top
(
input clk,
input [7:0] x,
output [3:0] y,
output [3:0] z
);
dff8 u0 (.clk(clk), .a(x), .b({y,s,s,s,s}));
dff8 u1 (.clk(clk), .a(x), .b({s,s,s,s,z}));
endmodule

Write to a reg's bitfields via alias names in Verilog

I have a register:
reg [7:0] dout; //output of memory bus
Groups of bits in dout represent something meaningful like:
dout[2:0] is a state
dout[3] is a flag
dout[7:4] is some data
I want to read and write to this register dout from inside an always statement. I want to address it using these labels.
This example conveys my attempt:
reg [7:0] dout; //output of memory bus
wire [2:0] dout_state;
wire dout_flag;
wire [3:0] dout_data;
//alias labels
assign dout_state[2:0] = dout[2:0];
assign dout_flag = dout[3];
assign dout_data = dout[7:4];
always(#posedge clk) begin
dout_state <= 3'b1;
dout_flag <= 1'b1;
end
The procedural assignments fail because dout_state and dout_flag are wires.
I want these labels to work as aliases that represent portions of the dout bus.
How can I achieve this?
The always block already drives dout_state and dout_flag signals, so the other assignments should be reversed. Your current code never drives dout.
//alias labels
assign dout[2:0] = dout_state;
assign dout[3] = dout_flag;
assign dout[7:4] = dout_data;
Now the signal definitions also should be updated. If dout is a port, the reg definition should be removed. If not, it should be a wire.
wire [7:0] dout; //output of memory bus
Because of the always block, dout_state and dout_flag signals should be reg.
reg [2:0] dout_state;
reg dout_flag;

Having trouble with Verilog inout wires

For the record, I'm a complete Verilog newbie. I'm writing a module that uses a few bidirectional buses.
inout wire [KEY_SIZE-1:0] prevKey;
inout wire [TAG_SIZE-1:0] prevTag;
inout wire [KEY_SIZE-1:0] nextKey;
inout wire [TAG_SIZE-1:0] nextTag;
I know how I read things off of the bus, but how do I write something onto it? If I use an assign statement to a reg, will the value of the reg get clobbered when new data comes onto the wire? Is dealing with an inout port worth the hassle, or should I just make an input and and output bus for each?
If I use an assign statement to a reg...
This statement doesn't really make sense, you don't do assignments to regs, you do assignments to wires.
Simple example of driving an inout wire:
inout wire bidir_wire;
reg drive_value;
reg drive_enable;
reg something;
assign bidir_wire = drive_enable ? drive_value : 1'bz;
always #(posedge clk) begin
drive_value <= ... ; //assign a drive value based on some criteria
drive_enable <= ...;
something <= bidir_wire; //do something with the input value
end

Resources