計算機構成: トップダウンの解説

第5回 やや複雑な設計
慶應義塾大学 理工学部
天野
5回と6回の目的




前回のアキュムレータマシンでは、設計が簡単すぎて論理合成の最
適化がうまく働かない
今回はやや複雑な16ビットマイクロプロセッサPICOを導入して、やや
まともな論理合成のステップを習得
この授業はコンピュータアーキテクチャの授業ではないので、CPU自
体の理解はいい加減でも進めるようにしたい
情報工学科以外の方は、http://www.am.ics.keio.ac.jp/picobook
および「作りながら学ぶコンピュータアーキテクチャ:培風館」にPICO
についての情報がある。しかし、これらはSFLで書かれているのであ
まり参考にならないかも、、、


命令セットのドキュメントは、pico.pdfを参照のこと
cp –r ~hunga/vlsi07/5kai . でファイルを全部持ってくる
PICO-16の概要






シンプルなRISCアーキテクチャ
命令長16bit、データ長16bitの16bit-CPU
2 operand
レジスタ間接指定アドレッシング
Big Endian
レジスタはr0-r7まで8個
MSB
15 ……
8
LSB
7 6 ……
0
0
1
0
2
3
2
実装されている命令

レジスタ間演算命令



ADD r1,r2
他にSUB,AND,OR等(ALUの設計依存)
Immediate命令



ADDI r1,#10
Immediate部は8ビット、算術演算は符号拡張
LDHI r1,#10


10が上位8ビットに入る
分岐命令



BEQZ r1,飛び先
BNEZ r1,飛び先
飛び先は8ビット、PC相対指定
命令フォーマット

3種類の基本フォーマットを持つ
今回のverilog記述
ppico16_test.v テストベンチ
memory.v メモリ
ppico16.v CPU
合成対象
if_stage.v 命令フェッチ
rf_stage.v レジスタフェッチ
regfile.v レジスタファイル
ex_stagef.v (ex_stage.v) 実行(記述が違う2種類)
パイプライン化はしてある
Data Hazard, Control Hazardの除去はしてない
PICOのパイプライン構造
IF
RF
RFPC
WB
EX
a
2
regc
ALU
+
rega
IFPC
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
LDLI r1,#1
IF
RF
RFPC
EX
WB
a
2
regc
ALU
+
rega
IFPC
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
LDLI r2,#2
LDLI r1,#1
IF
RF
RFPC
EX
WB
a
2
regc
ALU
+
rega
IFPC
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
LDLI r3,#3
LDLI r2,#2
IF
RF
LDLI r1,#1
RFPC
EX
WB
a
2
ALU
+
rega
IFPC
1
regc
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
ADD r1,#2
LDLI r3,#3
IF
RF
LDLI r2,#2
RFPC
LDLI r1,#1
EX
WB
a
2
ALU
+
rega
IFPC
2
regc
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
1
ADD r2,r2
ADD r1,#2
IF
RF
LDLI r3,#3
RFPC
LDLI r2,#2
EX
WB
a
2
ALU
+
rega
IFPC
3
regc
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
2
ADD r2,r2
IF
RF
ADD r1,#2
RFPC
LDLI r3,#3
EX
WB
a
2
ALU
+
rega
IFPC
3
regc
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
3
ADD r2,r2
IF
RF
RFPC
ADD r1,#2
EX
WB
a
2
ALU
+
rega
IFPC
4
regc
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
3
ADD r2,r2
IF
RF
RFPC
EX
WB
a
2
regc
ALU
+
rega
IFPC
regb
c
b
IFIR
Instruction
Memory
Imm.
wadr
RFIR
Data
Memory
4
if_stage.v
module if_stage (clk,reset_,idata,pcset,badr,ifpc,ifir);
input
clk;
input
reset_;
input
[`BitBus] idata;
// Data from I-Cache
input
pcset;
// Branch Taken Signal
input
[`AddrBus] badr;
// Branch Addr
output
[`AddrBus] ifpc;
// PC ( IFstage output )
output
[`BitBus] ifir;
// IR ( IFstage output )
// Pipeline Registers
reg
[`AddrBus] pc;
reg
[`BitBus] ir;
// Regsiter assign directly.
assign ifpc = pc;
assign ifir = ir;
pcsetが1ならば分岐先ア
always @( posedge clk ) begin
if ( reset_ == `Enable_ ) begin
ドレスのセット
pc <= 16'b0;
ir <= 16‘b0; end
そうでなければ+2
else begin
ir
<=
idata;
(バイトアドレスなので)
if( pcset == `Enable )begin
pc
<=
badr; end
else begin
pc
<=
ifpc + 2; end
end
end
pico.h コードの定義
`define
`define
`define
`define
`define
`define
ROP
NOP
LDLI
LDHI
BEQZ
BNEZ
5'b00000
5'b00000
5'b11100
5'b11101
5'b01010
5'b01001
`define
`define
LD
ST
5'b01000
5'b01001
`define
`define
`define
`define
`define
`define
`define
`define
ThroughA
ThroughB
And
Or
ShiftLeft
ShiftRight
Add
Sub
3'b000
3'b001
3'b010
3'b011
3'b100
3'b101
3'b110
3'b111
rf_stage.v 1 入出力と定義
module rf_stage (clk,reset_,ifir,ifpc,rwe,c,rwadr,rfpc,rfir,a,b,imm);
input
clk;
input
reset_;
input
[`BitBus] ifir;
// IR ( IF stage output )
input
[`AddrBus] ifpc;
// PC ( IF state output )
input
rwe;
// Register Write Enable (c)
input
[`BitBus] c;
// Destination Data
input
[`RegAddrBus]
rwadr;
// Destination Register No
output
[`BitBus] rfpc;
// PC ( RFstage output )
output
[`BitBus] rfir;
// IR ( RFstage output )
output
[`BitBus] a;
// Source Data A
output
[`BitBus] b;
// Source Data B
output
[`BitBus] imm;
// Immediate Data
// Pipeline Registers
reg
[`BitBus] reg_a;
reg
[`BitBus] reg_b;
reg
[`BitBus] reg_im;
reg
[`BitBus] reg_ir;
reg
[`BitBus] reg_pc;
rf_stage.v 2 レジスタファイル
// Register File
wire
[`BitBus]
wire
[`BitBus]
dout1;
dout2;
// Register File Output for Source A (Rd)
// Register File Output for Source B (Rs)
regfile regfile (
.clk( clk ),
.reset_( reset_ ),
.r_addr1( ifir[`DecRd] ),
.r_addr2( ifir[`DecRs] ),
.w_addr( rwadr ),
.we( rwe ),
.w_data( c ),
.dout1( dout1 ),
.dout2( dout2 )
);
// See regfile.v
// Read Address for Source A
// Read Address for Source B
// Write Address
// Write Enable
// Write Data
rf_stage.v 3 出力とレジスタセット
// Outputs
assign
assign
assign
assign
assign
rfir = reg_ir;
rfpc = reg_pc;
a = reg_a;
b = reg_b;
imm = reg_im;
// intermidiate Wire
wire
[`BitBus]
wire
[`BitBus]
frega;
fregb;
// Source A Data
// Source B Data
always @( posedge clk ) begin
if ( reset_ == `Enable_ ) begin
reg_ir <= `NULL;
reg_pc <= `NULL;
reg_a <= `NULL;
reg_b <= `NULL; end
else begin
reg_ir
<= ifir;
reg_pc
<= ifpc;
reg_a <= dout1;
reg_b <= dout2;
reg_im
<= {{8{ifir[7]}},ifir[`DecImm]}; end
end
endmodule
regfile.v レジスタファイル本体
module regfile (clk,reset_,r_addr1,r_addr2,w_addr,we,w_data,dout1,dout2);
input
clk;
input
reset_;
input
[`RegAddrBus]
r_addr1;
// Source A Addr
input
[`RegAddrBus]
r_addr2;
// Source B Addr
input
[`RegAddrBus]
w_addr;
// Destination Addr ( Write Addr )
input
we;
// Write Enable
input
[`BitBus] w_data;
// Write Data
output
[`BitBus] dout1;
// Source A Data
output
[`BitBus] dout2;
// Source B Dataデータスルー機構
reg
[`BitBus] register
[`RegNum-1:0];
assign
dout1 =(r_addr1 == w_addr)&we ? w_data: register[r_addr1];
assign
dout2 = (r_addr2 == w_addr)&we ? w_data: register[r_addr2];
integer
i;
always @( posedge clk ) begin
for文の使い方に注意
if ( reset_ == `Enable_ ) begin
// Reset Regsters
for( i = 0; i < `RegNum; i = i + 1)begin
register[i] <= `BitWidth‘h0; end
end else begin
// Write Register
if( we == `Enable )begin
register[w_addr]
<=
w_data; end
end
end
endmodule
ex_stage.v 入出力
module ex_stage (clk,reset_,rfir,rfim,a,b,ddatain,rfpc,
c,ddataout,address,rwadr,dmoe,dmwe,rwe,pcset);
input
clk;
input
reset_;
input
[`BitBus] rfir;
// IR ( RF stage output )
input
[`BitBus] rfim;
// Immediate Data
input
[`BitBus] a;
// Source Data A
input
[`BitBus] b;
// Source Data B
input
[`BitBus] ddatain; // Read Data from D-Memory
input
[`BitBus] rfpc;
// PC (RF stage output )
output
[`BitBus] c;
// Operation Result
output
[`BitBus] ddataout; // Write Data to D-Memory
output
[`AddrBus]
address; // Address for D-Memory access
output
[`RegAddrBus]
rwadr;
// Destination Register No
output
dmoe;
// D-Memory Read Enable
output
dmwe;
// D-Memory Write Enable
output
rwe;
// Register Write Enable
output pcset;
// PC branch address set
ex_stage.v レジスタと簡単な論理部の接続
// Pipeline Registers
reg
reg
reg
reg
[`BitBus] reg_c;
[`RegAddrBus]
reg_rwe;
pcsetr;
reg_rwadr;
// Temporary Wire
wire
[`BitBus] aluout;
// ALU Output
wire
[`AluOpeBus]
aluope;
// ALU Operation
wire
[`BitBus] alu_ina, alu_inb;// Temporary Wire for ALU Source B
wire
[`BitBus] result;
// Temporary Wire for results
wire rwen;
wire pcsett;
// Output
assign rwadr = reg_rwadr;
assign rwe = reg_rwe;
assign c = reg_c;
assign pcset = pcsetr;
assign address
= ( rfir[`DecFunc] == `ST )? a : b;
assign ddataout = b;
assign dmwe = ( rfir[`DecOpe] == `ROP )&
(rfir[`DecFunc] == `ST) ? `Enable : `Disable;
assign dmoe = ( rfir[`DecOpe] == `ROP )&
(rfir[`DecFunc] == `LD) ? `Enable : `Disable;
ex_stage.v ALU
assign
aluout = alu ( alu_ina, alu_inb, aluope );
// ALU ( ThrohghA, ThrohghB, And, Or, ShiftLeft, ShiftRight, Add, Sub )
function
[`BitBus] alu;
input
[`BitBus] ina;
input
[`BitBus] inb;
input
[`AluOpeBus]
com;
begin
// Check "com" and operate
// Refer "pico.h"
case( com )
`ThroughA :
`ThroughB :
`And
:
`Or
:
`ShiftLeft :
`ShiftRight :
`Add
:
`Sub
:
endcase
end
endfunction
alu = ina;
alu = inb;
alu = ina & inb;
alu = ina | inb;
alu = ina << 1;
alu = ina >> 1;
alu = ina + inb;
alu = ina - inb;
ex_stage.v やや複雑な中間出力 案1
? : の利用
やや見にくい
// Intermediate wires
assign alu_ina = (rfir[`DecOpe] == `BNEZ) | (rfir[`DecOpe] == `BEQZ) ? rfpc: a;
assign alu_inb = // Sign extended immediate
( rfir[15:13] == 3'b001 ) | (rfir[`DecOpe] == `BEQZ) |
(rfir[`DecOpe] == `BNEZ) | (rfir[`DecOpe] == `LDLI) ? rfim:
// Sign unextended immediate
(rfir[`DecOpe] == `ROP) ? b:
(rfir[`DecOpe] == `LDHI) ? {rfir[`DecImm],8'b0}: {8'b0,rfir[`DecImm]};
// LDHI
assign aluope = // Braches
(rfir[`DecOpe] == `BEQZ) | (rfir[`DecOpe] == `BNEZ) ? `Add:
// LDLI, LDHI
(rfir[`DecOpe] == `LDLI) | (rfir[`DecOpe] == `LDHI) ? `ThroughB:
(rfir[`DecOpe] == `ROP) ? rfir[2:0]: rfir[13:11];
assign rwen = // Disable when Braches or ST
(rfir[`DecOpe] == `BEQZ) | (rfir[`DecOpe] == `BNEZ) |
((rfir[`DecOpe] == `ROP) & (rfir[`DecFunc] == `ST)) |
((rfir[`DecOpe] == `ROP) & (rfir[`DecFunc] == `NOP)) ? `Disable :
`Enable;
assign result = // when LD datain
((rfir[`DecOpe] == `ROP) & (rfir[`DecFunc] == `LD)) ? ddatain : aluout;
assign pcsett = ( rfir[`DecOpe] == `BEQZ )& (a==16'h0000) |
( rfir[`DecOpe] == `BNEZ )& (a!=16'h0000) ;
ex_stagef.v やや複雑な中間出力
案2
簡単なものは今ま
で通り
複雑な記述をfunction文で
functionの利用
置き換える
assign alu_ina = (rfir[`DecOpe] == `BNEZ) | (rfir[`DecOpe] == `BEQZ) ? rfpc: a;
function [`BitBus] aluinb;
input [`DecFunc] ope; input [`DecImm] imm; input [`BitBus] rfim, b;
if(ope[4:2]==3'b001) aluinb = rfim;
else
case(ope)
`BEQZ, `BNEZ, `LDLI : aluinb = rfim;
`ROP: aluinb = b;
`LDHI: aluinb = {imm,8'b0};
default: aluinb = {8'b0,imm};
endcase
endfunction
assign alu_inb = aluinb(rfir[`DecOpe],rfir[`DecImm],rfim,b);
function [`AluOpeBus] aluope;
input [`DecFunc] rfope;
input [`AluOpeBus] rffunc;
case (rfope)
`BEQZ, `BNEZ : aluope = `Add;
`LDLI, `LDHI : aluope = `ThroughB;
`ROP: aluope = rffunc;
default: aluope = rfope[`AluOpeBus];
endcase
endfunction
assign alu_ope = aluope(rfir[`DecOpe],rfir[`AluOpeBus]);
多出力を一つのfunctionで管
理
案3 やまさきfunction
// Outputs
assign
// etc
{ fdata, dmoe, dmwe, rwen, aluope, imm_e }
= alu_dec ( rfir, aluout, ddatain );
// Decode & Conrol Signal
function
[18:0] alu_dec;
input [`BitBus]
rfir;
input [`BitBus]
aluout;
input [`BitBus]
ddatain;
reg
reg
reg
reg
reg
reg
begin
//
//
[`BitBus]
dmoe;
dmwe;
rwen;
[`AluOpeBus]
imm_e;
fdata;
function文中では
wireが使えないの
でregを利用
しかしこれらは無論
レジスタではない
aluope;
1. Check ifir[`DecOpe]
2. If necessary, Check ifir[`DecFunc]
alu_dec = { fdata, dmoe, dmwe, rwen, aluope, imm_e };
end
endfunction
ex_stage.v レジスタのセット
always @ ( posedge clk or negedge reset_ ) begin
if ( reset_ == `Enable_ ) begin
reg_c <= `NULL;
reg_rwadr <= `NULL;
reg_rwe <= `Disable;
pcsetr <= `Disable;
end else begin
reg_c <= result;
reg_rwadr <= rfir[`DecRd];
reg_rwe
<= rwen;
pcsetr <= pcsett;
end
end
ppico.v 入出力と接続信号線
module ppico16 (clk,reset_,idata,ddatain,iaddr,daddr,ddataout,dmoe,dmwe);
input
clk;
input
reset_;
input
[`BitBus] idata;
// Instruction Data from I-Memory
input
[`BitBus] ddatain;
// Read Data from D-Memory
output
[`AddrBus] iaddr;
// Instruction Addr to I-Memory
output
[`AddrBus] daddr;
// Data Addr to D-Memory
output
[`BitBus] ddataout;
// Write Data to D-Memory
output
dmoe;
// D-Memory
Read Enable
output
dmwe;
// D-Memory
Write Enable
// IF & RF stage
wire
pcset;
// Branch Taken Signal
wire
[`AddrBus] ifpc;
// PC ( IFstage output )
wire
[`BitBus] ifir;
// IR ( IFstage output )
// RF stage
wire
rwe;
// Register Write Enable
wire
rwen;
// RWE for Next Clock
// RF & EX stage
wire
[`BitBus] a;
// Source Data A
wire
[`BitBus] b;
// Source Data B
wire
[`BitBus] c;
// Destination Data
wire
[`BitBus] imm;
// Immediate Data
wire
[`RegAddrBus]
rwadr;
// Destination Register No
wire
[`BitBus] fdata;
// Forward Data
wire
[`BitBus] rfir;
// IR ( RFstage output )
wire
[`AddrBus] rfpc;
// PC ( RFstage output )
ppico.v ステージ間接続
assign
iaddr = ifpc;
Memory
// Fetch Addr to Instruction
if_stage if_stage
(.clk( clk ),.reset_( reset_ ),.idata( idata ),.pcset( pcset ),.badr( c ),.ifpc( ifpc ),.ifi
r( ifir )
);
rf_stage rf_stage (.clk( clk ),.reset_( reset_ ),.ifir( ifir ),.ifpc( ifpc ),.rwe( rwe ),.c( c ),
.rwadr( rwadr ), .rfpc( rfpc ),.rfir( rfir ),.a( a ),.b( b ),.imm( imm )
);
ex_stage ex_stage (.clk( clk ),.reset_( reset_ ),.rfir( rfir ),.a( a ),.b( b ),.rfim( imm ),
.ddatain( ddatain ),.rfpc(rfpc), .c( c ),
.ddataout( ddataout ),.address( daddr ),.rwadr( rwadr ),.dmoe( dmoe ),
.dmwe( dmwe ),.rwe( rwe ),.pcset(pcset) );
test.prg
11100_001_00000001
11100_010_00000010
11100_011_00000011
00110_010_00000010
00000_010_010_00110
00000_000_00000000
00000_000_00000000
00000_000_00000000
00000_000_00000000
00000_000_00000000
// LDLI r1,#1
// LDLI r2,#2
// LDLI r3,#3
// ADDI R2,#2
// ADD R2,R2
// NOP
// NOP
// NOP
// NOP
// NOP
mult.prg
11100_000_00000000
00000_000_00000000
00000_001_000_01000
00000_000_00000000
00110_000_00000010
00000_000_00000000
00000_010_000_01000
11100_011_00000000
00000_000_00000000
00000_011_001_00110
00111_010_00000001
00000_000_00000000
01001_010_11111000
00000_000_00000000
00000_000_00000000
00000_000_00000000
01010_010_11111110
00000_000_00000000
00000_000_00000000
00000_000_00000000
// LDLI R0,#0
// NOP
// LD R1, (R0)
// NOP
// ADDI R0,#2
// NOP
// LD R2, (R0)
// LDLI R3,#0
// NOP
// ADD R3,R1
// SUBI R2,#1
// NOP
// BNEZ R2, -8
// NOP
// NOP
// NOP
// BEQZ R2, -2
// NOP
// NOP
// NOP
NOPはパイプラインハ
ザードを防止するため
合成と結果の確認

signal_visionでクロックを10nsにセットして
合成し、ex_stagef.vとex_stage.vで差を見
よう
演習

LDHI2 rd,#X
rdの上位8ビットにXをセットし、下位8ビットは
rdのままにする命令

ppico16.vに付け加えシミュレーションし
て結果を確認の上、天野
([email protected])までソース
をメールのこと