⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 risc8_control.v

📁 这是一篇关于8位RISC CPU设计的文章
💻 V
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//          (C) COPYRIGHT 2000 S.Aravindhan
//
// This program is free software; you can redistribute it and/or
// modify it  provided this header is preserved on all copies. 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//
// Author   : S.Aravindhan
// File     : risc8_control.v
// Abstract : Control Unit and Instruction Decoder.
//            Please use 160 column window to view this file 
//          
// History:
// ============================================================================
// 02/06/2000  arvind   1.0      Initial Release
// ============================================================================

module risc8_control (/*AUTOARG*/
  // Outputs
  alu_cmd, carry_src, a_addr, b_addr, w_addr, wr_reg, a_src, b_src, 
  muldiv_op, flag_op, data_op, addr_op, invert_b, lu_op, inc_pc, 
  opcode_op, int_type, 
  // Inputs
  clk, rst_n, nmi, int, queue_out, psw, data_ready, queue_count, 
  divide_by_0
  ); 

  output [3:0]  alu_cmd;       // alu command
  output [2:0]  carry_src;     // carry source
  output [3:0]  a_addr;        // a-bus read reg. address
  output [3:0]  b_addr;        // b-bus read reg. address
  output [3:0]  w_addr;        // write-back reg. address
  output        wr_reg;        // write register
  output [1:0]  a_src;         // alu a-bus source
  output [1:0]  b_src;         // alu b-bus source
  output [5:0]  muldiv_op;     // mulitier/divider operation
  output [2:0]  flag_op;       // flag operation
  output [2:0]  data_op;       // data cycle operation     
  output [3:0]  addr_op;       // address register operation
  output        invert_b;      // invert b-bus 
  output        lu_op;         // Logic Unit Operation
  output [1:0]  inc_pc;        // increment pc
  output [4:0]  opcode_op;     // opcode fetch operations
  output [1:0]  int_type;      // interrupt type
 
  input         clk;           // clock
  input         rst_n;         // reset
  input         nmi;           // non-maskable interrupt
  input         int;           // maskable interrupt
  input  [7:0]  queue_out;     // instruction queue fifo output
  input  [7:0]  psw;           // psw
  input         data_ready;    // data ready
  input  [2:0]  queue_count;   // instruction queue count
  input         divide_by_0;   // divide by zero

  reg    [3:0]  state;
  reg    [3:0]  alu_cmd;
  reg    [2:0]  carry_src;
  reg           invert_b; 
  reg    [3:0]  a_addr;
  reg    [3:0]  b_addr;
  reg    [3:0]  w_addr;
  reg           wr_reg;
  reg    [1:0]  a_src;
  reg    [1:0]  b_src;
  reg    [7:0]  opcode_tmp;
  reg    [1:0]  inc_pc;
  reg    [4:0]  opcode_op_d;
  reg           lu_op;
  reg    [2:0]  flag_op;
  reg    [5:0]  muldiv_op;
  reg    [2:0]  data_op;
  reg    [3:0]  addr_op;

  reg           condition;
  reg    [51:0] decode;

  reg           nmi_reg;
  reg           int_reg;
  reg           div_reg;
  reg           int_processing;
  reg           next_int_processing;
  reg    [1:0]  int_type;
  reg    [1:0]  next_int_type;

  wire   [3:0]  operan;
  wire   [3:0]  operan1;
  wire   [3:0]  operan2;
  wire          opcode_valid;
  wire          sel_opcode_tmp;
  wire          clear_opcode;
  wire          load_opcode_tmp;
  wire   [7:0]  opcode;

  wire          queue_count_gt0;
  wire          queue_count_gt1;
  wire          lda_sta_opcode;
  wire          int_pending;
 
  assign opcode_op       = decode[11:7];
  assign sel_opcode_tmp  = opcode_op_d[2];
  assign clear_opcode    = opcode_op_d[3];
  assign load_opcode_tmp = opcode_op[1];
  assign operan          = {1'b0, opcode[2:0]};
  assign operan1         = {1'b0, opcode[1:0], 1'b0};
  assign operan2         = {1'b0, opcode[1:0], 1'b1};
  assign int_pending     = ((state == `ST0) &  (nmi_reg | 
                            (int_reg & psw[4]) | div_reg));
  assign lda_sta_opcode  = (opcode[7:4] == 4'b1111); // load/store only
  assign queue_count_gt0 = ~(queue_count == 3'b000);
  assign queue_count_gt1 = (queue_count > 3'b001);
  assign opcode_valid    = sel_opcode_tmp | 
                           (~lda_sta_opcode & queue_count_gt0 & ~clear_opcode) |
                           (lda_sta_opcode & queue_count_gt1 & ~clear_opcode);
  assign opcode          = (sel_opcode_tmp)? opcode_tmp : queue_out;

  // store the interrupt/nmi/divide_by_zero till they are serviced
  always @ (posedge clk or negedge rst_n)
    begin
      if(!rst_n)
        begin
          nmi_reg <= 1'b0;
          int_reg <= 1'b0;
          div_reg <= 1'b0;
        end
      else
        begin
          if(int_type == 2'b01)
            nmi_reg <= 1'b0;
          else if(nmi_reg)
            nmi_reg <= 1'b1;
          else
            nmi_reg <= nmi;
 
          if(int_type == 2'b10)
            div_reg <= 1'b0;
          else if(div_reg)
            div_reg <= 1'b1;
          else
            div_reg <= divide_by_0;
 
          if(int_type == 2'b11)
            int_reg <= 1'b0;
          else if(int_reg)
            int_reg <= 1'b1;
          else
            int_reg <= (int); // psw[4] = ie
        end
    end

  // moving controls from DECODE stage to EXECUTE stage.
  always @ (posedge clk or negedge rst_n)
    begin
      if(!rst_n)
        begin 
          int_processing <= 0;
          int_type       <= 2'b00; 
          opcode_tmp     <= 8'h00;
          lu_op          <= 1'b1;
          {state, alu_cmd, carry_src, invert_b, a_addr, b_addr, 
           w_addr, wr_reg, a_src, b_src, flag_op, muldiv_op, inc_pc, 
           opcode_op_d, data_op, addr_op} <= 0;
        end
      else
        begin
          if(load_opcode_tmp)
            opcode_tmp  <= queue_out;
            lu_op       <= ~(decode[47:44] == `ALUadd);

          if(data_ready) 
            begin
              int_processing <= next_int_processing;
              int_type       <= next_int_type; 
              {state, alu_cmd, carry_src, invert_b, a_addr, b_addr, 
               w_addr, wr_reg, a_src, b_src, flag_op, muldiv_op, inc_pc, 
               opcode_op_d, data_op, addr_op} <= decode;
            end
        end
    end

  // branch condition check; Flags Mapping: {V, N, C, Z} = psw[3:0]
  always @ (opcode or psw)
    begin
      case(opcode[2:0])
        3'b000: condition = (psw[0]);                       // EQ       
        3'b001: condition = (~psw[0]);                      // NE       
        3'b010: condition = (~(psw[3] ^ psw[2]) & ~psw[0]); // GT      
        3'b011: condition = (psw[3] ^ psw[2]);              // LT     
        3'b100: condition = (psw[1]);                       // CS    
        3'b101: condition = (psw[2]);                       // CC 
        3'b110: condition = (psw[3]);                       // NS      
        3'b111: condition = 1'b1;                           // AL      
        endcase
    end
 
  // INSTRUCTION DECODE: One BIG case statement!!
  // outputs
  // state, alu_cmd, carry_src, invert_b, a_addr, b_addr, w_addr, wr_reg,   
  // a_src, b_src, flag_op, muldiv_op, inc_pc, opcode_op, data_op, addr_opp
  

  always @ (opcode or state or opcode_valid or operan or operan1 or operan2 or
            a_addr or b_addr or w_addr or alu_cmd or invert_b or a_src or b_src
            or queue_count_gt0 or queue_count_gt1 or condition or carry_src or
            divide_by_0 or int_pending or int_processing or nmi_reg or div_reg 
            or int_type) 
    begin
    decode = {`ST0, `ALUpre, `CRYc, `PIb, `ADRpva, `ADRpvb, `ADRpvw, `Nrg, `ASRCp, `BSRCp, `FLnul, `MDnul, `PC0, `OPC00000, `DAOPno, `ADOPnul };
    next_int_type = 2'b00; next_int_processing = 0;
    if(int_pending | int_processing) 
     begin
     next_int_processing = 1;
     case(state[2:0])  
     3'b000: decode = {`ST1, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRr0,  `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC11000, `DAOPwr, `ADOPrsp};
     3'b001: decode = {`ST2, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpsw, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
     3'b010: decode = {`ST3, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpcl, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
     3'b011: decode = {`ST4, `ALUpre, `CRYp, `NIb, `ADRspl, `ADRpch, `ADRspl, `Nrg, `ASRC0, `BSRCp, `FLnul, `MDnul, `PC0, `OPC10000, `DAOPwr, `ADOPinc};
     3'b100: begin
     if(nmi_reg) 
      begin
      next_int_type = 2'b01;
      decode = {`ST5, `ALUtha, `CRYp, `NIb, `ADRspl, `ADRpch, `ADRpcl, `Nrg, `ASRC1, `BSRCp, `FLclie, `MDnul, `PC0, `OPC10100, `DAOPno, `ADOPint};
      end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -