Clark 变换是坐标转换,将输入的三相电流转换到两相直角坐标下电流,如下图为坐标表示方法。
根据坐标的投影我们可以得到
从而可以推知:
上述公式为最终代码中实现的计算公式。
在FPGA中实现时,由于FPGA中不擅长浮点数计算,因此代码中涉及的数据量全部用Q格式来表示。Q格式表示为:Qm.n,表示数据用m比特表示整数部分,n比特表示小数部分,共需要 m+n+1位来表示这个数据,多余的一位用作符合位。假设小数点在 n位的左边(从右向左数),从而确定小数的精度。例如Q15表示小数部分有15位,一个short 型数据,占2个字节,最高位是符号位,后面 15位是小数位,就假设小数点在第 15位左边,表示的范围是: -1<X<0.9999695 。浮点数据转化为 Q15,将数据乘以2^15;Q15数据转化为浮点数据,将数据除以 2^15。
应用Q15格式,使用Verilog代码编写的clark变换算法如下所示:
module clark_transform
#(parameter WIDTH = 16)
(
input clk,
input rst,
input start,
output out_valid,
input [WIDTH-1:0] i_w,
input [WIDTH-1:0] i_u,
output reg [WIDTH-1:0] i_alpha,
output reg [WIDTH-1:0] i_beta
);
localparam DELAY = 4;
reg start_delay = 0;
wire start_edge = !start_delay & start;
reg [DELAY:1] delay_cnt = 0;
always @(posedge clk or posedge rst)begin
if(rst) begin
start_delay <= 0;
delay_cnt <= 0;
end
else begin
start_delay <= start;
delay_cnt <= {delay_cnt[DELAY-1:1],start_edge};
end
end
reg signed [WIDTH-1:0] mult_din0;
wire signed [WIDTH-1:0] mult_din1 = -16'd18919;
wire signed [2*WIDTH-1:0] mult_dout;
multiplier mult (.clk(clk), .dataa(mult_din0), .datab(mult_din1), .dataout(mult_dout));
defparam inst_mult.WIDTH = WIDTH;
always @(posedge clk or posedge rst)
if(rst) begin
mult_din0 <= 0;
i_alpha <= 0;
i_beta <= 0;
end
else begin
if(start_edge)begin
i_alpha <= i_u;
mult_din0 <= i_u + {i_w[WIDTH-2:0],1'b0};
end
if(delay_cnt[3])
i_beta <= mult_dout[WIDTH-1+10:10];
end
assign out_valid = delay_cnt[DELAY];
endmodule
在代码中应用了Q15格式,存在常数1/sqrt(3)=0.57735026918962576450914878050196,
转化为Q格式的数据为0.57735026918962576450914878050196*2^15=18918。
在start信号的上升沿触发后,需要4个时钟周期才计算出正确的结果,因此在out_valid上升沿时,输出正确的Clark Transform结果。