第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])までソース をメールのこと
© Copyright 2024 ExpyDoc