PSoCのUDB 7bitカウンターを使用する

Use a PSoC UDB 7bit counter
 
PSoCのプログラマブル論理回路は非常にタイトで、32bitレジスタを複数用意して制御しようとしただけでも許容値を超えてしまいます。そのようなリソース量を節約するための方法として、PSoC内蔵の7bitカウンタモジュールを使うというのがあります。
count7.v
cy_psoc3_count7 #(.cy_period(7'b111), .cy_route_ld(1), .cy_route_en(1))
DataCounter(
    .clock(clock),
    .reset(1'b0),
    .load(count_reset),
    .enable(1'b1),
    .count(count),
    .tc(data_tc)
);
cy_period周期。カウンターの値がこの値を上回ると、値はリセットされます。
cy_route_ldloadパラメーターを使用するかどうか(1で使用)
cy_route_enenableパラメーターを使用するかどうか
clockカウンターを増やすために使用するクロック
resetカウンターのハードウェアをリセットする
loadカウンターの値をリセットする。resetと違い、カウンター値以外に影響はしない
enableカウンターの有効状態。cy_route_enが0ならこの値は無視される
countここで指定したレジスタに現在のカウンター値が格納される
tcカウンターが一巡した場合に、このレジスタに1が格納される


カウンターを有効にするに当たり注意しておきたいのが、Verilog内だけではなくC言語(CPU)からも有効にさせる命令を実行させなければいけない点です(英語ドキュメントには具体例が言及されているのですが、日本語ドキュメントでは抜け落ちています)。

カウンターを有効にするには「`$INSTANCE_NAME`_[関数で指定した名前]__CONTROL_AUX_CTL_REG」の6ビット目をHighにします。
api.h
#define `$INSTANCE_NAME`_enable()  *((reg8*)`$INSTANCE_NAME`_DataCounter__CONTROL_AUX_CTL_REG) |= 0x20
このサンプルでは8カウント目に一巡するとdata_tc値がHighになるので、そのたびにLEDが明滅を繰り返します。また、ボタンとcount_resetは直結されており、ボタンを押している間は常にカウンター値がリセットされるため、その間は全く動いていないように見えます。
sample.v
`include "cypress.v"

module ctr (
	output  result,
	input   clock,
    input   count_reset
);

wire data_tc;
reg [6:0] count; 
reg result_reg;
 
cy_psoc3_count7 #(.cy_period(7'b111),.cy_route_ld(1),.cy_route_en(1))
DataCounter(
    .clock(clock),
    .reset(1'b0),
    .load(count_reset),
    .enable(1'b1),
    .count(count),
    .tc(data_tc)
);
    
always @(posedge clock)
begin
    if(data_tc)
    begin
        result_reg = ~result_reg;
    end
end

assign result = result_reg;

endmodule
2019/06/28