I am writing a simple Control Unit in verilog. It goes something like this.
module controlUnit(
output reg wreg,
input wire [5:0] op, func
);
// wreg sub-handles. Beware: wreg is 0 if any of these s high
wire isBranch = (op[5:3] == 3'b0) & (|op[2:0]);
wire isStrWrd = op == 6'b101011;
wire isJumpReg = (op == 6'd0) & (func == 6'b001000);
// wreg handle
always @(*) begin
if(isBranch | isStrWrd | isJumpReg)
wreg <= op == 6'b000011;
else
wreg <= 1'b1;
end
endmodule
module testbench;
integer i;
wire out;
reg [11:0] in;
controlUnit CU0(
.wreg(out),
.op(in[11:6]), .func(in[5:0])
);
initial begin
$dumpfile("test.vcd");
$dumpvars(0, testbench);
#4 in = 0;
for(i=0; i<1024; i=i+1) begin
#1 in = i;
end
#1 in = 10'hXX; // Garbage input here
#1000;
end
endmodule
However in simulation, the wreg signal is a solid logical HIGH when the input becomes garbage. I have seen this behaviour with iverilog-10/GTKwave and Vivado 2019.1. Following is the waveform:
So, why?
You only set 10 of your 12 input bits to x
; the 2 MSBs are 0. You should set all of your input signals to x
. This is probably unrelated to your problem, but I think it is what you intended. Change:
#1 in = 10'hXX; // Garbage input here
to:
#1 in = {12{1'bx}}; // Garbage input here
When the signals in if(isBranch | isStrWrd | isJumpReg)
are x
, the if
is false, and the else
is executed, which sets wreg
to 1 (wreg <= 1'b1
), not x
. This answers the question of why the Verilog simulator assigns wreg
to 1 when all the inputs are x
. This is the way the simulator is designed to work.
Using the ternary operator equivalent code will set wreg
to x
when the inputs are x
:
always @(*) begin
wreg = (isBranch | isStrWrd | isJumpReg) ? (op == 6'b000011) : 1'b1;
end
Note that using a blocking assignment (=
) is recommended for combinational logic.