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
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
.