Reptile FSM
Reptile Hardware
Reptile memory connection
Reptile FSM with Control Signals
Reptile Control Unit
We must have as many lines as the number of “balls” plus one line for JZ.
Each line contains as many bits as control signals plus one bit for Fetch.
The complete circuit for the control unit of Reptile is shown below. As can be seen, it is almost identical with the control unit of Frog. The only difference is the part drawn in red in the diagram below, which handles the conditional jumps, ie, the JZ instructions.
Microcode
Reptile in Verilog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
module reptile ( input clk, input [15:0] data_in, output reg [15:0] data_out, output reg [11:0] address, output wire memwt ); reg [11:0] pc, ir; //program counter, instruction register reg [3:0] state; //FSM reg [15:0] regbank [3:0];//registers reg zeroflag; //zero flag register reg [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; wire zeroresult; //zeroflag value always @(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[1:0] ] <= data_in; //if inst is LDI get the destination register number from ir and move the data in it. pc<=pc+1; //for next instruction (32 bit instruction) state <= FETCH; end LD: begin regbank[ ir[1:0] ] <= data_in; state <= FETCH; end ST: begin data_out <= regbank[ ir[7:6] ]; state <= FETCH; end JMP: begin pc <= pc+ir; state <= FETCH; end ALU: begin regbank[ir[2:0]]<=result; zeroflag<=zeroresult; state <= FETCH; end endcase always @* case (state) LD: address=regbank[ir[4:3]][11:0]; ST: address=regbank[ir[4:3]][11:0]; default: address=pc; endcase assign memwt=(state==ST); //ALU always @* case (ir[11:8]) 4'h0: result = regbank[ir[7:6]]+regbank[ir[4:3]]; //000 4'h1: result = regbank[ir[7:6]]-regbank[ir[4:3]]; //001 4'h2: result = regbank[ir[7:6]]®bank[ir[4:3]]; //010 4'h3: result = regbank[ir[7:6]]|regbank[ir[4:3]]; //011 4'h4: result = regbank[ir[7:6]]^regbank[ir[4:3]]; //100 3'h5: result = !regbank[ir[4:3]]; 3'h6: result = regbank[ir[4:3]]; 3'h7: result = regbank[ir[4:3]]+1'h1; 3'h8: result = regbank[ir[4:3]]-1'h1; default: result=16'h0000; endcase assign zeroresult = ~|result; initial begin; state=FETCH; end endmodule |
Problems
- Add an overflow flag into hardware. How you should change the instruction set to take advantage of this new flag?
- Add address offset to load and store instructions.
- Create conditional jump instructions for many different conditions, ie, not only JZ but JNZ, JEQ, JGT etc.
- Increase memory size to 64K while keeping the data size 16 bits. Which instructions will change?
- Add a monitor which shows the address and PC at each instruction.