Bird FSM

Verilog CodeĀ
//bird CPU
module bird (
input clk,
input [15:0] data_in,
output logic [15:0] data_out,
output logic [11:0] address,
output memwt
);
logic [11:0] pc,ir; //program counter, instruction register
logic [4:0] state; //FSM
logic [15:0] regbank [7:0];//registers
logic zeroflag; //zero flag register
logic [15:0] result; //output for result
localparam FETCH=4'b0000,
LDI=4'b0001,
LD=4'b0010,
ST=4'b0011,
JZ=4'b0100,
JMP=4'b0101,
ALU=4'b0111,
PUSH=4'b1000,
POP1=4'b1001,
POP2=4'b1100,
CALL=4'b1010,
RET1=4'b1011,
RET2=4'b1101;
logic zeroresult;
always_ff @(posedge clk)
case(state)
FETCH:
begin
if ( data_in[15:12]==JZ) // if instruction is jz
if (zeroflag) //and if last bit of 7th register is 0 then jump to jump instruction state
state <= JMP;
else
state <= FETCH; //stay here to catch next instruction
else
state <= data_in[15:12]; //read instruction opcode and jump the state of the instruction to be read
ir<=data_in[11:0]; //read instruction details into instruction register
pc<=pc+1; //increment program counter
end
LDI:
begin
regbank[ ir[2:0] ] <= data_in;
pc<=pc+1; //for next instruction (32 bit instruction)
state <= FETCH;
end
LD:
begin
regbank[ir[2:0]] <= data_in;
state <= FETCH;
end
ST:
begin
state <= FETCH;
end
JMP:
begin
pc <= pc+ir;
state <= FETCH;
end
ALU:
begin
regbank[ir[2:0]]<=result;
zeroflag<=zeroresult;
state <= FETCH;
end
PUSH:
begin
regbank[7]<=regbank[7]-1;
state <= FETCH;
end
POP1:
begin
regbank[7]<=regbank[7]+1;
state <= POP2;
end
POP2: //actually unnecessary
begin
regbank[ir[2:0]] <= data_in;
state <= FETCH;
end
CALL:
begin
regbank[7]<=regbank[7]-1;
pc<=pc+ir;
state <= FETCH;
end
RET1:
begin
regbank[7]<=regbank[7]+1;
state <= RET2;
end
RET2:
begin
pc<=data_in[11:0];
state <= FETCH;
end
endcase
always_comb
case (state)
LD: address=regbank[ir[5:3]][11:0];
ST: address=regbank[ir[5:3]][11:0];
PUSH: address=regbank[7][11:0];
POP2: address=regbank[7][11:0];
CALL: address=regbank[7][11:0];
RET2: address=regbank[7][11:0];
default: address=pc;
endcase
assign memwt=(state==ST)||(state==PUSH)||(state==CALL);
always_comb
case (state)
CALL: data_out = {4'b0,pc};
default: data_out = regbank[ir[8:6]];
endcase
always_comb //ALU Operation
case (ir[11:9])
3'h0: result = regbank[ir[8:6]]+regbank[ir[5:3]]; //000
3'h1: result = regbank[ir[8:6]]-regbank[ir[5:3]]; //001
3'h2: result = regbank[ir[8:6]]®bank[ir[5:3]]; //010
3'h3: result = regbank[ir[8:6]]|regbank[ir[5:3]]; //011
3'h4: result = regbank[ir[8:6]]^regbank[ir[5:3]]; //100
3'h7: case (ir[8:6])
3'h0: result = !regbank[ir[5:3]];
3'h1: result = regbank[ir[5:3]];
3'h2: result = regbank[ir[5:3]]+1;
3'h3: result = regbank[ir[5:3]]-1;
default: result=16'h0000;
endcase
default: result=16'h0000;
endcase
assign zeroresult = ~|result;
initial
begin
state=FETCH;
zeroflag=0;
pc=0;
end
endmodule