PSoCのシフトアウトによる32bitデータパス入力
32bit shift out inputting on PSoC Datapath
前回のシフト挿入の逆を行えば、CPU(C言語)で代入した32bitレジスト値をデータコンポーネントから出力させることができます。
C言語で対象のアドレスに値を代入するとデータコンポーネントの「f0_bus_stat」がHighになります。厳密にはf0_bus_statの4bit全てがHighになっているかを調べる必要がありますが、レジスタへの代入は一度に行われているので、1bitだけのチェックでも問題ありません。
データパスの「A0 WR SRC=F0」によってA0レジスタに値をコピーしてから、左シフトを行うと、各データブロックのはみ出したビットは「cy_psoc3_dp」の「so」パラメータに記録されます。出力された4bitのうち、so[3]が最上位ビットなので、この値を32bit分読み取ると、C言語で入力した32bit値を全て読み取ることになります。
sreg_out.v
`include "cypress.v"
module sreg_out (
output isr,
output data,
input clock
);
localparam PG_IDLE = 3'b000;
localparam PG_COPY_F0 = 3'b001;
localparam PG_SHIFTOUT = 3'b010;
reg [2:0] pg_state;
reg [3:0] so_32;
reg [4:0] out_count;
reg f0_empty;
reg f0_not_empty;
always @(posedge clock)
begin
case(pg_state)
PG_IDLE:
begin
if(f0_not_empty)
begin
pg_state = PG_COPY_F0;
end
end
PG_COPY_F0:
begin
out_count = 5'd0;
pg_state = PG_SHIFTOUT;
end
PG_SHIFTOUT:
begin
out_count = out_count + 5'd1;
if(out_count == 5'd0)
begin
pg_state = PG_IDLE;
end
end
endcase
end
assign isr = f0_empty;
assign data = so_32[3];
cy_psoc3_dp32 #(
.cy_dpconfig_a({
}),
.cy_dpconfig_b({
}),
.cy_dpconfig_c({
}),
.cy_dpconfig_d({
}))dp(
/* input */ .clk(clock),
/* input [02:00] */ .cs_addr(pg_state),
/* 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 [03:00] */ .f0_bus_stat(f0_not_empty),
/* output [03:00] */ .f0_blk_stat(f0_empty),
/* output [03:00] */ .f1_bus_stat(),
/* output [03:00] */ .f1_blk_stat(),
/* output [03:00] */ .so(so_32)
);
endmodule
今回のサンプルでは、32bit分シフトが完了するごとに割り込み信号を発生させ、そのタイミングで新しい値を代入しています。
値がそのままピン出力の状態になるため、LEDの点滅期間が短くなる→長くなるが繰り返されます。
main.c
#include "project.h"
int ppos = 0;
const uint32_t patterns[] = {
0b11111111000000001111111100000000,
0b11110000111100001111000011110000,
0b11001100110011001100110011001100,
0b10101010101010101010101010101010,
0b11001100110011001100110011001100,
0b11110000111100001111000011110000,
};
CY_ISR(OnInterruptSO)
{
sreg_out_SetValue(patterns[ppos]);
ppos++;
if(ppos == 6) ppos = 0;
}
int main(void)
{
CyGlobalIntEnable;
so_isr_StartEx(OnInterruptSO);
for(;;)
{
}
}
2019/06/19