verilogmodelsimlc3

LC-3 16 bit processor wrong simulation in Verilog


I am working on designing a LC-3(Little Computer) CPU. I have designed PC unit, Control Unit(as Finite State Machine), Instruction Memory, ALU unit and Data Memory in Modules. There is also a Register File unit which works as Main, module calls are done in this unit.

I want the program to work as when PCread is 1, get the variable that going to be assigned to out from in variable, and when PCwrite is 1, just increment the out variable. out is the address that sent to the Instruction Memory.

The problem is when I simulate, instruction never loads to the Instruction Memory. Because PCwrite does not work for the first state of the Control Unit, because I reset both PCread and PCread variables in the first state. I do this because I do not want the instruction to load until one instruction finishes it work. I could not find a way to handle this.

I know if this is solved, processor will work because when I try it for one instruction with initialized values, it works.

module reg_fileandMain();
  
  parameter B=16, W=3;
  
  reg Clk;
  wire wr_en;
  wire [W-1:0] w_addr, r_addr1, r_addr2;
  wire [B-1:0] inData;
  wire [B-1:0] r_data1;
  wire [B-1:0] r_data2;
  wire [B-1:0] address;
  wire Dataout;
  wire InsMemRead;
  
  reg [15:0] extended, mux1out, mux2out, mux3out, mux4out, mux5out;
  wire ALUout, incrementer;
  wire [15:0] instruction;
  reg [B-1:0] array_reg[2**W-1:0];
  wire mux1,mux3,mux4,mux5;
  wire [1:0] mux2;
  
  initial begin
    mux5out=16'hFFFF;
  end

  wire MemRead,PCwrite,ALUcontrol,MemWrite,PCread;
  
  always@(posedge Clk)
  begin
  if(wr_en)begin
    array_reg[w_addr]<=inData;
  end
  end
  assign r_data1=array_reg[r_addr1];
  assign r_data2=array_reg[r_addr2];
  
  controlUnit controlUnit0(Clk,instruction,mux1,mux2,mux3,mux4,mux5,InsMemRead,MemRead,PCwrite,wr_en,ALUcontrol,MemWrite,PCread,r_addr1,r_addr2,w_addr);
  
  PCunit PCunit0(Clk,PCwrite,PCread,mux5out,address);
  
  DataMem DataMem0(Clk,mux2out,r_data1,MemRead,MemWrite,Dataout);
    
  ALU ALU0(mux1out,r_data2,ALUout,ALUcontrol);
  
  InstructionMemory InstructionMemory0(Clk,address,InsMemRead,instruction);
  
  always @* begin
  if(mux1)begin
    extended = { {11{instruction[4]}}, instruction[4:0] };
    mux1out=extended;
  end
  else begin
    mux1out=r_data1;
  end
  
  if(mux2==2'b00)begin
    mux2out=ALUout;
    end
  else if(mux2==2'b01)begin
    extended = instruction[8:0];
    mux2out=extended;
    end
  else if(mux2==2'b11)begin
    extended = instruction[8:0];
    mux2out=extended;
    end
    
  if(mux3)begin
    mux3out<=mux2out;
    end
  else begin
    mux3out<=Dataout;
    end
    
  if(mux4)begin
    mux4out<=address;
    end
  else begin
    mux4out<=mux3out;
    end
    
  if(mux5)begin
    mux5out<=address;
    end
  else begin
    mux5out<=mux3out;
    end 

end

   assign inData=mux4out;
       always begin
   #20 Clk<=0;
   #20 Clk<=1;
 end

endmodule
    


module controlUnit(Clk,in,mux1,mux2,mux3,mux4,mux5,InsMemRead,MemRead,PCwrite,WE,ALUcontrol,MemWrite,PCread,rd1,rd2,wr);
  
  input Clk;
  input [15:0] in;
  output reg mux1,mux3,mux4,mux5,InsMemRead,MemRead,PCwrite,WE,ALUcontrol,MemWrite,PCread;
  output reg [1:0] mux2;
  reg [3:0] state,stateNext;
  
  reg counter;
  output wire [2:0] rd1,rd2,wr;
  
  initial begin
    state=4'b0000;
    stateNext=4'b0001;
    MemRead=0;
    
    PCwrite=1;
  end
  
    assign rd1=in[2:0];
    assign rd2=in[8:6];
    assign wr=in[11:9];
  
  
  
  always @* begin
      
    if (state==4'b0000)begin
      stateNext=4'b0001;
      PCwrite=0;
      PCread=0;
    end
    if(state==4'b0001)
      begin
      InsMemRead<=1;
    if(in[15:12]==4'b0100)begin
      stateNext=4'b0100;
      InsMemRead=1'b1;
    end
    else if( in[15:12]==4'b1000)begin
      stateNext=4'b0100;
      InsMemRead=1;
    end
      else if(in[15:12]==4'b0010)begin
      stateNext=4'b0010;
      InsMemRead=1;
    end
      else if(in[15:12]==4'b1100)begin
      stateNext=4'b1100;
      InsMemRead=1;
    end
      else if(in[15:12]==1010)begin
      stateNext=4'b1010;
      InsMemRead=1;
    end
  end
    else if(state==4'b0100)begin
      stateNext=4'b0101;
    end
    else if(state==4'b0101)begin
      stateNext=4'b0000;
      mux3=0;
      mux4=0; 
      WE=1; 
      mux2=2'b01; 
      MemRead=1;
      mux5=1;
      PCwrite=1;
    end
    else if(state==4'b1000)begin
      stateNext=4'b0000;
      mux1=in[5];
      ALUcontrol=0; 
      mux3=1;
      mux4=0;
      WE=1;
      PCwrite=1;
    end
    else if(state==4'b0010)begin
      stateNext=4'b0000;
      mux1=in[5];
      ALUcontrol=1;
      mux3=1;
      mux4=0;
      WE=1;
      PCwrite=1;
    end
      else if(state==4'b1100)begin
      stateNext=4'b0000;
      mux2=2'b01;
      MemWrite=1;
      PCwrite=1;
    end
    else if(state==4'b1010)begin
      stateNext=4'b0000;
      mux2=2'b11;
      mux3=1;
      mux5=0;
      PCread=1;
      
    end
  end
  always @(posedge Clk) begin
      state = stateNext;
  end
  
endmodule

module PCunit(Clk,PCwrite,PCread,in,out);
  input Clk,PCread,PCwrite;
   
  input wire [15:0] in;
  output reg [15:0] out;
  
  
always @(posedge Clk) begin
        
      if(PCwrite)
      begin
      out<=out+1; 
       end
      else
      begin
       if(PCread)
      begin
      out<=in;
      end 
      end
    end
    
endmodule

module ALU(in1,in2,ALUout,ALUcontrol);
  input ALUcontrol;
  input wire [15:0] in1, in2;
  output reg [15:0] ALUout;
  
    always @* begin
    if(ALUcontrol) 
      
    ALUout = in1 + in2;

else
    ALUout = in1 & in2; 

end
  endmodule

module DataMem(Clk,AddrReg,in,MemRead,MemWrite,out);
  input Clk, MemRead, MemWrite;
  input [15:0] AddrReg, in;
  output reg [15:0] out;
  
  reg[15:0] Mem[2**9:0];
  
  always @(posedge Clk) begin
    if(MemWrite)begin
      Mem[AddrReg]=in;
    end
  end
  
  always @* begin
    if(MemRead) begin
      out=Mem[AddrReg];
      end
      end
  
endmodule

module InstructionMemory(Clk,address,InsMemRead,instruction);
  input Clk;
  input [15:0] address;
  input InsMemRead;
  output reg [15:0] instruction;
  
  reg [15:0] InstructionMemory [15:0];
  
  initial begin
    $readmemh("AssemblerOutput.hex", InstructionMemory);
  end
  
  always@(posedge Clk)begin
    if(InsMemRead)
  instruction=InstructionMemory[address];
end
endmodule
  

Solution

  • Always use @* for sensitivity lists for combinational logic. Change:

      always @(MemRead) begin
    

    to:

      always @* begin
    

    Your always block is not sensitive to changes in AddrReg.