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 |