Inputs | Outputs | Signals | Module Instances | Defines | Always Constructs

alu Module Reference

Arithmetic and Logic Unit. More...

Inheritance diagram for alu:
ao68000

List of all members.

Always Constructs

ALWAYS_31  ( clock , reset_n )
ALWAYS_32  ( clock , reset_n )

Defines

Sm  ((size [0]==1'b1)?operand2[7]:(size [1]==1'b1)?operand2[15]:operand2 [31])
Dm  ((size [0]==1'b1)?operand1[7]:(size [1]==1'b1)?operand1[15]:operand1 [31])
Rm  ((size [0]==1'b1)?result[7]:(size [1]==1'b1)?result[15]:result [31])
Z  ((size [0]==1'b1)?(result [7:0]==8'b0):(size [1]==1'b1)?(result [15:0]==16'b0):(result [31:0]==32'b0))

Inputs

clock  
reset_n  
address  [31:0]
ir  [15:0]
size  [2:0]
operand1  [31:0]
operand2  [31:0]
interrupt_mask  [2:0]
alu_control  [4:0]
decoder_alu_reg  [17:0]

Outputs

sr  reg[15:0]
result  reg[31:0]
alu_signal  reg
alu_mult_div_ready  

Module Instances

lpm_mult::muls  

Signals

wire  mult_div_sign
reg[4:0]  div_count
reg[16:0]  quotient
reg[31:0]  dividend
reg[31:0]  divider
wire[32:0]  div_diff
wire  div_overflow
wire[15:0]  div_quotient
wire[15:0]  div_remainder
wire[33:0]  mult_result
reg[2:0]  interrupt_mask_copy
reg  was_interrupt
wire  lbit
wire  rbit

Detailed Description

Arithmetic and Logic Unit.

The alu module is responsible for performing all of the arithmetic and logic operations of the ao68000 processor. It operates on two 32-bit registers: operand1 and operand2 from the registers module. The output is saved into a result 32-bit register. This register is located in the alu module.

The alu module also contains the status register (SR) with the condition code register. The microcode decides what operation the alu performs.

Definition at line 2626 of file ao68000.v.


Member Function Documentation

[Always Construct]
ALWAYS_31 ( clock ,
reset_n )

Definition at line 2688 of file ao68000.v.

 
02688 always @(posedge clock or negedge reset_n) begin
02689     if(reset_n == 1'b0) begin
02690         div_count <= 5'd0;
02691     end
02692     // Cycle #0 : load the registers
02693     else if(alu_control == `ALU_MULS_MULU_DIVS_DIVU && ir[15:12] == 4'b1000 && div_count == 5'd0) begin
02694         // 17 cycles to finish + wait state
02695         div_count   <= 5'd18;
02696         // Clear the quotient
02697         quotient    <= 17'd0;
02698     
02699         // Unsigned divide or positive numerator
02700         if ((!mult_div_sign) || (!operand1[31]))    dividend <= operand1;
02701         // Negative numerator
02702         else                                        dividend <= -operand1;
02703         
02704         // Unsigned divide or positive denominator
02705         if ((!mult_div_sign) || (!operand2[15]))    divider <= {operand2[15:0],16'd0};
02706         // Negative denominator
02707         else                                        divider <= {-operand2[15:0],16'd0};
02708     end
02709     // Cycles #1-17 : division calculation
02710     else if(div_count > 5'd1) begin
02711         // Check difference's sign
02712         if (!div_diff[32]) begin
02713           // Difference is positive : shift a one
02714           dividend <= div_diff[31:0];
02715           quotient <= {quotient[15:0], 1'b1};
02716         end
02717         else begin
02718           // Difference is negative : shift a zero
02719           quotient <= {quotient[15:0], 1'b0};
02720         end
02721         // Shift right divider
02722         divider <= {1'b0, divider[31:1]};
02723         // Count one bit
02724         div_count <= div_count - 5'd1;
02725     end
02726     // result read
02727     else if(alu_control == `ALU_MULS_MULU_DIVS_DIVU && ir[15:12] == 4'b1000 && div_count == 5'd1) begin
02728         // goto idle
02729         div_count <= div_count - 5'd1;
02730     end
02731 end
[Always Construct]
ALWAYS_32 ( clock ,
reset_n )

Definition at line 2774 of file ao68000.v.

 
02774 always @(posedge clock or negedge reset_n) begin
02775     if(reset_n == 1'b0) begin
02776         sr                  <= { 1'b0, 1'b0, 1'b1, 2'b0, 3'b111, 8'b0 };
02777         result              <= 32'd0;
02778         alu_signal          <= 1'b0;
02779         interrupt_mask_copy <= 3'b0;
02780         was_interrupt       <= 1'b0;
02781     end
02782     else begin
02783         case(alu_control)
02784             `ALU_SR_SET_INTERRUPT: begin
02785                 interrupt_mask_copy <= interrupt_mask[2:0];
02786                 was_interrupt <= 1'b1;
02787             end
02788 
02789             `ALU_SR_SET_TRAP: begin
02790                 if(was_interrupt == 1'b1) begin
02791                     sr <= { 1'b0, sr[14], 1'b1, sr[12:11], interrupt_mask_copy[2:0], sr[7:0] };
02792                 end
02793                 else begin
02794                     sr <= { 1'b0, sr[14], 1'b1, sr[12:0] };
02795                 end
02796                 was_interrupt <= 1'b0;
02797             end
02798 
02799             `ALU_MOVEP_M2R_1: begin
02800                 if(ir[6] == 1'b1)   result[31:24] <= operand1[7:0];
02801                 else                result[15:8] <= operand1[7:0];
02802                 //CCR: no change
02803             end
02804             `ALU_MOVEP_M2R_2: begin
02805                 if(ir[6] == 1'b1)   result[23:16] <= operand1[7:0];
02806                 else                result[7:0] <= operand1[7:0];
02807                 //CCR: no change
02808             end
02809             `ALU_MOVEP_M2R_3: begin
02810                 if(ir[6] == 1'b1)   result[15:8] <= operand1[7:0];
02811                 //CCR: no change
02812             end
02813             `ALU_MOVEP_M2R_4: begin
02814                 if(ir[6] == 1'b1)   result[7:0] <= operand1[7:0];
02815                 //CCR: no change
02816             end
02817             
02818 
02819             `ALU_MOVEP_R2M_1: begin
02820                 if(ir[6] == 1'b1)   result[7:0] <= operand1[31:24];
02821                 else                result[7:0] <= operand1[15:8];
02822                 // CCR: no change
02823             end
02824             `ALU_MOVEP_R2M_2: begin
02825                 if(ir[6] == 1'b1)   result[7:0] <= operand1[23:16];
02826                 else                result[7:0] <= operand1[7:0];
02827                 // CCR: no change
02828             end
02829             `ALU_MOVEP_R2M_3: begin
02830                 result[7:0] <= operand1[15:8];
02831                 // CCR: no change
02832             end
02833             `ALU_MOVEP_R2M_4: begin
02834                 result[7:0] <= operand1[7:0];
02835                 // CCR: no change
02836             end
02837 
02838             `ALU_SIGN_EXTEND: begin
02839                 // move operand1 with sign-extension to result
02840                 if(size[1] == 1'b1) begin
02841                     result <= { {16{operand1[15]}}, operand1[15:0] };
02842                 end
02843                 else begin
02844                     result <= operand1;
02845                 end
02846                 // CCR: no change
02847             end
02848 
02849             `ALU_ARITHMETIC_LOGIC: begin
02850 
02851                 // OR,OR to mem,OR to Dn
02852                 if(decoder_alu_reg[0])                              result[31:0] = operand1[31:0] | operand2[31:0];
02853                 // AND,AND to mem,AND to Dn
02854                 else if(decoder_alu_reg[1])                         result[31:0] = operand1[31:0] & operand2[31:0];
02855                 // EORI,EOR
02856                 else if(decoder_alu_reg[2])                         result[31:0] = operand1[31:0] ^ operand2[31:0];
02857                 // ADD,ADD to mem,ADD to Dn,ADDQ
02858                 else if(decoder_alu_reg[3])                         result[31:0] = operand1[31:0] + operand2[31:0];
02859                 // SUBI,CMPI,CMPM,SUB to mem,SUB to Dn,CMP,SUBQ
02860                 else if(decoder_alu_reg[4] | decoder_alu_reg[5])    result[31:0] = operand1[31:0] - operand2[31:0];
02861 
02862                 // Z
02863                 sr[2] <= `Z;
02864                 // N
02865                 sr[3] <= `Rm;
02866 
02867                 // CMPI,CMPM,CMP
02868                 if(decoder_alu_reg[5]) begin
02869                     // C,V
02870                     sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02871                     sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02872                     // X not affected
02873                 end
02874                 // ADDI,ADD to mem,ADD to Dn,ADDQ
02875                 else if(decoder_alu_reg[3]) begin
02876                     // C,X,V
02877                     sr[0] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm);
02878                     sr[4] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm); //=ccr[0];
02879                     sr[1] <= (`Sm & `Dm & ~`Rm) | (~`Sm & ~`Dm & `Rm);
02880                 end
02881                 // SUBI,SUB to mem,SUB to Dn,SUBQ
02882                 else if(decoder_alu_reg[4]) begin
02883                     // C,X,V
02884                     sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02885                     sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
02886                     sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02887                 end
02888                 // ANDI,EORI,ORI,EOR,OR to mem,AND to mem,OR to Dn,AND to Dn
02889                 else begin
02890                     // C,V
02891                     sr[0] <= 1'b0;
02892                     sr[1] <= 1'b0;
02893                     // X not affected
02894                 end
02895             end
02896             
02897             `ALU_ABCD_SBCD_ADDX_SUBX_prepare: begin
02898                 // ABCD
02899                 if( ir[14:12] == 3'b100) begin
02900                     result[13:8] = {1'b0, operand1[3:0]} + {1'b0, operand2[3:0]} + {4'b0, sr[4]};
02901                     result[19:14] = {1'b0, operand1[7:4]} + {1'b0, operand2[7:4]};
02902                     
02903                     result[31:23] = operand1[7:0] + operand2[7:0] + {7'b0, sr[4]};
02904                     
02905                     result[13:8] = (result[13:8] > 6'd9) ? (result[13:8] + 6'd6) : result[13:8];
02906                 end
02907                 // SBCD
02908                 else if( ir[14:12] == 3'b000 ) begin
02909                     result[13:8] = 6'd32 + {2'b0, operand1[3:0]} - {2'b0, operand2[3:0]} - {5'b0, sr[4]};
02910                     result[19:14] = 6'd32 + {2'b0, operand1[7:4]} - {2'b0, operand2[7:4]};
02911                     
02912                     result[31:23] = operand1[7:0] - operand2[7:0] - {7'b0, sr[4]};
02913                     
02914                     result[13:8] = (result[13:8] < 6'd32) ? (result[13:8] - 6'd6) : result[13:8];
02915                 end
02916             end
02917             
02918             `ALU_ABCD_SBCD_ADDX_SUBX: begin
02919                 // ABCD
02920                 if( ir[14:12] == 3'b100) begin
02921                     result[19:14] = (result[13:8] > 6'h1F) ? (result[19:14] + 6'd2) :
02922                                     (result[13:8] > 6'h0F) ? (result[19:14] + 6'd1) :
02923                                     result[19:14];
02924                     result[19:14] = (result[19:14] > 6'd9) ? (result[19:14] + 6'd6) : result[19:14];
02925                     
02926                     result[7:4] = result[17:14];
02927                     result[3:0] = result[11:8];
02928 
02929                     // C
02930                     sr[0] <= (result[19:14] > 6'd9) ? 1'b1 : 1'b0;
02931                     // X = C
02932                     sr[4] <= (result[19:14] > 6'd9) ? 1'b1 : 1'b0;
02933                     
02934                     // V
02935                     sr[1] <= (result[30] == 1'b0 && result[7] == 1'b1) ? 1'b1 : 1'b0;
02936                 end
02937                 // SBCD
02938                 else if( ir[14:12] == 3'b000 ) begin
02939                     result[19:14] = (result[13:8] < 6'd16) ? (result[19:14] - 6'd2) :
02940                                     (result[13:8] < 6'd32) ? (result[19:14] - 6'd1) :
02941                                     result[19:14];
02942                     result[19:14] = (result[19:14] < 6'd32 && result[31] == 1'b1) ? (result[19:14] - 6'd6) : result[19:14];
02943                     
02944                     result[7:4] = result[17:14];
02945                     result[3:0] = result[11:8];
02946                 
02947                     // C
02948                     sr[0] <= (result[19:14] < 6'd32) ? 1'b1 : 1'b0;
02949                     // X = C
02950                     sr[4] <= (result[19:14] < 6'd32) ? 1'b1 : 1'b0;
02951                     
02952                     // V
02953                     sr[1] <= (result[30] == 1'b1 && result[7] == 1'b0) ? 1'b1 : 1'b0;
02954                 end
02955                 // ADDX
02956                 else if( ir[14:12] == 3'b101 ) begin
02957                     result[31:0] = operand1[31:0] + operand2[31:0] + sr[4];
02958                     
02959                     // C,X,V
02960                     sr[0] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm);
02961                     sr[4] <= (`Sm & `Dm) | (~`Rm & `Dm) | (`Sm & ~`Rm); //=ccr[0];
02962                     sr[1] <= (`Sm & `Dm & ~`Rm) | (~`Sm & ~`Dm & `Rm);
02963                 end
02964                 // SUBX
02965                 else if( ir[14:12] == 3'b001 ) begin
02966                     result[31:0] = operand1[31:0] - operand2[31:0] - sr[4];
02967                     
02968                     // C,X,V
02969                     sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
02970                     sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
02971                     sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
02972                 end
02973                 
02974                 // Z
02975                 sr[2] <= sr[2] & `Z;
02976                 // N
02977                 sr[3] <= `Rm;
02978             end
02979 
02980             `ALU_ASL_LSL_ROL_ROXL_ASR_LSR_ROR_ROXR_prepare: begin
02981                 // 32-bit load even for 8-bit and 16-bit operations
02982                 // The extra bits will be anyway discarded during register / memory write
02983                 result[31:0] = operand1[31:0];
02984                 
02985                 // V cleared
02986                 sr[1] <= 1'b0;
02987                 // C for ROXL,ROXR: set to X
02988                 if(decoder_alu_reg[11] | decoder_alu_reg[15]) begin
02989                     sr[0] <= sr[4];
02990                 end
02991                 else begin
02992                     // C cleared
02993                     sr[0] <= 1'b0;
02994                 end
02995 
02996                 // N set
02997                 sr[3] <= `Rm;
02998                 // Z set
02999                 sr[2] <= `Z;
03000             end
03001 
03002             `ALU_ASL_LSL_ROL_ROXL_ASR_LSR_ROR_ROXR: begin
03003                 // ASL / LSL / ROL / ROXL
03004                 if (decoder_alu_reg[8] | decoder_alu_reg[9] | decoder_alu_reg[10] | decoder_alu_reg[11]) begin
03005                     result[31:0] = {operand1[30:0], lbit};
03006 
03007                     sr[0] <= `Dm; // C for ASL / LSL / ROL / ROXL
03008                     if (decoder_alu_reg[8])
03009                         sr[1] <= (sr[1] == 1'b0)? (`Rm != `Dm) : 1'b1; // V for ASL
03010                     else
03011                         sr[1] <= 1'b0; // V for LSL / ROL / ROXL
03012                    
03013                     if (!decoder_alu_reg[10]) sr[4] <= `Dm; // X for ASL / LSL / ROXL
03014                 end
03015                 // ASR / LSR / ROR / ROXR
03016                 else begin
03017                     result[6:0]   = operand1[7:1];
03018                     result[7]     = (size[0]) ? rbit : operand1[8];
03019                     result[14:8]  = operand1[15:9];
03020                     result[15]    = (size[1]) ? rbit : operand1[16];
03021                     result[30:16] = operand1[31:17];
03022                     result[31]    = rbit;
03023                     sr[0] <= operand1[0]; // C for ASR / LSR / ROR / ROXR
03024                     sr[1] <= 1'b0;        // V for ASR / LSR / ROR / ROXR
03025                     if (!decoder_alu_reg[14]) sr[4] <= operand1[0]; // X for ASR / LSR / ROXR
03026                 end
03027 
03028                 // N set
03029                 sr[3] <= `Rm;
03030                 // Z set
03031                 sr[2] <= `Z;
03032             end
03033 
03034             `ALU_MOVE: begin
03035                 result = operand1;
03036 
03037                 // X not affected
03038                 // C cleared
03039                 sr[0] <= 1'b0;
03040                 // V cleared
03041                 sr[1] <= 1'b0;
03042 
03043                 // N set
03044                 sr[3] <= `Rm;
03045                 // Z set
03046                 sr[2] <= `Z;
03047             end
03048 
03049             `ALU_ADDA_SUBA_CMPA_ADDQ_SUBQ: begin
03050                 // ADDA: 1101
03051                 // CMPA: 1011
03052                 // SUBA: 1001
03053                 // ADDQ,SUBQ: 0101 xxx0,1
03054                 // operation requires that operand2 was sign extended
03055                 
03056                 // ADDA,ADDQ
03057                 if(decoder_alu_reg[6])  result[31:0] = operand1[31:0] + operand2[31:0];
03058                 // SUBA,CMPA,SUBQ
03059                 else                    result[31:0] = operand1[31:0] - operand2[31:0];
03060 
03061                 // for CMPA
03062                 if( ir[15:12] == 4'b1011 ) begin
03063                     // Z
03064                     sr[2] <= `Z;
03065                     // N
03066                     sr[3] <= `Rm;
03067 
03068                     // C,V
03069                     sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
03070                     sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
03071                     // X not affected
03072                 end
03073                 // for ADDA,SUBA,ADDQ,SUBQ: ccr not affected
03074             end
03075 
03076             `ALU_CHK: begin
03077                 result[15:0] = operand1[15:0] - operand2[15:0];
03078                 
03079                 // undocumented behavior: Z flag, see 68knotes.txt
03080                 //sr[2] <= (operand1[15:0] == 16'b0) ? 1'b1 : 1'b0;
03081                 // undocumented behavior: C,V flags, see 68knotes.txt
03082                 //sr[0] <= 1'b0;
03083                 //sr[1] <= 1'b0;
03084                 
03085                 // C,X,V
03086                 //    sr[0] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm);
03087                 //    sr[4] <= (`Sm & ~`Dm) | (`Rm & ~`Dm) | (`Sm & `Rm); //=ccr[0];
03088                 //    sr[1] <= (~`Sm & `Dm & ~`Rm) | (`Sm & ~`Dm & `Rm);
03089                 // +: 0-1,    0-0=0, 1-1=0
03090                 // -: 0-0=1,  1-0,   1-1=1
03091                 // operand1 - operand2 > 0
03092                 if( operand1[15:0] != operand2[15:0] && ((~`Dm & `Sm) | (~`Dm & ~`Sm & ~`Rm) | (`Dm & `Sm & ~`Rm)) == 1'b1 ) begin
03093                     // clear N
03094                     sr[3] <= 1'b0;
03095                     alu_signal <= 1'b1;
03096                 end
03097                 // operand1 < 0
03098                 else if( operand1[15] == 1'b1 ) begin
03099                     // set N
03100                     sr[3] <= 1'b1;
03101                     alu_signal <= 1'b1;
03102                 end
03103                 // no trap
03104                 else begin
03105                     // N undefined: not affected
03106                     alu_signal <= 1'b0;
03107                 end
03108 
03109                 // X not affected
03110             end
03111 
03112             `ALU_MULS_MULU_DIVS_DIVU: begin
03113 
03114                 // division by 0
03115                 if(ir[15:12] == 4'b1000 && operand2[15:0] == 16'b0) begin
03116                     // X not affected
03117                     // C cleared
03118                     sr[0] <= 1'b0;
03119                     // V,Z,N undefined: cleared
03120                     sr[1] <= 1'b0;
03121                     sr[2] <= 1'b0;
03122                     sr[3] <= 1'b0;
03123 
03124                     // set trap
03125                     alu_signal <= 1'b1;
03126                 end
03127                 // division in idle state
03128                 else if(ir[15:12] == 4'b1000 && div_count == 5'd0) begin
03129                     alu_signal <= 1'b0;
03130                 end
03131                 // division overflow: divu, divs
03132                 else if(ir[15:12] == 4'b1000 && div_overflow == 1'b1) begin
03133                     // X not affected
03134                     // C cleared
03135                     sr[0] <= 1'b0;
03136                     // V set
03137                     sr[1] <= 1'b1;
03138                     // Z,N undefined: cleared and set
03139                     sr[2] <= 1'b0;
03140                     sr[3] <= 1'b1;
03141 
03142                     // set trap
03143                     alu_signal <= 1'b1;
03144                 end
03145                 // division
03146                 else if( ir[15:12] == 4'b1000 ) begin
03147                     result[31:0] <= {div_remainder, div_quotient};
03148                     
03149                     // X not affected
03150                     // C cleared
03151                     sr[0] <= 1'b0;
03152                     // V cleared
03153                     sr[1] <= 1'b0;
03154                     // Z
03155                     sr[2] <= (div_quotient == 16'b0);
03156                     // N
03157                     sr[3] <= (div_quotient[15] == 1'b1);
03158 
03159                     // set trap
03160                     alu_signal <= 1'b0;
03161                 end
03162                 // multiplication
03163                 else if( ir[15:12] == 4'b1100 ) begin
03164                     result[31:0] <= mult_result[31:0];
03165 
03166                     // X not affected
03167                     // C cleared
03168                     sr[0] <= 1'b0;
03169                     // V cleared
03170                     sr[1] <= 1'b0;
03171                     // Z
03172                     sr[2] <= (mult_result[31:0] == 32'b0);
03173                     // N
03174                     sr[3] <= (mult_result[31] == 1'b1);
03175 
03176                     // set trap
03177                     alu_signal <= 1'b0;
03178                 end
03179             end
03180 
03181 
03182             `ALU_BCHG_BCLR_BSET_BTST: begin // 97 LE
03183                 // byte
03184                 if( ir[5:3] != 3'b000 ) begin
03185                     sr[2] <= ~(operand1[ operand2[2:0] ]);
03186                     result = operand1;
03187                     result[ operand2[2:0] ] = (ir[7:6] == 2'b01) ? ~(operand1[ operand2[2:0] ]) : (ir[7:6] == 2'b10) ? 1'b0 : 1'b1;
03188                 end
03189                 // long
03190                 else if( ir[5:3] == 3'b000 ) begin
03191                     sr[2] <= ~(operand1[ operand2[4:0] ]);
03192                     result = operand1;
03193                     result[ operand2[4:0] ] = (ir[7:6] == 2'b01) ? ~(operand1[ operand2[4:0] ]) : (ir[7:6] == 2'b10) ? 1'b0 : 1'b1;
03194                 end
03195 
03196                 // C,V,N,X not affected
03197             end
03198 
03199             `ALU_TAS: begin
03200                 result[7:0] <= { 1'b1, operand1[6:0] };
03201 
03202                 // X not affected
03203                 // C cleared
03204                 sr[0] <= 1'b0;
03205                 // V cleared
03206                 sr[1] <= 1'b0;
03207 
03208                 // N set
03209                 sr[3] <= (operand1[7] == 1'b1);
03210                 // Z set
03211                 sr[2] <= (operand1[7:0] == 8'b0);
03212             end
03213 
03214 
03215             `ALU_NEGX_CLR_NEG_NOT_NBCD_SWAP_EXT: begin
03216                 // NEGX / CLR / NEG / NOT
03217                 // Optimization thanks to Frederic Requin
03218                 if ((ir[11:8] == 4'b0000) || (ir[11:8] == 4'b0010) || (ir[11:8] == 4'b0100) || (ir[11:8] == 4'b0110))
03219                     result = 32'b0 - (operand1[31:0] & {32{ir[10] | ~ir[9]}}) - ((sr[4] & ~ir[10] & ~ir[9]) | (ir[10] & ir[9]));
03220                 // NBCD
03221                 else if( ir[11:6] == 6'b1000_00 ) begin
03222                     result[3:0] = 5'd25 - operand1[3:0];
03223                     result[7:4] = (operand1[3:0] > 4'd9) ? (5'd24 - operand1[7:4]) : (5'd25 - operand1[7:4]);
03224                     
03225                     if(sr[4] == 1'b0 && result[3:0] == 4'd9 && result[7:4] == 4'd9) begin
03226                         result[3:0] = 4'd0;
03227                         result[7:4] = 4'd0;
03228                     end
03229                     else if(sr[4] == 1'b0 && (result[3:0] == 4'd9 || result[3:0] == 4'd15)) begin
03230                         result[3:0] = 4'd0;
03231                         result[7:4] = result[7:4] + 4'd1;
03232                     end
03233                     else if(sr[4] == 1'b0) begin
03234                         result[3:0] = result[3:0] + 4'd1;
03235                     end
03236                     
03237                     //V undefined: unchanged
03238                     //Z
03239                     sr[2] <= sr[2] & `Z;
03240                     //C,X
03241                     sr[0] <= (operand1[7:0] == 8'd0 && sr[4] == 1'b0) ? 1'b0 : 1'b1;
03242                     sr[4] <= (operand1[7:0] == 8'd0 && sr[4] == 1'b0) ? 1'b0 : 1'b1; //=C
03243                 end
03244                 // SWAP
03245                 else if( ir[11:6] == 6'b1000_01 ) result = { operand1[15:0], operand1[31:16] };
03246                 // EXT byte to word
03247                 else if( ir[11:6] == 6'b1000_10 ) result = { result[31:16], {8{operand1[7]}}, operand1[7:0] };
03248                 // EXT word to long
03249                 else if( ir[11:6] == 6'b1000_11 ) result = { {16{operand1[15]}}, operand1[15:0] };
03250 
03251                 // N set if negative else clear
03252                 sr[3] <= `Rm;
03253 
03254                 // CLR,NOT,SWAP,EXT
03255                 if( ir[11:8] == 4'b0010 || ir[11:8] == 4'b0110 || ir[11:6] == 6'b1000_01 || ir[11:7] == 5'b1000_1 ) begin
03256                     // X not affected
03257                     // C,V cleared
03258                     sr[0] <= 1'b0;
03259                     sr[1] <= 1'b0;
03260                     // Z set
03261                     sr[2] <= `Z;
03262                 end
03263                 // NEGX
03264                 else if( ir[11:8] == 4'b0000 ) begin
03265                     // C set if borrow
03266                     sr[0] <= `Dm | `Rm;
03267                     // X=C
03268                     sr[4] <= `Dm | `Rm;
03269                     // V set if overflow
03270                     sr[1] <= `Dm & `Rm;
03271                     // Z cleared if nonzero else unchanged
03272                     sr[2] <= sr[2] & `Z;
03273                 end
03274                 // NEG
03275                 else if( ir[11:8] == 4'b0100 ) begin
03276                     // C clear if zero else set
03277                     sr[0] <= `Dm | `Rm;
03278                     // X=C
03279                     sr[4] <= `Dm | `Rm;
03280                     // V set if overflow
03281                     sr[1] <= `Dm & `Rm;
03282                     // Z set if zero else clear
03283                     sr[2] <= `Z;
03284                 end
03285             end
03286 
03287 
03288             `ALU_SIMPLE_LONG_ADD: begin
03289                 result <= operand1[31:0] + operand2[31:0];
03290 
03291                 // CCR not affected
03292             end
03293 
03294             `ALU_SIMPLE_LONG_SUB: begin
03295                 result <= operand1[31:0] - operand2[31:0];
03296 
03297                 // CCR not affected
03298             end
03299 
03300             `ALU_MOVE_TO_CCR_SR_RTE_RTR_STOP_LOGIC_TO_CCR_SR: begin
03301 
03302                 // MOVE TO SR,RTE,STOP,ORI to SR,ANDI to SR,EORI to SR
03303                 if(decoder_alu_reg[16]) sr <= { operand1[15], 1'b0, operand1[13], 2'b0, operand1[10:8], 3'b0, operand1[4:0] };
03304                 // MOVE TO CCR,RTR,ORI to CCR,ANDI to CCR,EORI to CCR
03305                 else                    sr <= { sr[15:8], 3'b0, operand1[4:0] };
03306             end
03307 
03308             `ALU_SIMPLE_MOVE: begin
03309                 result <= operand1;
03310                 
03311                 // CCR not affected
03312             end
03313             
03314             `ALU_LINK_MOVE: begin
03315                 if(ir[3:0] == 3'b111) begin
03316                     result <= operand1 - 32'd4;
03317                 end
03318                 else begin
03319                     result <= operand1;
03320                 end
03321                 
03322                 // CCR not affected
03323             end
03324 
03325         endcase
03326     end
03327 end

Member Data Documentation

clock [Input]

Definition at line 2627 of file ao68000.v.

reset_n [Input]

Definition at line 2628 of file ao68000.v.

address [31:0] [Input]

Definition at line 2631 of file ao68000.v.

ir [15:0] [Input]

Definition at line 2633 of file ao68000.v.

size [2:0] [Input]

Definition at line 2635 of file ao68000.v.

operand1 [31:0] [Input]

Definition at line 2637 of file ao68000.v.

operand2 [31:0] [Input]

Definition at line 2638 of file ao68000.v.

interrupt_mask [2:0] [Input]

Definition at line 2640 of file ao68000.v.

alu_control [4:0] [Input]

Definition at line 2641 of file ao68000.v.

sr reg[15:0] [Output]

Definition at line 2643 of file ao68000.v.

result reg[31:0] [Output]

Definition at line 2644 of file ao68000.v.

alu_signal reg [Output]

Definition at line 2646 of file ao68000.v.

Definition at line 2647 of file ao68000.v.

decoder_alu_reg [17:0] [Input]

Definition at line 2648 of file ao68000.v.

mult_div_sign [wire]

Definition at line 2659 of file ao68000.v.

div_count [reg[4:0]]

Definition at line 2662 of file ao68000.v.

quotient [reg[16:0]]

Definition at line 2663 of file ao68000.v.

dividend [reg[31:0]]

Definition at line 2664 of file ao68000.v.

divider [reg[31:0]]

Definition at line 2664 of file ao68000.v.

div_diff [wire[32:0]]

Definition at line 2667 of file ao68000.v.

div_overflow [wire]

Definition at line 2670 of file ao68000.v.

div_quotient [wire[15:0]]

Definition at line 2676 of file ao68000.v.

div_remainder [wire[15:0]]

Definition at line 2682 of file ao68000.v.

mult_result [wire[33:0]]

Definition at line 2735 of file ao68000.v.

interrupt_mask_copy [reg[2:0]]

Definition at line 2766 of file ao68000.v.

Definition at line 2767 of file ao68000.v.

lbit [wire]

Definition at line 2770 of file ao68000.v.

rbit [wire]

Definition at line 2772 of file ao68000.v.

Dm [Define]

Definition at line 2758 of file ao68000.v.

lpm_mult muls [Module Instance]

Definition at line 2737 of file ao68000.v.

Rm [Define]

Definition at line 2760 of file ao68000.v.

Sm [Define]

Definition at line 2756 of file ao68000.v.

Z [Define]

Definition at line 2762 of file ao68000.v.


The documentation for this class was generated from the following file: