3.レジスタ
H8のレジスタ構成です。
アクセスとしては、8ビットレジスタ16本(R0L-R7H)、16ビットレジスタ16本(R0-R7,E0-E7)、32ビットレジスタ(ER0-ER7)8本としてアクセスできます。ER7は、スタックポインタとして暗黙的に使用されます。
レジスタは、その名の通り、記憶素子です。素直に仕様を記述して行きます。1パックとしてreg_file モジュールとして記述します。ここでやや面倒なのは、BYTE_ACCESS,WORD_ACCESS,LONG_ACCESSがあることです。それぞれのアクセスに対し、WriteやReadを適切にアレンジしなくてはいけません。
入力1ポート(32ビット、ALUの出力または、Effective_Addressの出力選択)、出力3ポート(LEFT,RIGHT32ビットx2 ALU用、EA用)として記述します。
レジスタのアドレス指定(Register Field)は、インストラクションレジスタ(32ビット、(64ビットを一回でフェッチするがその上位32ビット)中の4ビット)で指定されますが、命令毎にその位置が違うので、MUXで位置を選択します。一般に、これらの制御線がマイクロコードになります。
`include "define.h" //Jun.3.2004 add 3rd output port module reg_file(clock,sync_reset,irhword,left_address_sel,right_address_sel,write_address_sel, access_mode,reg_write,alu_out,ea,reg_left_out,reg_right_out,insel,left_address_out,ea_reg_address); input clock,sync_reset; input [31:0] irhword; input [1:0] left_address_sel,right_address_sel; input [2:0] write_address_sel; input [1:0] access_mode; input reg_write; input insel; input [31:0] alu_out; input [23:0] ea; output [31:0] reg_left_out,reg_right_out; // output data file output [31:0] left_address_out;//For EA Address input [2:0] ea_reg_address;//May.30.2004 wire write0,write1,write2,write3,write4,write5,write6,write7; wire high_access; wire [31:0] ER0,ER1,ER2,ER3,ER4,ER5,ER6,ER7,Y0,Y1,Y2; wire [3:0] input_address,reg_out0_address,reg_out1_address; wire [3:0] IR0H=irhword[31:28]; wire [3:0] IR0L=irhword[27:24]; wire [3:0] IR1H=irhword[23:20]; wire [3:0] IR1L=irhword[19:16]; wire [3:0] IR3H=irhword[7:4]; wire [3:0] IR3L=irhword[3:0]; wire [31:0] i32=insel==`ALU_OUT_SEL ? alu_out:{8'h00, ea}; reg32 reg32_0(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER0),.write(write0),.high_access(high_access)); reg32 reg32_1(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER1),.write(write1),.high_access(high_access)); reg32 reg32_2(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER2),.write(write2),.high_access(high_access)); reg32 reg32_3(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER3),.write(write3),.high_access(high_access)); reg32 reg32_4(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER4),.write(write4),.high_access(high_access)); reg32 reg32_5(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER5),.write(write5),.high_access(high_access)); reg32 reg32_6(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER6),.write(write6),.high_access(high_access)); reg32 reg32_7(.clock(clock),.sync_reset(sync_reset),.access_bytes(access_mode),.i32(i32),.R32(ER7),.write(write7),.high_access(high_access)); MPX_8 mpx_8_0(reg_out0_address[2:0],ER0,ER1,ER2,ER3,ER4,ER5,ER6,ER7,Y0); MPX_8 mpx_8_1(reg_out1_address[2:0],ER0,ER1,ER2,ER3,ER4,ER5,ER6,ER7,Y1); MPX_8 mpx_8_2(ea_reg_address,ER0,ER1,ER2,ER3,ER4,ER5,ER6,ER7,Y2); assign reg_out0_address=left_address_sel==`IR1L_SEL ? IR1L : left_address_sel==`IR1H_SEL? IR1H : left_address_sel==`IR3H_SEL? IR3H: 07;// SP=07 assign reg_out1_address=right_address_sel==`IR1L_SEL ? IR1L : right_address_sel==`IR0L_SEL? IR0L : right_address_sel==2 ? IR3L : 07;//SP=07 assign input_address=write_address_sel==`IR1L_SEL ? IR1L: write_address_sel==`IR0L_SEL ? IR0L: write_address_sel==`IR1H_SEL_W ? IR1H: write_address_sel==2 ? IR3L: write_address_sel==3 ? IR3H: 07;//SP=07 assign left_address_out=Y2; assign reg_left_out=access_mode == `LONG_ACCESS ? Y0 : access_mode == `WORD_ACCESS ? (reg_out0_address[3] ==1'b1 ? {16'h0000,Y0[31:16]} : {16'h0000,Y0[15:0]} ) : reg_out0_address[3] ==1'b0 ? {24'h00_0000,Y0[15:8]} : {24'h00_0000,Y0[7:0]} ;//Note: register field mapping R0H =>0000, R0L=>1000 assign reg_right_out=access_mode == `LONG_ACCESS ? Y1 : access_mode == `WORD_ACCESS ? (reg_out1_address[3] ==1'b1 ? {16'h0000,Y1[31:16]} : {16'h0000,Y1[15:0]} ) : reg_out1_address[3] ==1'b0 ? {24'h00_0000,Y1[15:8]} : {24'h00_0000,Y1[7:0]} ; //Note: register field mapping R0H =>0000, R0L=>1000 assign high_access = !input_address[3]; assign write0 = reg_write && input_address[2:0]==3'b000; assign write1 = reg_write && input_address[2:0]==3'b001; assign write2 = reg_write && input_address[2:0]==3'b010; assign write3 = reg_write && input_address[2:0]==3'b011; assign write4 = reg_write && input_address[2:0]==3'b100; assign write5 = reg_write && input_address[2:0]==3'b101; assign write6 = reg_write && input_address[2:0]==3'b110; assign write7 = reg_write && input_address[2:0]==3'b111; endmodule module MPX_8 (address,R0,R1,R2,R3,R4,R5,R6,R7,Y); input [2:0] address; input [31:0] R0,R1,R2,R3,R4,R5,R6,R7 ; output [31:0] Y; wire [31:0] R0,R1,R2,R3,R4,R5,R6,R7 ; reg [31:0] Y; always @(address or R0 or R1 or R2 or R3 or R4 or R5 or R6 or R7 ) case(address) 3'b000: Y=R0; 3'b001: Y=R1; 3'b010: Y=R2; 3'b011: Y=R3; 3'b100: Y=R4; 3'b101: Y=R5; 3'b110: Y=R6; 3'b111: Y=R7; endcase endmodule module reg32(clock,sync_reset,access_bytes,i32,R32,write,high_access); input sync_reset; input clock,high_access; input [1:0] access_bytes; input [31:0] i32; output [31:0] R32; reg [31:0] R32; input write; always @ (posedge clock) begin if (sync_reset) R32 <=32'h0000_0000; else if (write && access_bytes==`LONG_ACCESS) R32<=i32; else if (write && access_bytes==`WORD_ACCESS && high_access) R32[15:0] <=i32[15:0];//Note 0000=>R0 1000=>E0 else if (write && access_bytes==`WORD_ACCESS && !high_access) R32[31:16] <=i32[15:0]; else if (write && access_bytes==`BYTE_ACCESS && !high_access) R32[7:0] <=i32[7:0];//Note Reg file Mapping 1000=>R0L else if (write && access_bytes==`BYTE_ACCESS && high_access) R32[15:8] <=i32[7:0];//Note 0000=>R0H end endmodule |