7.ALU

同じADDでも、BYTE,WORD、LONGで違うところがやや面倒ですが、乗除算を除けば、組み合わせ回路のみで記述できます。

//May.31.2004
//Jun.2.2004 imprement mul_div_out

`include "define.h"
module ALU(clock,sync_reset,alu_left_sel,alu_right_sel,ope,imm_sel,v_clear,h_latch,n_latch,z_latch,v_latch,c_latch,ccr_all_write,access_mode,
          RO_left,RO_right,irword,MOUT,bus_state,ccr_input_sel,z_bus,CCR,BCC_jmp,i_bit,stop_state,state,mul_div_dest_reg,
          mul_div_address3);
        input clock;
        input sync_reset;
        input [1:0] alu_left_sel;
        input [3:0] alu_right_sel;
        input [4:0] ope;
        input imm_sel;
        input v_clear;
        input h_latch,n_latch,z_latch,v_latch,c_latch;
        input ccr_all_write;
        input [1:0] access_mode;
        input [31:0] RO_left,RO_right,MOUT;
        input [63:0] irword;
        input [1:0] bus_state;
        input [1:0] ccr_input_sel;
        output [31:0] z_bus;
        output [7:0] CCR;
        output BCC_jmp;
        output i_bit;
        output stop_state;
        input [7:0] state;
        input [31:0] mul_div_dest_reg;//Jun.3.2004              
        input mul_div_address3;//Jun.3.2004
        wire [31:0] mul_div_dest_reg_out;//Jun.3.2004


        wire [7:0] IR1=irword[23+32:16+32];
        wire [15:0] IR23=irword[15+32:32];
        wire [15:0] IR45=irword[31:16];
        wire [31:0] IR2345=irword[15+32:16];
        wire [31:0] IR4567=irword[31:0];
        wire [31:0] left,right;
        wire [2:0] IR1H_imm=irword[16+32+2+4:16+32+4];
        wire [2:0] IR3H_imm=irword[32+2+4:32+4];
      wire [3:0] IR1H=irword[16+32+3+4:16+32+4];
        wire [3:0] IR0L=irword[63-4:63-8+1];
       reg carry_w ;  //combination
         reg over_flow;//combination
       reg BCC_jmp;//combination

         reg [31:0] z_bus;        // combination
       reg c_bit,z_bit,v_bit,n_bit,i_bit,u_bit6,h_bit,u_bit4;//h flag は未サポート
         wire z_out,v_out,n_out;
        reg [31:0] temp;        
 
         wire  [7:0] ccr_input,CCR;
       wire [2:0] imm;
//mul_div
         wire mul_div_enable,mul_div_sign,mul_div_word,mul_div_mode;
         wire stop_state;
         wire [31:0] mul_div_out;
       wire div_nflag_set,div_nflag;

        assign left=alu_left_sel==`RO_LEFT_SEL ? RO_left :
                           alu_left_sel==`IR1_SEL  ? {24'h00_0000,IR1} :
                           alu_left_sel==`IR23_SEL ? {16'h0000,IR23} : IR2345;

        assign right=alu_right_sel==`RO_RIGHT_SEL ? RO_right :
                             alu_right_sel==`VAL_0_SEL ? 0 :
                             alu_right_sel==`VAL_1_SEL ? 1 :
                             alu_right_sel==`VAL_2_SEL ? 2 :
                             alu_right_sel==`VAL_4_SEL ? 4 :                         
                             alu_right_sel==`VAL_MINUS1_SEL_ALU ? -1 :
                             alu_right_sel==`VAL_MINUS2_SEL_ALU ? -2 :
                             alu_right_sel==`VAL_MINUS4_SEL_ALU ? -4 :
                             alu_right_sel==`MOUT_SEL_ALU ? MOUT : 
                             alu_right_sel==`MUL_DIV_OUT_SEL ? mul_div_out: {24'h00_0000,CCR};//Jun.2.2004

        assign imm=imm_sel==`IR3H_SEL_IMM ? IR3H_imm : IR1H_imm;
        
  //Jun.3.2004
//      assign mul_div_dest_reg_out=access_mode == `LONG_ACCESS ? mul_div_dest_reg : 
//                                  access_mode == `WORD_ACCESS ? (mul_div_address3 ==1'b1 ? {16'h0000,mul_div_dest_reg[31:16]} : {16'h0000,mul_div_dest_reg[15:0]} ) :
//                                  mul_div_address3 ==1'b0 ? {24'h00_0000,mul_div_dest_reg[15:8]} : {24'h00_0000,mul_div_dest_reg[7:0]} ; //Note: register field mapping R0H =>0000, R0L=>1000 
//      always @(negedge clock) temp <=mul_div_dest_reg_out;
        
 mul_div mul_div_unit(.clock(clock),.sync_reset(sync_reset),.a(mul_div_dest_reg),.b(RO_left),
                .mul_div_out(mul_div_out),.mul_div_sign(mul_div_sign),.mul_div_word(mul_div_word),
              .mul_div_mode(mul_div_mode),
                .state(state),.stop_state(stop_state),.mul_div_enable(mul_div_enable));

        assign mul_div_sign=irword[63:44]==20'h01d05 || irword[63:44]==20'h01c05;
        assign mul_div_word=irword[43:40]==3 || irword[43:40]==2 || irword[59:56]==3 || irword[59:56]==2;
        assign mul_div_mode=irword[63:44]==20'h01d05 ||  irword[63:56]==8'h51 || irword[63:56]==8'h53 ;
        assign mul_div_enable=irword[63:44]==20'h01c05 || irword[63:44]==20'h01d05 ||
                                              irword[63:56]==8'h51 || irword[63:56]==8'h53 ||
                                                irword[63:56]==8'h50 || irword[63:56]==8'h52;

        assign div_nflag_set=mul_div_enable && state==8'b0000_0001;
      assign div_nflag=mul_div_word ?  RO_left[15] ^ mul_div_dest_reg[31] :
                                                                 RO_left[7]   ^ mul_div_dest_reg[15];
// alu_out
         always @( ope , left , right , carry_w ,  z_bit, c_bit, n_bit , v_bit,access_mode,z_bus,imm ) begin
               case (ope)    
                   `BYPATH_RIGHT : z_bus=right;
                   `BYPATH_LEFT  : z_bus=left;
                   `ADD   :  begin
                                    if (access_mode==`BYTE_ACCESS)          begin
                                             {carry_w,z_bus[7:0]}=left[7:0]+right[7:0];
                                             over_flow= (~left[7] & ~right[7] & z_bus[7] ) | (left[7] & right[7] & !z_bus[7] );
                                    end
                                    else if  (access_mode==`WORD_ACCESS) begin
                                             {carry_w,z_bus[15:0]}=left[15:0]+right[15:0];
                                             over_flow= (~left[15] & ~right[15] & z_bus[15] ) | (left[15] & right[15] & !z_bus[15] );
                                    end else    begin
                                                {carry_w,z_bus[31:0]}=left[31:0]+right[31:0];   
                                                over_flow= (~left[31] & ~right[31] & z_bus[31] ) | (left[31] & right[31] & !z_bus[31] );
                                    end
                                end
                       `SUB  :  begin
                                    if (access_mode==`BYTE_ACCESS) begin
                                           {carry_w,z_bus[7:0]} =right[7:0]-left[7:0];
                                           over_flow= (~right[7] & left[7] & z_bus[7] ) | (right[7] & !left[7] & !z_bus[7] );
                                    end else if (access_mode==`WORD_ACCESS)  begin
                                           over_flow= (~right[15] & left[15] & z_bus[15] ) | (right[15] & !left[15] & !z_bus[15] );
                                           {carry_w,z_bus[15:0]}=right[15:0]-left[15:0];
                                    end else    begin
                                           {carry_w,z_bus[31:0]}=right[31:0]-left[31:0];
                                           over_flow= (~right[31] & left[31] & z_bus[31] ) | (right[31] & !left[31] & !z_bus[31] );
                                    end 
                                end
                       `ADDX   : begin
                                                 {carry_w,z_bus[7:0] }=left[7:0]+right[7:0]+c_bit; // Byte Operation Only
                                                 over_flow= (~left[7] & ~right[7] & z_bus[7] ) | (left[7] & right[7] & !z_bus[7] );
                                           end
                       `SUBX   :  begin 
                                                {carry_w,z_bus[7:0] }=right[7:0]-left[7:0]-c_bit; // Byte Operation Only
                                                over_flow= (~right[7] & left[7] & z_bus[7] ) | (right[7] & !left[7] & !z_bus[7] );
                                            end
                       `ADDS   :  z_bus=left+right;//Long Only No Flag changed SUBS 兼用
                       `AND    :  z_bus=left & right;
                        `OR      :  z_bus=left | right;
                       `XOR    :  z_bus=left ^ right;
                       `NOT    :  z_bus=~left;
                       `NEG    :  begin
                                                if (access_mode==`BYTE_ACCESS)   begin
                                                           {carry_w,z_bus[7:0]} =0-left[7:0];
                                                           over_flow= left[7] & z_bus[7] ;
                                                end
                                                else if (access_mode==`WORD_ACCESS) begin
                                                           {carry_w,z_bus[15:0]}=0-left[15:0];
                                                           over_flow= left[15] & z_bus[15] ;    
                                        end else  begin 
                                                          {carry_w,z_bus[31:0]}=0-left[31:0];
                                                          over_flow= left[31] & z_bus[31] ;
                                                end     
                                        end
                       `EXTU   :   begin 
                                                if (access_mode==`WORD_ACCESS)   z_bus={24'h00_0000,left[7:0]};
                                                else                                                       z_bus={16'h0000, left[15:0]};//LONG ACCESS
                                                end              
                       `EXTS :     begin
                                                if (access_mode==`WORD_ACCESS)   z_bus={ {24{left[7]}},left[7:0]};
                                                else                                                       z_bus={ {16{left[15]}}, left[15:0]};//LONG ACCESS
                                             end
                       `ROTATION_LEFT: begin
                                                        if (access_mode==`BYTE_ACCESS)            {carry_w,z_bus[7:0] }={ left[7:0],left[7]};
                                                        else if ( access_mode==`WORD_ACCESS)    {carry_w,z_bus[15:0]}={ left[15:0],left[15]};
                                                        else                                                                    {carry_w,z_bus[31:0]}={ left[31:0],left[31]};                   
                                                end
                      `ROTATION_RIGHT: begin
                                        if (access_mode==`BYTE_ACCESS)            {z_bus[7:0],carry_w }= { left[0],left[7:1]  ,left[0]};
                                        else if ( access_mode==`WORD_ACCESS)    {z_bus[15:0],carry_w}={ left[0],left[15:1],left[0]};
                                        else                                                            {z_bus[31:0],carry_w}={ left[0],left[31:1],left[0]};                    
                                       end
                      `ROTATION_X_LEFT: begin
                                         if(access_mode==`BYTE_ACCESS)          {carry_w,z_bus[7:0]} = {left[7:0],c_bit};
                                         else if (      access_mode==`WORD_ACCESS)      {carry_w,z_bus[15:0]}={left[15:0],c_bit};
                                         else                                                           {carry_w,z_bus[31:0]}={left[31:0],c_bit};
                                        end
                      `ROTATION_X_RIGHT: begin
                                          if(access_mode==`BYTE_ACCESS)                 {z_bus[7:0],carry_w} = {c_bit,left[7:0]};
                                          else if (     access_mode==`WORD_ACCESS)      {z_bus[15:0],carry_w}={c_bit,left[15:0]};
                                          else                                                          {z_bus[31:0],carry_w}={c_bit,left[31:0]};
                                         end
                      `ARITHMATIC_SHIFT_LEFT: begin//Logical shift Leftとの違いはVFlagが変化すること
                                          if(access_mode==`BYTE_ACCESS)               {carry_w,z_bus[7:0]} ={left[7:0],1'b0} ;
                                          else if (     access_mode==`WORD_ACCESS)   {carry_w,z_bus[15:0]} ={left[15:0],1'b0} ;
                                          else                                                                  {carry_w,z_bus[31:0]} ={left[31:0],1'b0} ;
                                          over_flow=c_bit;//SHIFT関係でVビットがLatchされるのはここだけ。 c_bit をLEFT SHIFTすると OVERFlowに入ると考えた。シミュレータで動作Check要  
                                          end
                                                
                      `ARITHMATIC_SHIFT_RIGHT: begin
                                          if(access_mode==`BYTE_ACCESS)               {z_bus[7:0],carry_w} ={left[7],left[7:0]};//Jun.1.2004
                                          else if (     access_mode==`WORD_ACCESS)   {z_bus[15:0],carry_w} ={left[15],left[15:0]};//Jun.1.2004
                                          else                                                                  {z_bus[31:0],carry_w} ={left[31],left[31:0]};//Jun.1.2004
                                         end
                      `LOGIC_SHIFT_RIGHT: begin
                                           if(access_mode==`BYTE_ACCESS)              {z_bus[7:0],carry_w} ={1'b0,left[7:0]};
                                           else if (    access_mode==`WORD_ACCESS)   {z_bus[15:0],carry_w} ={1'b0,left[15:0]};
                                           else                                                                 {z_bus[31:0],carry_w} ={1'b0,left[31:0]};
                                          end
                      `LOGIC_SHIFT_LEFT: begin
                                           if(access_mode==`BYTE_ACCESS)              {carry_w,z_bus[7:0]} ={left[7:0],1'b0} ;
                                           else if (    access_mode==`WORD_ACCESS)   {carry_w,z_bus[15:0]} ={left[15:0],1'b0} ;
                                           else                                                                 {carry_w,z_bus[31:0]} ={left[31:0],1'b0} ;
                                         end

                      `BSET            :  z_bus[7:0]=bit_set(imm);
                      `BCLR            :  z_bus[7:0]=bit_clr(imm);
                          `BNOT        :  z_bus[7:0]=bit_not(imm);      
                      `BTST            :  z_bus[7:0]=left[7:0];//z_bit のセットは下でおこなう。
                                       
                       default         :  $display("ALU ERROR");
                      endcase
                  end 

   function [7:0] bit_set;
                input [2:0] bit_sel;
                begin
                  case(bit_sel)
                        3'b000: bit_set={right[7:1],1'b1};
                        3'b001: bit_set={right[7:2],1'b1,right[0]  };
                        3'b010: bit_set={right[7:3],1'b1,right[1:0]};
                        3'b011: bit_set={right[7:4],1'b1,right[2:0]};
                        3'b100: bit_set={right[7:5],1'b1,right[3:0]};
                        3'b101: bit_set={right[7:6],1'b1,right[4:0]};
                        3'b110: bit_set={right[7],  1'b1,right[5:0]};
                        3'b111: bit_set={           1'b1,right[6:0]};
                  endcase
                end
        endfunction
        function [7:0] bit_clr;
                input [2:0] bit_sel;
                begin
                  case(bit_sel)
                        3'b000: bit_clr={right[7:1],1'b0};
                        3'b001: bit_clr={right[7:2],1'b0,right[0]  };
                        3'b010: bit_clr={right[7:3],1'b0,right[1:0]};
                        3'b011: bit_clr={right[7:4],1'b0,right[2:0]};
                        3'b100: bit_clr={right[7:5],1'b0,right[3:0]};
                        3'b101: bit_clr={right[7:6],1'b0,right[4:0]};
                        3'b110: bit_clr={right[7],  1'b0,right[5:0]};
                        3'b111: bit_clr={           1'b0,right[6:0]};
                  endcase
                end
        endfunction

         function [7:0] bit_not;
                input [2:0] bit_sel;
                begin
                  case(bit_sel)
                        3'b000: bit_not={right[7:1],~right[0]};
                        3'b001: bit_not={right[7:2], ~right[1],right[0] };
                        3'b010: bit_not={right[7:3],~right[2],right[1:0]};
                        3'b011: bit_not={right[7:4],~right[3],right[2:0]};
                        3'b100: bit_not={right[7:5],~right[4],right[3:0]};
                        3'b101: bit_not={right[7:6],~right[5],right[4:0]};
                        3'b110: bit_not={right[7],  ~right[6],right[5:0]};
                        3'b111: bit_not={           ~right[7],right[6:0]};
                  endcase
                end
        endfunction

// z_out
   assign z_out=access_mode ==`LONG_ACCESS ? z_bus==32'h0000 : access_mode==`WORD_ACCESS ? z_bus[15:0]==16'h0000 : z_bus[7:0] ==8'h00;//May.31.2004
   assign n_out=access_mode ==`LONG_ACCESS ? z_bus[31]  : access_mode==`WORD_ACCESS ?  z_bus[15] : z_bus[7];
  
   assign ccr_input=ccr_input_sel==`ALU_OUT_SEL ? z_bus[7:0] :
                                  ccr_input_sel==`MOUT_7_0_SEL ? MOUT[7:0] : MOUT[31:24];

//c_bit
        always @ (posedge clock)
          if (sync_reset)     c_bit<=1'b0;
          else if (ccr_all_write) c_bit<=ccr_input[0];
          else if (c_latch)   c_bit<=carry_w;
// v_bit
        always @ (posedge clock)
          if (sync_reset)     v_bit<=1'b0;
          else if (ccr_all_write) v_bit<=ccr_input[1];
          else if (v_clear)       v_bit<=1'b0;
          else if (v_latch)    v_bit<=over_flow;
// n_bit
        always @ (posedge clock)
          if (sync_reset) n_bit<=1'b0;
          else if (ccr_all_write) n_bit<=ccr_input[3];
            else if (div_nflag_set) n_bit <=div_nflag_set;//Jun.4.2004
          else if (n_latch ) n_bit<=n_out;
// z_bit
        always @ (posedge clock) begin
          if (sync_reset) z_bit<=1'b0;
         else if (ccr_all_write) z_bit<=ccr_input[2];
           else if (z_latch && (ope==`ADDX  || ope==`SUBX)) z_bit<=(z_bus[7:0]==8'h00) ? z_bit :1'b0;//ADDX,SUBXはBYTEONLY 演算結果が0の時=>前の値保持、それ以外クリア
           else if (z_latch && ope==`BTST)  begin
               case(imm)
                3'b000:         z_bit<=!z_bus[0];
                3'b001:         z_bit<=!z_bus[1];
                3'b010:         z_bit<=!z_bus[2];
                3'b011:         z_bit<=!z_bus[3];
                3'b100:         z_bit<=!z_bus[4];
                3'b101:         z_bit<=!z_bus[5];
                3'b110:         z_bit<=!z_bus[6];
                3'b111:         z_bit<=!z_bus[7];
              endcase
          end
          else if (z_latch) z_bit<=z_out;
        end
// i_bit
        always @ (posedge clock)
        if (sync_reset) i_bit<=1'b1;
          else if (bus_state==2'b10 && z_latch) i_bit<=1;       // if interrput state
        else if (ccr_all_write) i_bit<=ccr_input[7];
// u_bit
        always @ (posedge clock) begin
        if (sync_reset) begin
                      u_bit6<=1'b0;
                      h_bit <=1'b0;
                      u_bit4<=1'b0;
                    end
        else if (ccr_all_write) begin
                      u_bit6<=ccr_input[6];
                      h_bit <=ccr_input[5];
                      u_bit4<=ccr_input[4];
        end
        end
// CCR
        assign CCR={i_bit,u_bit6,h_bit,u_bit4,n_bit,z_bit,v_bit,c_bit};
       
//BCC
        always @(irword[60],IR0L,IR1H,c_bit,v_bit,z_bit,n_bit) begin
                if (irword[60]) begin//IR0H 5 disp16
                case ( IR1H) 
                        `BRA : BCC_jmp=1;
                        `BRN : BCC_jmp=0;
                        `BHI  : if(!(c_bit || z_bit)) BCC_jmp=1; else BCC_jmp=0;
                        `BLS : if( c_bit || z_bit)  BCC_jmp=1; else BCC_jmp=0;
                        `BHS : if(!c_bit ) BCC_jmp=1;else BCC_jmp=0;
                        `BLO : if(c_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BEQ : if(z_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BNE : if(!z_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BVC : if(!v_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BVS : if(v_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BPL : if(!n_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BMI : if(n_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BGE : if(!(n_bit^v_bit)) BCC_jmp=1; else BCC_jmp=0;
                        `BLT : if((n_bit^v_bit)) BCC_jmp=1;else BCC_jmp=0;
                        `BGT : if(!(z_bit | (n_bit^v_bit))) BCC_jmp=1;else BCC_jmp=0;
                        `BLE : if(z_bit | (n_bit^v_bit)) BCC_jmp=1; else BCC_jmp=0;
                endcase
                end else begin//IR0H=4 displacement:8
                case ( IR0L) 
                        `BRA : BCC_jmp=1;
                        `BRN : BCC_jmp=0;
                        `BHI  : if(!(c_bit || z_bit)) BCC_jmp=1; else BCC_jmp=0;
                        `BLS : if( c_bit || z_bit)  BCC_jmp=1; else BCC_jmp=0;
                        `BHS : if(!c_bit ) BCC_jmp=1;else BCC_jmp=0;
                        `BLO : if(c_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BEQ : if(z_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BNE : if(!z_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BVC : if(!v_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BVS : if(v_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BPL : if(!n_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BMI : if(n_bit) BCC_jmp=1;else BCC_jmp=0;
                        `BGE : if(!(n_bit^v_bit)) BCC_jmp=1; else BCC_jmp=0;
                        `BLT : if((n_bit^v_bit)) BCC_jmp=1;else BCC_jmp=0;
                        `BGT : if(!(z_bit | (n_bit^v_bit))) BCC_jmp=1;else BCC_jmp=0;
                        `BLE : if(z_bit | (n_bit^v_bit)) BCC_jmp=1; else BCC_jmp=0;
                endcase


                end
        end


endmodule