module steuerwerk ( // Eingaben opc,alu_flags,mode, // Ausgaben sel_pc,inc_pc,load_pc,sel_mem_addr, mem_wr,mem_cs,mem_sflag, ld_ir,ld_mdr, set_sel_a,sel_reg_a_src,new_sel_a, sel_op_a, sel_op_b,alu_go, ld_reg,clock, ); `include ".\\timing.v" `include ".\\defs.v" input [5:0] opc; input [3:0] alu_flags, mode; output inc_pc, load_pc, ld_mdr, ld_ir, ld_reg; output mem_cs, mem_wr, mem_sflag; output sel_reg_a_src, sel_op_a, sel_op_b, sel_pc, alu_go; output clock, set_sel_a; output [1:0] sel_mem_addr; output [2:0] new_sel_a; reg inc_pc, load_pc, ld_mdr, ld_ir, ld_reg, alu_go; reg mem_cs, mem_wr, mem_sflag, first_wait; reg sel_reg_a_src, sel_op_a, sel_op_b, sel_pc; reg clock, set_sel_a; reg [1:0] sel_mem_addr; reg [2:0] new_sel_a; reg [5:0] state, next_state; opw opw ( .inc_pc(inc_pc), .load_pc(load_pc), .ld_mdr(ld_mdr), .ld_ir(ld_ir), .ld_reg(ld_reg), .mem_cs(mem_cs), .mem_wr(mem_wr), .mem_sflag(mem_sflag), .set_sel_a(set_sel_a), .sel_reg_a_src(sel_reg_a_src), .sel_op_a(sel_op_a), .sel_op_b(sel_op_b), .sel_mem_addr(sel_mem_addr), .sel_pc(sel_pc), .alu_go(alu_go), .clock(clock), .new_sel_a(new_sel_a), .opc(opc), .alu_flags(alu_flags), .mode(mode) ); reg finished; initial begin finished = 0;clock = 0;inc_pc=0;ld_mdr = 0;ld_ir = 0;ld_reg = 0;mem_cs = 0;mem_wr = 0;mem_sflag= 0;sel_reg_a_src = 0;sel_op_a = 0; sel_op_b =0;sel_pc=0;clock=0; set_sel_a=0;sel_mem_addr=0;new_sel_a=0;state=62; end always begin while (finished == 0) begin #TCLOCK; clock = !clock; if (clock==1) $display("%t Posedge of CLOCK, ld_mdr :%bb, mem_cs: %bb, sel_reg_a_src: %bb,ld_reg: %bb",$time, ld_mdr, mem_cs, sel_reg_a_src,ld_reg); end $finish; end always begin $monitor("LOAD: %d", load_pc); #350000 $finish; end always @(state) begin case (state) S0: // Startzustand begin $display("%t ****************************************************************** STATE: S0",$time); {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 3'b000, 1'b0, 1'b0, 1'b0, 1'b0}; next_state = S1; end S1: // Fetch-Zustand begin $display("%t ****************************************************************** STATE: S1 Fetching Instruction",$time); {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b1, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 3'b000, 1'b0, 1'b0, 1'b0, 1'b0}; next_state = S2; end S2: //decode begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b1, 1'b0, 1'b0, 2'b10, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S2 Decoding OPC (mode: %h): %d",$time, mode, opc); #TDECO case(opc) nop : next_state = S4; stop : next_state = S3; bra : next_state = S7; beq : next_state = S7; bgt : next_state = S7; blt : next_state = S7; boo : next_state = S7; boc : next_state = S7; load : next_state = S9; store : next_state = S11; nicht : next_state = S5; und : next_state = S5; oder : next_state = S5; add : next_state = S5; sub : next_state = S5; comp : next_state = S5; multh : next_state = S5; multl : next_state = S5; div : next_state = S5; mod : next_state = S5; neg : next_state = S5; jsr : next_state = S13; ret : next_state = S17; default : begin $display("%t %m Ungültiger Opcode:", $time, opc); next_state = S3; end endcase if (opc == stop) mem_sflag = 1; if (((mode == MRLIT) || (mode == MA) || (mode == MRA)) && (opc != jsr)) begin inc_pc =1; mem_cs=1; ld_mdr = 1; // Konstante ins MDR laden $display("%t MODE MRLIT/MA detected (Preparing sram, inc_pc =1...)", $time); next_state = S7; end if ((mode == MRRI) && (opc == load)) begin $display("%t LOAD with MRRI detected (Preparing sram, ...)", $time); mem_cs=1; ld_mdr = 1; sel_mem_addr = 2'b01; // Register B an Speicher anlegen next_state = S10; end if ((mode == MRRI) && (opc == store)) begin $display("%t STORE with MRRI detected (Preparing sram, ...)", $time); mem_cs=1; ld_mdr = 0; mem_wr = 1; sel_mem_addr = 2'b01; // Register B an Speicher anlegen next_state = S12; end if ((mode == MRR) && (opc == load)) begin $display("%t LOAD with MRR detected, working like arithmetic command", $time); next_state = S5; end if (opc == jsr) begin $display("%t JSR detected, selecting R7 as reg A", $time); set_sel_a = 1; new_sel_a = 3'b111; // Register R7 (Stackpointer auswählen) end end S3: //************************************* S3 *********************************** Ende: Kiste anhalten begin $display("%t ****************************************************************** STATE: S3 Finishing",$time); $finish; end S4: //Nächsten Zustand vorbereiten begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b1, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 3'b000, 1'b0, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S4 Preparing next command",$time); next_state = S1; end S5: //************************************* S5 *********************************** Befehle die die ALU benutzen begin case (mode) MRR: begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 3'b000, 1'b1, 1'b1, 1'b0, 1'b1}; $display("%t ****************************************************************** STATE: S5 Preparing Arithmetic/Logic Command (mode: MRR)",$time); end MRLIT: begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 3'b000, 1'b1, 1'b0, 1'b0, 1'b1}; $display("%t ****************************************************************** STATE: S5 Preparing Arithmetic/Logic Command (mode: MRLIT)",$time); end default : begin $display("%t %m Ungültiger Mode: %h", $time, mode); next_state = S3; end endcase next_state = S6; end S6: //************************************* S6 ****************************** Ergebnis nach A zurückschreiben begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b1, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 3'b000, 1'b0, 1'b0, 1'b1, 1'b0}; next_state = S1; $display("%t ****************************************************************** STATE: S6 writing result to reg a",$time); if ((mode == MRRI) || (mode == MRA) ) sel_reg_a_src = 1; // Von MDR uebernehmen end S7: //************************************* S7 *********************************** Warten auf Speicher begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S7 Waiting for sram",$time); case (opc) bra : next_state = S8; jsr : next_state = S8; beq : if (alu_flags[0] == 1) next_state = S8; else next_state = S4; bgt : if (alu_flags[1] == 0) next_state = S8; else next_state = S4; blt : if (alu_flags[1] == 1) next_state = S8; else next_state = S4; boo : if ((alu_flags[3] == 1)) next_state = S8; else next_state = S4; boc : if ((alu_flags[2] == 1)) next_state = S8; else next_state = S4; load : next_state = S9; default: next_state = S5; endcase if ((opc == load) && (mode == MRRI)) next_state = S6; // MDR ins Register A schreiben end S8: //************************************* S8 *********************************** Branch begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b1, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S8 Branch: Setting PC",$time); next_state = S1; end S9: //************************************* S9 *********************************** LOAD begin case (mode) MRLIT: begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 3'b000, 1'b1, 1'b0, 1'b1, 1'b0}; $display("%t ****************************************************************** STATE: S9 LOAD Mode MRLIT",$time); next_state = S4; end MRA: begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b11, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S9 LOAD Mode MRA",$time); next_state = S6; end MRR: begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 3'b000, 1'b1, 1'b0, 1'b1, 1'b0}; $display("%t ****************************************************************** STATE: S9 LOAD Mode MA",$time); next_state = S4; end endcase end S10: //************************************* S10 *********************************** Reg B an Bus legen begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b01, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b0, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S10 Waiting for sram (Reg B on abus)",$time); next_state = S6; // MDR ins Reg A schreiben end S11: //************************************* S11 *********************************** STORE begin // Zustand wird zur Zeit nicht mehr benutzt!!!!!!!! {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b01, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S11 STORE Mode MRRI",$time); next_state = S12; end S12: //************************************* S12 *********************************** STORE_2 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b1, 1'b0, 2'b01, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b1, 3'b000, 1'b1, 1'b0, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S12 Finishing STORE Mode MRRI",$time); next_state = S1; end S13: //************************************* S13 *********************************** JSR begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b1}; $display("%t ****************************************************************** STATE: S13 JSR:: Incrementing stackpointer (R7)",$time); next_state = S14; end S14: //************************************* S14 *********************************** JSR_2 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b1, 1'b0}; $display("%t ****************************************************************** STATE: S14 JSR: saving stackpointer to R7",$time); next_state = S15; end S15: //************************************* S15 *********************************** JSR_3 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b1, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S15 JSR: Saving PC to Stack",$time); next_state = S16; end S16: //************************************* S16 *********************************** JSR_4 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b10, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S16 JSR: Waiting for mem to finish",$time); next_state = S8; // Ab hier weitermachen wie normaler Branch end S17: //************************************* S17 *********************************** ret begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b1, 1'b1}; $display("%t ****************************************************************** STATE: S17 ret:Reducing R7",$time); next_state = S18; end S18: //************************************* S18 *********************************** ret_2 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b0, 1'b1, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S18 ret: Putting R7 on abus",$time); next_state = S19; end S19: //************************************* S19 *********************************** ret_3 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b0, 2'b00, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S19 ret: Loading old PC to MDR",$time); next_state = S20; end S20: //************************************* S20 *********************************** ret_4 begin {sel_pc, inc_pc, load_pc, sel_mem_addr, mem_wr, mem_cs, mem_sflag, ld_ir, ld_mdr, set_sel_a, sel_reg_a_src, new_sel_a, sel_op_a, sel_op_b, ld_reg, alu_go }= {1'b0, 1'b0, 1'b1, 2'b00, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1, 1'b0, 3'b111, 1'b1, 1'b1, 1'b0, 1'b0}; $display("%t ****************************************************************** STATE: S20 ret: Moving PC from MDR to PC",$time); next_state = S4; end endcase end always@(posedge clock) begin if (state==62) state=S0; else #TREG state <= next_state; end endmodule