Controller FSM Outputs are all don't care values

I’m trying to design the controller FSM for the MIPS multicycle CPU. My first two states output the correct result. But after that they are all don’t care values and I don’t know why. The op(opcode) and funct are instruction parameters. The zero signal is an output signal of the ALU that is 1 if the ALU result is 0. In my testbench, I’m only testing only the beq insruction in my function.

CODE:


module controller(input logic clk, reset,
input logic [5:0] op, funct,
input logic zero,
output logic pcen, memwrite, irwrite, regwrite,
output logic alusrca, iord, memtoreg, regdst,
output logic [1:0] alusrcb, pcsrc,
output logic [2:0] alucontrol);
logic [1:0] aluop;
logic branch, pcwrite;
// Main Decoder and ALU Decoder subunits.
	maindec md(clk, reset, op,
	pcwrite, memwrite, irwrite, regwrite,
	alusrca, branch, iord, memtoreg, regdst,
	alusrcb, pcsrc, aluop);
	aludec ad(funct, aluop, alucontrol);
// ADD CODE HERE
// Add combinational logic (i.e. an assign statement)
// to produce the PCEn signal (pcen) from the branch,
// zero, and pcwrite signals
	assign pcen=(branch && zero) ||(pcwrite);
endmodule

//MAINDEC:
module maindec(input logic clk, reset,
input logic [5:0] op,
output logic pcwrite, memwrite, irwrite, regwrite,
output logic alusrca, branch, iord, memtoreg, regdst,
output logic [1:0] alusrcb, pcsrc,
output logic [1:0] aluop);
parameter FETCH = 4'b0000; // State 0
parameter DECODE = 4'b0001; // State 1
parameter MEMADR = 4'b0010; // State 2
parameter MEMRD = 4'b0011; // State 3
parameter MEMWB = 4'b0100; // State 4
parameter MEMWR = 4'b0101; // State 5
parameter RTYPEEX = 4'b0110; // State 6
parameter RTYPEWB = 4'b0111; // State 7
parameter BEQEX = 4'b1000; // State 8
parameter ADDIEX = 4'b1001; // State 9
parameter ADDIWB = 4'b1010; // state 10
parameter JEX = 4'b1011; // State 11
parameter LW = 6'b100011; // Opcode for lw
parameter SW = 6'b101011; // Opcode for sw
parameter RTYPE = 6'b000000; // Opcode for R-type
parameter BEQ = 6'b000100; // Opcode for beq
parameter ADDI = 6'b001000; // Opcode for addi
parameter J = 6'b000010; // Opcode for j
	logic [3:0] state, nextstate;
	logic [14:0] controls;
// state register
	always_ff @(posedge clk or posedge reset)
	begin
	if(reset) state <= FETCH;
	else state <= nextstate;
	end

// ADD CODE HERE
// Finish entering the next state logic below. The first
// two states, FETCH and DECODE, have been completed for you.
// next state logic
	always_comb
	case(state)
	FETCH: nextstate = DECODE;
	DECODE: case(op)
	LW: nextstate = MEMADR;
	SW: nextstate = MEMADR;
	RTYPE: nextstate = RTYPEEX;
	BEQ: nextstate = BEQEX;
	ADDI: nextstate = ADDIEX;
	J: nextstate = JEX;
	default: nextstate = 4'bx; // should never happen
	endcase
// Add code here
	MEMADR: case(op)
	LW: nextstate=MEMRD;
	SW: nextstate= MEMWR;
	default: nextstate= 4'bx;
	endcase

	MEMRD: nextstate= MEMWB;
	MEMWB: nextstate= FETCH;
	MEMWR: nextstate=FETCH;
	RTYPEEX: nextstate= RTYPEWB;
	RTYPEWB: nextstate= FETCH;
	BEQEX: nextstate= FETCH;
	ADDIEX: nextstate= ADDIWB;
	ADDIWB: nextstate= FETCH ;
	JEX: nextstate= FETCH;
	default: nextstate = 4'bx; // should never happen
	endcase

// output logic
	assign {pcwrite, memwrite, irwrite, regwrite,
	alusrca, branch, iord, memtoreg, regdst,
	alusrcb, pcsrc, aluop} = controls;

// ADD CODE HERE
// Finish entering the output logic below. The
// output logic for the first two states, S0 and S1,
// have been completed for you.
	always_comb
	case(state)
	FETCH: controls = 15'h5010;
	DECODE: controls = 15'h0030;
	// your code goes here
	MEMADR: controls = 15'h0420;
	MEMRD: controls = 15'h0520;
	MEMWB: controls = 15'h0da0;
	MEMWR: controls = 15'h25a0;
	RTYPEEX: controls = 15'h0582;
	RTYPEWB: controls = 15'h0d42;
		BEQEX: controls = 15'h0745;
	ADDIEX: controls = 15'h0564;
	ADDIWB: controls = 15'h0c24;
	JEX: controls = 15'h4428;
	default: controls = 15'hxxxx; // should never happen
	endcase
endmodule

// ALUDEC:
module aludec(input logic [5:0] funct,
input logic [1:0] aluop,
output logic [2:0] alucontrol);
// ADD CODE HERE
// Complete the design for the ALU Decoder.
// Your design goes here. Remember that this is a combinational
// module.
// Remember that you may also reuse any code from previous labs.
always_comb
    case(aluop)
      2'b00: alucontrol = 3'b010;  // add
      2'b01: alucontrol = 3'b110;  // sub
      2'b11: alucontrol = 3'b001;  // OR
      default: case(funct)          // RTYPE
          6'b100000: alucontrol = 3'b010; // ADD
          6'b100010: alucontrol = 3'b110; // SUB
          6'b100100: alucontrol = 3'b000; // AND
          6'b100101: alucontrol = 3'b001; // OR
          6'b101010: alucontrol = 3'b111; // SLT
          default:   alucontrol = 3'bxxx; // ???
        endcase
    endcase
endmodule


TESTBENCH:


module testbench();
logic clk,reset,zero,pcen;
logic [5:0] op,funct;
logic [15:0] controls;
logic [3:0] state;
logic [2:0] alucontrol;
logic [1:0] aluop;
logic  memwrite, irwrite, regwrite,alusrca, iord, memtoreg, regdst;
logic [1:0] alusrcb, pcsrc;

controller dut(.clk(clk),.reset(reset),.op(op),.funct(funct),.zero(zero),.alucontrol(alucontrol),.pcen(pcen)
,.memwrite(memwrite),.irwrite(irwrite),.regwrite(regwrite),.alusrca(alusrca)
,.iord(iord),.memtoreg(memtoreg),.regdst(regdst),.alusrcb(alusrcb),.pcsrc(pcsrc));

always
    begin
      clk = 1; # 5; clk = 0; # 5;
    end
initial
begin
reset=1;#10;
reset=0;#10;
op=000100;
funct=000000;
zero=1;#10;
end
endmodule


change your testbench code to

op=6’b000100;

The value of ‘op’ being passed into the DUT was being treated as a decimal number
ie 100

which when you convert to binary is 1100100
but since op is defined as [5:0] then the MSB got dropped

So the value of op inside the DUT was seen as ‘100100’ which is not a valid state

In reply to graeme_jessiman:
Yes, that did make the signals display properly. However, I instantiated the maindec module in my testbench because I wanted to output the state and controls signals. But they are still don’t care values after adding the change you suggested.How do I make them to work?

My new testbench is:


module testbench();
		logic clk, reset, zero, pcen,pcwrite,branch;
		logic [5:0]  op, funct;
		logic [14:0] controls;
		logic [3:0]  state;
		logic [2:0]  alucontrol;
		logic [1:0]  aluop;
		logic  		 memwrite, irwrite, regwrite,alusrca, iord, memtoreg, regdst;
		logic [1:0]  alusrcb, pcsrc;

		controller dut(.clk(clk), .reset(reset), .op(op), .funct(funct)
		, .zero(zero), .alucontrol(alucontrol), .pcen(pcen)
		, .memwrite(memwrite), .irwrite(irwrite), .regwrite(regwrite)
		, .alusrca(alusrca), .iord(iord), .memtoreg(memtoreg)
		, .regdst(regdst) , .alusrcb(alusrcb), .pcsrc(pcsrc));

		maindec dut_1(.clk(clk), .reset(reset), .op(op),.pcwrite(pcwrite),.memwrite(memwrite), .irwrite(irwrite), .regwrite(regwrite)
		,.alusrca(alusrca),.branch(branch),.iord(iord),.memtoreg(memtoreg), .regdst(regdst) , .alusrcb(alusrcb), .pcsrc(pcsrc),.aluop(aluop));

		always
		 begin
			clk = 1; # 5; 
			clk = 0; # 5;
		 end
		
		initial 
		begin
		
		reset = 1; #10;
		reset = 0; 
		
		op = 	6'b000100;
		funct= 	6'b100010;
		zero = 1;  #10;
		end
endmodule

I modified the order of the assignments… .as op was not getting any value until after the #10 had executed 10 time units.
i.e.

initial
begin
  op=6'b000100;
  funct=6'b100010

  reset=1;#10;
  reset=0;#10;
  zero=1;#10;
end

This simulates and I see state & next_state change every clock cycle

In reply to graeme_jessiman:

I tried this code. However, state and controls always stay as don’t care values. Also, for some reason, I don’t see nextstate listed on my waveform screen. The code I used was:

CODE:


module controller(input logic clk, reset,
						input logic [5:0] op, funct,
						input logic zero,
						output logic pcen, memwrite, irwrite, regwrite,
						output logic alusrca, iord, memtoreg, regdst,
						output logic [1:0] alusrcb, pcsrc,
						output logic [2:0] alucontrol);

	logic [1:0] aluop;
	logic branch, pcwrite;
						
	// Main Decoder and ALU Decoder subunits.
	maindec md(clk, reset, op,
				  pcwrite, memwrite, irwrite, regwrite,
				  alusrca, branch, iord, memtoreg, regdst,
				  alusrcb, pcsrc, aluop);
	aludec ad(funct, aluop, alucontrol);

	 // ADD CODE HERE
    // Add combinational logic (i.e. an assign statement)
    // to produce the PCEn signal (pcen) from the branch,
	 // zero, and pcwrite signals
	
	assign pcen = (branch && zero) || (pcwrite);
	
endmodule

//MAINDEC:
module maindec(input logic clk, reset,
					input logic [5:0] op,
					output logic pcwrite, memwrite, irwrite, regwrite,
					output logic alusrca, branch, iord, memtoreg, regdst,
					output logic [1:0] alusrcb, pcsrc,
					output logic [1:0] aluop);

	parameter FETCH  	= 4'b0000; // State 0
	parameter DECODE 	= 4'b0001; // State 1
	parameter MEMADR 	= 4'b0010; // State 2
	parameter MEMRD  	= 4'b0011; // State 3
	parameter MEMWB  	= 4'b0100; // State 4
	parameter MEMWR  	= 4'b0101; // State 5
	parameter RTYPEEX = 4'b0110; // State 6
	parameter RTYPEWB = 4'b0111; // State 7
	parameter BEQEX 	= 4'b1000; // State 8
	parameter ADDIEX 	= 4'b1001; // State 9
	parameter ADDIWB 	= 4'b1010; // state 10
	parameter JEX 		= 4'b1011; // State 11
	parameter LW 		= 6'b100011; // Opcode for lw
	parameter SW 		= 6'b101011; // Opcode for sw
	parameter RTYPE 	= 6'b000000; // Opcode for R-type
	parameter BEQ 		= 6'b000100; // Opcode for beq
	parameter ADDI 	= 6'b001000; // Opcode for addi
	parameter J 		= 6'b000010; // Opcode for j
	
	logic [3:0] state, nextstate;
	logic [14:0] controls;

		// state register

		always_ff @(posedge clk or posedge reset)
			if(reset) state <= FETCH;
			else state <= nextstate;
			
			// ADD CODE HERE
			// Finish entering the next state logic below. The first
			// two states, FETCH and DECODE, have been completed for you.
			// next state logic

			always_comb
				case(state)
					FETCH: 		nextstate = DECODE;
					DECODE: 		
						case(op)
							LW: 			nextstate = MEMADR;
							SW: 			nextstate = MEMADR;
							RTYPE: 		nextstate = RTYPEEX;
							BEQ: 			nextstate = BEQEX;
							ADDI: 		nextstate = ADDIEX;
							J: 			nextstate = JEX;
							default: 	nextstate = 4'bx; // should never happen
						endcase
				
					// Add code here
					MEMADR: 
						case(op)
							LW: nextstate = MEMRD;
							SW: nextstate = MEMWR;
							default: nextstate= 4'bx;
						endcase

					MEMRD: 	nextstate = MEMWB;
					MEMWB: 	nextstate = FETCH;
					MEMWR: 	nextstate = FETCH;
					RTYPEEX: nextstate = RTYPEWB;
					RTYPEWB: nextstate = FETCH;
					BEQEX: 	nextstate = FETCH;
					ADDIEX: 	nextstate = ADDIWB;
					ADDIWB: 	nextstate = FETCH ;
					JEX: 		nextstate = FETCH;
					default: nextstate = 4'bx; // should never happen
				endcase

		// output logic
		assign {pcwrite, memwrite, irwrite, regwrite,
				  alusrca, branch, iord, memtoreg, regdst,
				  alusrcb, pcsrc, aluop} = controls;

		// ADD CODE HERE
		// Finish entering the output logic below. The
		// output logic for the first two states, S0 and S1,
		// have been completed for you.

		always_comb
			case(state)
				FETCH:  controls = 15'h5010;
				DECODE: controls = 15'h0030;
				
				// your code goes here
				MEMADR: 	controls = 15'h0420;
				MEMRD:  	controls = 15'h0520;
				MEMWB: 	controls = 15'h0da0;
				MEMWR:  	controls = 15'h25a0;
				RTYPEEX: controls = 15'h0582;
				RTYPEWB: controls = 15'h0d42;
				BEQEX:  	controls = 15'h0745;
				ADDIEX: 	controls = 15'h0564;
				ADDIWB: 	controls = 15'h0c24;
				JEX: 		controls = 15'h4428;
				default: controls = 15'hxxxx; // should never happen
			endcase
endmodule

// ALUDEC:
module aludec(input logic [5:0] funct,
				  input logic [1:0] aluop,
				  output logic [2:0] alucontrol);
				  
				// ADD CODE HERE
				// Complete the design for the ALU Decoder.
				// Your design goes here. Remember that this is a combinational
				// module.
				// Remember that you may also reuse any code from previous labs.
				always_comb
					 case(aluop)
						2'b00: alucontrol = 3'b010;  // add
						2'b01: alucontrol = 3'b110;  // sub
						2'b11: alucontrol = 3'b001;  // OR
						default: 
								case(funct)          // RTYPE
									 6'b100000: alucontrol = 3'b010; // ADD
									 6'b100010: alucontrol = 3'b110; // SUB
									 6'b100100: alucontrol = 3'b000; // AND
									 6'b100101: alucontrol = 3'b001; // OR
									 6'b101010: alucontrol = 3'b111; // SLT
									 default:   alucontrol = 3'bxxx; // ???
								endcase
					 endcase
endmodule

TESTBENCH:


module testbench();
		logic clk, reset, zero, pcen,pcwrite,branch;
		logic [5:0]  op, funct;
		logic [14:0] controls;
		logic [3:0]  state;
		logic [2:0]  alucontrol;
		logic [1:0]  aluop;
		logic  		 memwrite, irwrite, regwrite,alusrca, iord, memtoreg, regdst;
		logic [1:0]  alusrcb, pcsrc;

		controller dut(.clk(clk), .reset(reset), .op(op), .funct(funct)
		, .zero(zero), .alucontrol(alucontrol), .pcen(pcen)
		, .memwrite(memwrite), .irwrite(irwrite), .regwrite(regwrite)
		, .alusrca(alusrca), .iord(iord), .memtoreg(memtoreg)
		, .regdst(regdst) , .alusrcb(alusrcb), .pcsrc(pcsrc));

		maindec dut_1(.clk(clk), .reset(reset), .op(op),.pcwrite(pcwrite),.memwrite(memwrite), .irwrite(irwrite), .regwrite(regwrite)
		,.alusrca(alusrca),.branch(branch),.iord(iord),.memtoreg(memtoreg), .regdst(regdst) , .alusrcb(alusrcb), .pcsrc(pcsrc),.aluop(aluop));

		always
		 begin
			clk = 1; # 5; 
			clk = 0; # 5;
		 end
		
		initial 
		begin
		
		op=6'b000100;
  		funct=6'b100010;
  		reset=1;#10;
  		reset=0;#10;
  		zero=1;#10;
		
		/*
		reset = 1; #10;
		reset = 0; 
		
		op = 	6'b000100;
		funct= 	6'b100010;
		zero = 1;  #10;
		*/
		end
endmodule


In reply to VIKRANT97:

I’ve posted the code on EDA Playground at

Edit code - EDA Playground

Just try running the simulation and then look at the state & nextstate signals from the ‘md’ module using EPWave.
The signals are changing value as expected

In reply to graeme_jessiman:

Yes, it works correctly on the website you posted. However, the same code doesn’t work for me. Why is that? I’m using Modelsim PE Sudent Edition 10.4a

In reply to VIKRANT97:

I just downloaded and installed ModelSim PE 10.4g and the design simulated just fine for me.
[10.4g was as far back as I could go to get the install files]
Try deleting the work library and compiling the design from scratch again.