blob: 6a190e1bdea426c47fabc817991851d07df59baf [file] [log] [blame]
module Controller (
input clk
, input rst
, input intr_i
, output reg inta
, input nmir
, output reg nmia
, input trap
, output reg trapa
, input [15:0] ir
, input status
, input done
, output reg ldIr
, output reg ldSp
, output reg incSp
, output reg decSp
, output reg ldPc
, output reg incPc
, output reg rd16
, output reg rd8
, output reg [ 1:0] wr
, output reg [ 2:0] addrSel
, output reg [ 2:0] dataSel
, output reg [ 2:0] trapSel
, output reg [ 2:0] ra
, output reg [ 2:0] rb
, output reg [ 2:0] rd
, output reg [ 2:0] wd
, output reg [ 3:0] aluop
, output reg [ 3:0] flagCond
, output reg flagSave
, output reg flagRest
, output reg op8
);
reg irqA = 0;
wire intr = intr_i & irqA;
reg dbg_invalidop = 0;
// [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b000? alu 16 bit
// [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b001? alu 8h bit
// [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b010? alu 8l bit
// [15:13] [12:9][8:6][5:3][2:0] MEMORY with top bits == 3'b011? alu slot can diff read/write, 16 or 8 bit
// [15:13] [12:9][8:6][5:3][2:0] JUMP with top bits == 3'b100? alu slot can diff conditions
// [15:13] [12:9][8:6][5:3][2:0] FREE with top bits == 3'b1xx?
wire [2:0] majorOp = ir[15:13];
wire [3:0] minorOp = ir[12: 9];
reg [3:0] pstate, nstate;
always @ (posedge clk or negedge rst)
if( rst == 1'b0 )
pstate = 0;
else
pstate = nstate;
always @*
begin
if( rst == 1'b0 )
irqA = 0;
dbg_invalidop = 1'b0;
inta = 1'b0;
nmia = 1'b0;
trapa = 1'b0;
trapSel = 3'b000;
ldIr = 1'b0;
ldSp = 1'b0;
incSp = 1'b0;
decSp = 1'b0;
ldPc = 1'b0;
incPc = 1'b0;
op8 = 1'b0;
rd16 = 1'b0;
rd8 = 1'b0;
wr = 2'b00;
addrSel = 3'b000;
dataSel = 3'b000;
ra = 3'b000;
rb = 3'b000;
rd = 3'b000;
wd = 3'b000;
aluop = 4'b0000;
flagCond = 1'b0;
flagSave = 1'b0;
flagRest = 1'b0;
case(pstate)
4'b0000 : begin
addrSel = 3'b000;
rd16 = 1'b1;
ldIr = 1'b1;
incPc = done;
if( done == 1'b1 )
nstate = 4'b0001;
else
nstate = 4'b0000;
end
4'b0001 : begin
nstate = 4'b1111;
case(majorOp)
3'b000 : begin //Alu 16 bit
flagSave = 1'b1;
dataSel = 3'b001;
aluop = minorOp;
ra = ir[ 8:6];
rb = ir[ 5:3];
rd = ir[ 2:0];
wd = 3'b011;
nstate = 4'b1111;
end
3'b001 : begin //Alu 8 bit high
flagSave = 1'b1;
dataSel = 3'b001;
aluop = minorOp;
ra = ir[ 8:6];
rb = ir[ 5:3];
rd = ir[ 2:0];
wd = 3'b010;
nstate = 4'b1111;
end
3'b010 : begin //Alu 8 bit low
flagSave = 1'b1;
dataSel = 3'b001;
aluop = minorOp;
ra = ir[ 8:6];
rb = ir[ 5:3];
rd = ir[ 2:0];
wd = 3'b001;
op8 = 1'b1;
nstate = 4'b1111;
end
3'b011 : begin //Memory operations
nstate = 4'b1111;
case(minorOp)
4'b0000 : begin //16 bit read
rd16 = 1'b1;
ra = ir[8:6];
rb = ir[5:3];
rd = ir[2:0];
wd = 3'b011;
dataSel = 3'b000;
addrSel = ir[5:3];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0001 : begin //16 bit write
wr = 2'b11;
rb = ir[5:3];
ra = ir[2:0];
dataSel = 3'b011;
addrSel = ir[8:6];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0010 : begin //8 bit read low
rd8 = 1'b1;
ra = ir[8:6];
rb = ir[5:3];
rd = ir[2:0];
wd = 3'b001;
dataSel = 3'b000;
addrSel = ir[5:3];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0011 : begin //8 bit write low
wr = 2'b01;
rb = ir[5:3];
ra = ir[2:0];
dataSel = 3'b011;
addrSel = ir[8:6];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0100 : begin //8 bit read high
rd8 = 1'b1;
ra = ir[8:6];
rb = ir[5:3];
rd = ir[2:0];
wd = 3'b110;
dataSel = 3'b000;
addrSel = ir[5:3];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0101 : begin //8 bit write high
wr = 2'b10;
rb = ir[5:3];
ra = ir[2:0];
dataSel = 3'b011;
addrSel = ir[8:6];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0110 : begin //8 Bit read and save sign extend
rd8 = 1'b1;
ra = ir[8:6];
rb = ir[5:3];
rd = ir[2:0];
wd = 3'b011;
dataSel = 3'b101;
addrSel = ir[5:3];
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
4'b0111 : begin //Load 8 bit sign extended immediate into register
rd = {2'b00, ir[8]};
wd = 3'b011;
dataSel = 3'b111;
nstate = 4'b1111;
end
4'b1000 : begin //8 Bit immediate load
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1001 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1010 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1011 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1100 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1101 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1110 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
4'b1111 : begin
rd = ir[10:8];
wd = {1'b0, ir[11], ~ir[11]};
dataSel = 3'b110;
nstate = 4'b1111;
end
endcase
end
3'b100 : begin //Jump and Call
flagCond = minorOp;
if( ir[8] ) //Call instruction
begin
if( status )
begin
//Save PC
wr = 2'b11;
if( ~(minorOp == 4'b1111) )
trapSel = 3'b111;
else
trapSel = 3'b000;
dataSel = 3'b010;
addrSel = 3'b101;
decSp = done;
if( done )
nstate = 4'b1000;
else
nstate = 4'b0001;
end
else
nstate = 4'b1111;
end
else //Jump instruction
begin
if( status & ~(minorOp == 4'b1111))
begin
rd16 = 1'b1;
dataSel = 3'b000;
addrSel = 3'b000;
ldPc = done;
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
else if( status & (minorOp == 4'b1111))
begin
ra = ir[7:5];
dataSel = 3'b011;
ldPc = 1'b1;
nstate = 4'b1111;
end
else
begin
incPc = 1'b1;
nstate = 4'b1111;
end
end
end
3'b101 : begin //Call
nstate = 4'b1111;
end
3'b110 : begin //Free
nstate = 4'b1111;
end
3'b111 : begin //Special Operations
nstate = 4'b1111;
case(minorOp)
4'b0000 : begin //Load SP
if( ir[8] == 1'b1 )
begin
ldSp = 1'b1;
dataSel = 3'b111;
nstate = 4'b1111;
end
else
begin
rd16 = 1'b1;
dataSel = 3'b000;
addrSel = 3'b000;
ldSp = 1'b1;
incPc = done;
if( done )
nstate = 4'b1111;
else
nstate = 4'b0001;
end
end
4'b0001 : begin //Set Flag
if( ir[8] == 1'b1 )
irqA = 1'b1;
else
irqA = 1'b0;
nstate = 4'b1111;
end
4'b1110 : begin //return from interrupt
flagCond = ir[7:4];
if( status )
begin
incSp = 1'b1;
nstate = 4'b1010; //Load Flags from stack then PC
end
else
begin
nstate = 4'b1111;
end
end
4'b1111 : begin //return
flagCond = ir[7:4];
if( status )
begin
incSp = 1'b1;
nstate = 4'b1001; //Load PC from stack
end
else
begin
nstate = 4'b1111;
end
end
default : nstate = 4'b1111;
endcase
end
endcase
end
4'b0010 : begin // jump operation
nstate = 4'b1111;
end
4'b0011 : begin
nstate = 4'b1111;
end
4'b0100 : begin
nstate = 4'b1111;
end
4'b0101 : begin
nstate = 4'b1111;
end
4'b0110 : begin
nstate = 4'b1111;
end
4'b1000 : begin // Finish Call by loading PC from selected destination
if( ~(minorOp == 4'b1111))
begin
rd16 = 1'b1;
dataSel = 3'b000;
addrSel = 3'b000;
ldPc = done;
if( done )
nstate = 4'b1111;
else
nstate = 4'b1000;
end
else if(minorOp == 4'b1111)
begin
ra = ir[7:5];
dataSel = 3'b011;
ldPc = 1'b1;
nstate = 4'b1111;
end
else
begin
incPc = 1'b1;
nstate = 4'b1111;
end
end
4'b1001 : begin //Read from stack PC
rd16 = 1'b1;
ldPc = 1'b1;
addrSel = 3'b101;
dataSel = 3'b000;
if( done )
nstate = 4'b1111;
else
nstate = 4'b1001;
end
4'b1010 : begin //Read from stack PC
rd16 = 1'b1;
ldPc = 1'b1;
addrSel = 3'b101;
dataSel = 3'b000;
if( done )
nstate = 4'b1011;
else
nstate = 4'b1010;
end
4'b1011 : begin //Read from stack Flags
rd16 = 1'b1;
flagRest = 1'b1;
addrSel = 3'b101;
dataSel = 3'b000;
incSp = done;
if( done )
nstate = 4'b1111;
else
nstate = 4'b1011;
end
4'b1100 : begin //Interrupts! Save PC
trapSel = 3'b000;
wr = 2'b11;
dataSel = 3'b010;
addrSel = 3'b101;
decSp = done;
if( done )
nstate = 4'b1101;
else
nstate = 4'b1100;
end
4'b1101 : begin //Load PC
dataSel = 3'b010;
addrSel = 3'b101;
if ( trap == 1'b1 )
trapSel = 3'b001;
else if( nmir == 1'b1 )
trapSel = 3'b010;
else if( intr == 1'b1 )
trapSel = 3'b011;
else
trapSel = 3'b000;
nstate = 4'b1110;
end
4'b1110 : begin //Load PC
ldPc = 1'b1;
dataSel = 3'b010;
addrSel = 3'b101;
if ( trap == 1'b1 )
begin
trapSel = 3'b001;
trapa = 1'b1;
end
else if( nmir == 1'b1 )
begin
trapSel = 3'b010;
nmia = 1'b1;
end
else if( intr == 1'b1 )
begin
trapSel = 3'b011;
inta = 1'b1;
end
else
trapSel = 3'b000;
nstate = 4'b0000;
end
4'b1111 : begin //Int ack
if( trap == 1'b1 | nmir == 1'b1 | intr == 1'b1 )
begin
wr = 2'b11;
trapSel = 3'b000;
dataSel = 3'b100;
addrSel = 3'b101;
decSp = done;
if( done )
nstate = 4'b1100;
else
nstate = 4'b1111;
end
else
nstate = 4'b0000;
end
default : nstate = 4'b0000;
endcase
end
endmodule