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
|