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
|