lynxeyedの電音鍵盤

MBDとFPGAと車載で使うデバイスの備忘録

PSoC3で指定回数分だけクロック送出

前回(PSoCでVerilog - Lynx-EyEDの電音鍵盤 新館)の関連記事になります。
PSoC3/5で指定回数分だけパルス出力したいと考えました。8bit長シフトレジスタでは、通常8クロックを送出してから、保存用レジスタにストアします。
しかし、データストリームが8の倍数では流れて来ない場合、あるいは最初の1bitだけ読んで、後は読み捨てても構わない場合などもあります。このような場合は、クロックを指定した回数だけ送出するような機構が欲しくなります。
CypressがあらかじめPSoC Creatorで準備しているパーツのみでこの仕組みを用意するのが難しそうでしたので、Verilog HDLで最低限の回路を用意します。

この論理回路の構成は以下のようなものです。
f:id:Lynx-EyED:20120929151852p:plain
【入力】

  • clk_i : クロック入力
  • count_i [7:0] : クロックを出力する回数(8bit)
  • enable_i : 出力開始フラグ

【出力】

  • clk_o : クロック出力
  • clk_end_o : 送出完了フラグ(1:完了)

.....たいした事無いのに大仰な(ry

Verilog記述はこのようなもの

//`#start header` -- edit after this line, do not edit this line
// ========================================
//
// Copyright YOUR COMPANY, THE YEAR
// All Rights Reserved
// UNPUBLISHED, LICENSED SOFTWARE.
//
// CONFIDENTIAL AND PROPRIETARY INFORMATION
// WHICH IS THE PROPERTY OF your company.
//
// ========================================
`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 09/29/2012 at 13:19
// Component: clock_counter
module clock_counter (
	output  clk_end_o,
	output  clk_o,
	input   clk_i,
	input  [7:0] count_i,
	input   enable_i
);

//`#start body` -- edit after this line, do not edit this line

reg  [7:0] counter_reg;
reg  clk_ena;

always @(negedge clk_i or posedge enable_i)begin
    if(enable_i)begin
	    counter_reg <= 0;
	    clk_ena <= 0;
        clk_end <= 0;
    end
    else if(counter_reg < count_i)begin
	    counter_reg <= counter_reg + 1'b1;
        clk_ena <= 1;
        clk_end <= 0;
    end else begin
        counter_reg <= counter_reg;
	    clk_ena <= 0;
        clk_end <= 1;
    end
end

assign clk_o = clk_ena ? clk_i : 1'b0;
assign clk_end_o = clk_end;
//assign clk_end_o = ~clk_ena;


//`#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

CPUから操作出来るように周辺回路を仕上げます。
f:id:Lynx-EyED:20120929152317p:plain

CPUのプログラミング手順としては
(1回目)

  1. クロック送出回数を count_i に代入
  2. enable_i → High
  3. enable_i → Low
  4. clk_end_o がHighになるまで待つ。

(2回目以降)

  1. clk_end_o がhighになるまで待つ
  2. (1回目の手順と同様)

となります。今回はCY8K-KIT-030を使う前提なので、フリーランクロック(Pin_2)をP6[2]、clk_oの出力(Pin_1)をP6[3]のオンボードLEDそれぞれに出力しています。また送出完了フラグclk_end_oは液晶に出力しています。クロックは1Hz周期なので目で確認できると思います。

コードは以下の通りです。5回クロックを送出します。送出が完了したら液晶表示は0x0→0x1に変化します。

/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include <device.h>
#include <stdio.h>

void read_lcd()
{
    uint8 status = 0u;
    char  strings[10];
    
    status = Status_Reg_1_Read();
    sprintf(strings, "%#x", status);
    LCD_Char_1_Position(0u, 0u);
    LCD_Char_1_PrintString(strings);
}

void main()
{
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    

    CyGlobalIntEnable;  /* Uncomment this line to enable global interrupts. */

    LCD_Char_1_Start();

    read_lcd();

    Count_Clock_1_Write(5u);	// 送出クロック数は5回
    Enable_Clock_1_Write(1u);	// enable_i = High 

    read_lcd();
  
    CyDelay(1000);			// 1秒待つ
    Enable_Clock_1_Write(0u);	// enable_i = Low
    

    // 0.1秒ごとにLCDの表示を更新
    for(;;)
    {
        read_lcd();
        CyDelay(100);
    }
}

/* [] END OF FILE */

クロック送出中
f:id:Lynx-EyED:20120929153856j:plain

送出完了
f:id:Lynx-EyED:20120929153928j:plain

※追記
リソース使用量ですが

------------------------------------------------------------
Technology mapping summary
------------------------------------------------------------

Resource Type                 : Used : Free :  Max :  % Used
============================================================
Digital domain clock dividers :    1 :    7 :    8 :  12.50%
Analog domain clock dividers  :    0 :    4 :    4 :   0.00%
Pins                          :   12 :   60 :   72 :  16.67%
Macrocells                    :   17 :  175 :  192 :   8.85%
Unique Pterms                 :   42 :  342 :  384 :  10.94%
Total Pterms                  :   45 :      :      : 
Datapath Cells                :    0 :   24 :   24 :   0.00%
Status Cells                  :    1 :   23 :   24 :   4.17%
             Status Registers :    1 
Control Cells                 :    2 :   22 :   24 :   8.33%
            Control Registers :    2 
DMA Channels                  :    0 :   24 :   24 :   0.00%
Interrupts                    :    0 :   32 :   32 :   0.00%
DSM Fixed Blocks              :    0 :    1 :    1 :   0.00%
VIDAC Fixed Blocks            :    0 :    4 :    4 :   0.00%
SC Fixed Blocks               :    0 :    4 :    4 :   0.00%
Comparator Fixed Blocks       :    0 :    4 :    4 :   0.00%
Opamp Fixed Blocks            :    0 :    4 :    4 :   0.00%
CapSense Buffers              :    0 :    2 :    2 :   0.00%
CAN Fixed Blocks              :    0 :    1 :    1 :   0.00%
Decimator Fixed Blocks        :    0 :    1 :    1 :   0.00%
I2C Fixed Blocks              :    0 :    1 :    1 :   0.00%
Timer Fixed Blocks            :    0 :    4 :    4 :   0.00%
DFB Fixed Blocks              :    0 :    1 :    1 :   0.00%
USB Fixed Blocks              :    0 :    1 :    1 :   0.00%
LCD Fixed Blocks              :    0 :    1 :    1 :   0.00%
EMIF Fixed Blocks             :    0 :    1 :    1 :   0.00%
LPF Fixed Blocks              :    0 :    2 :    2 :   0.00%

17マクロセルはずいぶんと豪勢なんじゃないのかと思いますが、(単純比較は出来ないものの)Xilinx CoolRunner XC2C256で同様の合成を行ったところ20マクロセルでした。
格別PSoC3のUDBの回路効率が悪いという事ではなさそうです。

おしまい。