Advertisement
Guest User

Untitled

a guest
Jul 8th, 2017
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module yfcpu(clk, rst, PC, ra_w, rb_w, rd_w, current_state_w, opcode_w);
  2.  
  3. // our cpu core parameters
  4. parameter im_size = 8;      // 2^n instruction word memory
  5. parameter rf_size = 4;      // 2^n word register file
  6.  
  7. input clk;  // our system clock
  8. output PC;  // our program counter
  9. input rst;  // reset signal
  10.  
  11. output reg [2:0] current_state_w;
  12.  
  13. output reg [ rf_size-1 : 0 ] ra_w;   // left operand register address
  14. output reg [ rf_size-1 : 0 ] rb_w;   // right operand register address
  15. output reg [ rf_size-1 : 0 ] rd_w;   // destination register
  16. output reg [ opcode_size-1 : 0 ] opcode_w;
  17.  
  18. // the cycle states of our cpu, i.e. the Control Unit states
  19. parameter s_fetch   = 3'b000;   // fetch next instruction from memory
  20. parameter s_decode  = 3'b001;   // decode instruction into opcode and operands
  21. parameter s_execute = 3'b010;   // execute the instruction inside the ALU
  22. parameter s_store   = 3'b011;   // store the result back to memory
  23. parameter s_nostore = 3'b100; // dont store any result, skips a cycle
  24.  
  25. // the parts of our instruction word
  26. parameter opcode_size = 4;      // size of opcode in bits
  27.  
  28. // Mnemonic Op Codes
  29. parameter LRI   = 4'b0001;
  30. parameter ADD   = 4'b0100;
  31. parameter SUB   = 4'b0101;
  32. parameter OR    = 4'b0110;
  33. parameter XOR   = 4'b0111;
  34. parameter HALT  = 4'b0000;
  35.  
  36. // our new branch mnemonics!
  37. parameter BRA    = 4'b1000;   // branch to address in memory location RB
  38. parameter BRANZ  = 4'b1001;   // branch to address in memory location RB, if RA is zero
  39. parameter BRAL   = 4'b1010;   // branch to literal address RB
  40. parameter BRALNZ = 4'b1011;   // branch to literal address RB, if RA is zero
  41. parameter CALL   = 4'b1100;   // call subroutine; store current PC into RD and jump to address in literal location RB
  42.  
  43.  
  44. // our memory core consisting of Instruction Memory, Register File and an ALU working (W) register
  45. reg [ opcode_size + (rf_size*3) -1 : 0 ] IMEM[0: 2 ** im_size -1 ] ;    // instruction memory
  46. reg [ 7:0 ] REGFILE[0: 2 ** rf_size -1 ];   // data memory
  47. reg [ 7:0 ] W;  // working (intermediate) register
  48.  
  49. // our cpu core registers
  50. reg [ im_size-1 : 0 ] PC;           // program counter
  51. reg [ opcode_size + (rf_size*3) -1 : 0 ] IR;    // instruction register
  52.  
  53. /* Control Unit registers
  54.      The control unit sequencer cycles through fetching the next instruction
  55.      from memory, decoding the instruction into the opcode and operands and
  56.      executing the opcode in the ALU.
  57. */
  58. reg [ 2:0 ] current_state;
  59. reg [ 2:0 ] next_state;
  60. // our instruction registers
  61. // an opcode typically loads registers addressed from RA and RB, and stores
  62. // the result into destination register RD. RA:RB can also be used to form
  63. // an 8bit immediate (literal) value.
  64. reg [ opcode_size-1 : 0 ] OPCODE;
  65. reg [ rf_size-1 : 0 ] RA;   // left operand register address
  66. reg [ rf_size-1 : 0 ] RB;   // right operand register address
  67. reg [ rf_size-1 : 0 ] RD;   // destination register
  68.  
  69.  
  70.  
  71. always @ (*) begin
  72.   ra_w <= RA;
  73.   rb_w <= RB;
  74.   rd_w <= RD;
  75.   opcode_w <= OPCODE;
  76.   current_state_w <= current_state;
  77. end
  78.  
  79. // the initial cpu state bootstrap
  80. initial begin
  81.     PC = 0;
  82.     current_state = s_fetch;
  83.  
  84.     // Our sample computes 11 + 10*3...the long way, via 10 additions of 3!
  85.     //    IMEM[n] = { OPCODE, RA, RB, RD };
  86.     IMEM[0]  = { LRI    ,  8'd10, 4'd0 };          // load 10 into R0, our loop counter
  87.     IMEM[1]  = { LRI    ,  8'd1 , 4'd1 };          // load 1 into R1, our loop decrement value
  88.     IMEM[2]  = { LRI    ,  8'd11, 4'd2 };          // load 11 into R2
  89.     IMEM[3]  = { LRI    ,  8'd3 , 4'd3 };          // load 3 into R3
  90.     IMEM[4]  = { ADD    ,  4'd2 , 4'd3 , 4'd2 };   // add R2 + R3, into R2
  91.     IMEM[5]  = { SUB    ,  4'd0 , 4'd1 , 4'd0 };   // decrement the loop counter R0
  92.     IMEM[6]  = { BRALNZ ,  4'd0 , 4'd4 , 4'd0 };   // jump to address 4, if R0 is zero
  93.     IMEM[7]  = { CALL   ,  4'd0 , 4'd11, 4'd15 };  // call subroutine, store PC into R15
  94.     IMEM[8]  = { LRI    ,  8'd4, 4'd12 };          // load 10 into R0, our loop counter
  95.     IMEM[9]  = { ADD    ,  4'd12 , 4'd2 , 4'd2 };  // add R2 + R3, into R2
  96.     IMEM[10] = { HALT   , 12'd0 };                 // end program
  97.  
  98.     // subroutine that subtracts 11 from R2
  99.     IMEM[11] = { LRI    ,  8'd11, 4'd3 };          // load 10 into R0, our loop counter
  100.     IMEM[12] = { SUB    ,  4'd2 , 4'd3 , 4'd2 };   // decrement the loop counter R0
  101.    IMEM[13] = { BRA    ,  4'd0 , 4'd15, 4'd0 };   // return, branch to location from R15
  102.     end
  103.  
  104. // at each clock cycle we sequence the Control Unit, or if rst is
  105. // asserted we keep the cpu in reset.
  106. always @ (posedge clk or posedge rst)
  107. begin
  108.     if(rst) begin
  109.         current_state = s_fetch;
  110.         PC = 0;
  111.         end
  112.     else
  113.        begin
  114.        // sequence our Control Unit
  115.         case( current_state )
  116.             s_fetch: begin
  117.                 // fetch instruction from instruction memory
  118.                 IR = IMEM[ PC ];
  119.                 next_state = s_decode;
  120.                 end
  121.  
  122.             s_decode: begin
  123.                // PC can be incremented as current instruction is loaded into IR
  124.                 PC = PC + 1;
  125.                 next_state = s_execute;
  126.                
  127.                 // decode the opcode and register operands
  128.                 OPCODE = IR[ opcode_size + (rf_size*3) -1 : (rf_size*3) ];
  129.                 RA = IR[ (rf_size*3) -1 : (rf_size*2) ];
  130.                 RB = IR[ (rf_size*2) -1 : (rf_size  ) ];
  131.                 RD = IR[ (rf_size  ) -1 : 0 ];
  132.                 end
  133.  
  134.             s_execute: begin
  135.                // Execute ALU instruction, process the OPCODE
  136.                 case (OPCODE)
  137.                     LRI: begin 
  138.                        // load register RD with immediate from RA:RB operands
  139.                        W = {RA, RB};
  140.                        next_state = s_store;
  141.                        end
  142.                        
  143.                     ADD: begin 
  144.                        // Add RA + RB
  145.                         W = REGFILE[RA] + REGFILE[RB];
  146.                         next_state = s_store;
  147.                         end
  148.                        
  149.                     SUB: begin 
  150.                        // Sub RA - RB
  151.                         W = REGFILE[RA] - REGFILE[RB];
  152.                         next_state = s_store;
  153.                         end
  154.  
  155.                     OR: begin  
  156.                        // OR RA + RB
  157.                         W = REGFILE[RA] | REGFILE[RB];
  158.                         next_state = s_store;
  159.                         end
  160.                        
  161.                     XOR: begin 
  162.                        // Exclusive OR RA ^ RB
  163.                         W = REGFILE[RA] ^ REGFILE[RB];
  164.                         next_state = s_store;
  165.                         end
  166.                        
  167.                     HALT: begin
  168.                        // Halt execution, loop indefinately
  169.                         next_state = s_execute;
  170.                         end
  171.                        
  172.                     BRA: begin
  173.                        // branch to REGFILE[RB]
  174.                         PC = REGFILE[RB];
  175.                         next_state = s_nostore;
  176.                         end
  177.  
  178.                     BRAL: begin
  179.                        // branch to RB
  180.                         PC = RB;
  181.                         next_state = s_nostore;
  182.                         end
  183.                        
  184.                     BRANZ: begin
  185.                        // branch to REGFILE[RB] if REGFILE[RA] is zero
  186.                         if(REGFILE[RA] !=8'd0)
  187.                            PC = REGFILE[RB];
  188.                         next_state = s_nostore;
  189.                         end
  190.  
  191.                     BRALNZ: begin
  192.                        // branch to RB if REGFILE[RA] is zero
  193.                         if(REGFILE[RA] !=8'd0)
  194.                            PC = RB;
  195.                         next_state = s_nostore;
  196.                         end
  197.                        
  198.                     CALL: begin
  199.                        // call a subroutine; store PC into RD and jump to location in REGFILE[RB]
  200.                         W = PC;
  201.                         PC = RB;
  202.                         next_state = s_store; // note state s_store! because we store PC into REGFILE[RD]
  203.                         end
  204.                        
  205.                     // catch all
  206.                     default: begin end
  207.                 endcase
  208.                 end
  209.            
  210.             s_store: begin
  211.                // store the ALU working register into the destination register RD
  212.                 REGFILE[RD] = W;
  213.                 next_state = s_fetch;
  214.                 end
  215.  
  216.             s_nostore: begin
  217.                // not a store instruction, skip this cycle
  218.                // this is typically referred to as a "wait state".
  219.                 next_state = s_fetch;
  220.                 end
  221.            
  222.             // invalid state!
  223.             default: begin end
  224.         endcase
  225.  
  226.     // move the control unit to the next state
  227.     current_state = next_state;
  228.     end
  229. end
  230.  
  231. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement