PSoC 3 で、 8-bit 加算器を作った [PSoC]
タイトルを見ても、何を言っているのか分からないでしょうが、そういう事です。 作成したのは、 カスタムロジックで作成した二つの8-bit入力と一つの8-bit出力を持つ「コ・プロセッサ」です。
Verilog で書いた加算器
まずは、 Verilog で記述しています。 テストに使ったのは、こんな回路図です。 二つの Control Reg の出力をカスタム部品 AdderUDB に入力し、その出力を Status Reg で受け取ることにより、 CPU とのインターフェイスを可能にします。 Verilog で記述すると、簡単にカスタム部品の入出力の関係を定義できます。
//`#start header` -- edit after this line, do not edit this line // ======================================== // // Copyright noritan.org, 2013 // All Rights Reserved // UNPUBLISHED, LICENSED SOFTWARE. // // CONFIDENTIAL AND PROPRIETARY INFORMATION // WHICH IS THE PROPERTY OF NORITAN.ORG. // // ======================================== `include "cypress.v" //`#end` -- edit above this line, do not edit this line // Generated on 04/27/2013 at 15:30 // Component: AdderUDB module AdderUDB ( output [7:0] s, input [7:0] a, input [7:0] b ); //`#start body` -- edit after this line, do not edit this line assign s = a + b; //`#end` -- edit above this line, do not edit this line endmodule //`#start footer` -- edit after this line, do not edit this line //`#end` -- edit above this line, do not edit this line
PSoC Creator の場合、 Symbol Wizard で入出力を指定してシンボルを作成し、 Generate Verilog でひな形を作成し、 assign ステートメントを追加するだけです。
以下のようなテストプログラムを作成しました。 入力のすべての組み合わせについて結果を検証し、すべて正しければ二つの LED が同時に点滅し、一つでも間違っていれば LED が交互に点滅します。
/* ======================================== * * Copyright noritan.org, 2013 * All Rights Reserved * UNPUBLISHED, LICENSED SOFTWARE. * * CONFIDENTIAL AND PROPRIETARY INFORMATION * WHICH IS THE PROPERTY OF NORITAN.ORG. * * ======================================== */ #include <device.h> uint16 rega; uint16 regb; uint8 sum; CYBIT good = 1; void main() { /* Place your initialization/startup code here (e.g. MyInst_Start()) */ /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */ for (rega = 0; rega < 256; rega++) { CR1_Write(rega); for (regb = 0; regb < 256; regb++) { CR2_Write(regb); sum = SR1_Read(); if (sum != ((uint8)rega + (uint8)regb)) { good = 0; } } } // Specify LED status as the inspection results. if (good) { LED3_Write(0); LED4_Write(0); } else { LED3_Write(0); LED4_Write(1); } // Blink LEDs for(;;) { LED3_Write(!LED3_Read()); LED4_Write(!LED4_Read()); CyDelay(200); } } /* [] END OF FILE */
データパスで書いた加算器
単純に Verilog で加算器を書くと、多くの Look Up Table (LUT) を使ってしまいます。 これでは、すぐに資源を喰いつくしてしまいます。 そこで、 LUT の代わりにデータパスを使用して加算器を実装します。
//`#start header` -- edit after this line, do not edit this line // ======================================== // // Copyright noritan.org, 2013 // All Rights Reserved // UNPUBLISHED, LICENSED SOFTWARE. // // CONFIDENTIAL AND PROPRIETARY INFORMATION // WHICH IS THE PROPERTY OF NORITAN.ORG. // // ======================================== `include "cypress.v" //`#end` -- edit above this line, do not edit this line // Generated on 04/27/2013 at 15:55 // Component: AdderDp module AdderDp ( input clock, input reset ); //`#start body` -- edit after this line, do not edit this line cy_psoc3_dp8 #(.cy_dpconfig_a( { `CS_ALU_OP__ADD, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC__ALU, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM0: Add A0 and D0 into A1*/ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM1: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM2: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM3: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM4: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM5: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM6: */ `CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0, `CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE, `CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA, `CS_CMP_SEL_CFGA, /*CFGRAM7: */ 8'hFF, 8'h00, /*CFG9: */ 8'hFF, 8'hFF, /*CFG11-10: */ `SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH, `SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL, `SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI, `SC_SI_A_DEFSI, /*CFG13-12: */ `SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0, 1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS, `SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN, `SC_FB_NOCHN, `SC_CMP1_NOCHN, `SC_CMP0_NOCHN, /*CFG15-14: */ 10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX, `SC_FIFO_LEVEL,`SC_FIFO__SYNC,`SC_EXTCRC_DSBL, `SC_WRK16CAT_DSBL /*CFG17-16: */ } )) dp( /* input */ .reset(reset), /* input */ .clk(clock), /* input [02:00] */ .cs_addr(3'b0), /* input */ .route_si(1'b0), /* input */ .route_ci(1'b0), /* input */ .f0_load(1'b0), /* input */ .f1_load(1'b0), /* input */ .d0_load(1'b0), /* input */ .d1_load(1'b0), /* output */ .ce0(), /* output */ .cl0(), /* output */ .z0(), /* output */ .ff0(), /* output */ .ce1(), /* output */ .cl1(), /* output */ .z1(), /* output */ .ff1(), /* output */ .ov_msb(), /* output */ .co_msb(), /* output */ .cmsb(), /* output */ .so(), /* output */ .f0_bus_stat(), /* output */ .f0_blk_stat(), /* output */ .f1_bus_stat(), /* output */ .f1_blk_stat() ); //`#end` -- edit above this line, do not edit this line endmodule //`#start footer` -- edit after this line, do not edit this line //`#end` -- edit above this line, do not edit this line
多くの記述があるように見えますが、中身はデータパスモジュール "cy_psoc3_dp8" のインスタンス "dp" だけです。 しかも、この記述は、 Datapath Config Tool で自動的に生成されたものを "reset" と "clk" の二つの入力を追加したものです。
データパスの設定のうち使用しているのは、 CFGRAM の一行目 "Reg0" だけです。 この設定では、 A0 と D0 の内容を足して A1 に格納する動作をクロックごとに繰り返します。 クロックには、 BUS_CLK を与えているため、 CPU と無関係に高速で加算動作を行います。 ただし、データを出し入れしているのは、 CPU なんですけどね。
以下のようなテストプログラムを作成しました。 変更箇所は、レジスタに対する読み書きだけです。
/* ======================================== * * Copyright noritan.org, 2013 * All Rights Reserved * UNPUBLISHED, LICENSED SOFTWARE. * * CONFIDENTIAL AND PROPRIETARY INFORMATION * WHICH IS THE PROPERTY OF NORITAN.ORG. * * ======================================== */ #include <device.h> uint16 rega; uint16 regb; uint8 sum; CYBIT good = 1; void main() { /* Place your initialization/startup code here (e.g. MyInst_Start()) */ /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */ for (rega = 0; rega < 256; rega++) { CY_SET_REG8(Adder_dp_u0__A0_REG, rega); for (regb = 0; regb < 256; regb++) { CY_SET_REG8(Adder_dp_u0__D0_REG, regb); sum = CY_GET_REG8(Adder_dp_u0__A1_REG); if (sum != ((uint8)rega + (uint8)regb)) { good = 0; } } } // Specify LED status as the inspection results. if (good) { LED3_Write(0); LED4_Write(0); } else { LED3_Write(0); LED4_Write(1); } // Blink LEDs for(;;) { LED3_Write(!LED3_Read()); LED4_Write(!LED4_Read()); CyDelay(200); } } /* [] END OF FILE */
カスタム部品を作るときには、専用の API を作成して、配置配線後の違いを吸収するのが定石です。 今回は、横着をして、 API を作成せずにレジスタのアドレスを直接与えて、アクセスをしています。 このレジスタアドレスは、 "cyfitter.h" というファイルの中で宣言されています。
消費資源の比較
加算器をデータパスで実現した動機は、消費する資源を減らすためです。 上で作成したシステムのそれぞれの消費資源を比較してみました。
- Verilog での実装
Resource Type : Used : Free : Max : % Used ============================================================ Digital domain clock dividers : 0 : 8 : 8 : 0.00% Analog domain clock dividers : 0 : 4 : 4 : 0.00% Pins : 5 : 67 : 72 : 6.94% UDB Macrocells : 8 : 184 : 192 : 4.17% UDB Unique Pterms : 16 : 368 : 384 : 4.17% UDB Total Pterms : 16 : : : UDB Datapath Cells : 0 : 24 : 24 : 0.00% UDB Status Cells : 1 : 23 : 24 : 4.17% Status Registers : 1 UDB Control Cells : 2 : 22 : 24 : 8.33% Control Registers : 2 DMA Channels : 0 : 24 : 24 : 0.00% Interrupts : 0 : 32 : 32 : 0.00%
- データパスでの実装
Resource Type : Used : Free : Max : % Used ============================================================ Digital domain clock dividers : 0 : 8 : 8 : 0.00% Analog domain clock dividers : 0 : 4 : 4 : 0.00% Pins : 5 : 67 : 72 : 6.94% UDB Macrocells : 0 : 192 : 192 : 0.00% UDB Unique Pterms : 0 : 384 : 384 : 0.00% UDB Datapath Cells : 1 : 23 : 24 : 4.17% UDB Status Cells : 0 : 24 : 24 : 0.00% UDB Control Cells : 0 : 24 : 24 : 0.00% DMA Channels : 0 : 24 : 24 : 0.00% Interrupts : 0 : 32 : 32 : 0.00%
このように、単純な Verilog での実装の場合はマクロセルを8個消費していましたが、データパスの実装の場合はデータパスがセル一個だけで済んでいます。 データパスは、多機能な ALU の機能とそれに付随するレジスタから構成されていますので、資源の消費を少なくできます。 とはいえ、データパスを使って、これだけの事しかできないのではさみしいので、次回は、もっと違う事をしてみましょう。
プロジェクトアーカイブ
この記事を書くために作成したプロジェクトは、このファイルの拡張子を ZIP に変更して展開すると再現できます。
関連書籍
シリーズ最強!PSoC 3ボード+デバッグ・ボード: あのPSoCが生まれ変わった!アナログもディジタルも一新 (トライアルシリーズ)
- 作者: 古平 晃洋
- 出版社/メーカー: CQ出版
- 発売日: 2012/10/23
- メディア: 単行本
コメント 0