第五章 電路實作
5.6 實驗改善方向
本論文末將針對實作的誤差,提出幾點本實驗可以改善的方向:
1. 本論文實驗提出的無電流感測控制,僅靠二個 A/D 轉換電路感測輸入電壓及輸 出電壓,故此 A/D 轉換電路的可靠度顯得相當的重要,無論是感測出的大小或 是頻寬不足造成時間的誤差,將影響控制的效果。
2. 所提出的控制法中,補償開關及二極體不理想特性的壓降,是假設一定值,但 其壓降的大小會隨著溫度而有所改變,其補償的大小應有所不同,故實驗時半 導體元件散熱也會影響實驗的結果。
第六章 結論
總結以上實驗歸納,若是採用本系統有以下優點:
1. 本電路結構簡單,相較於傳統之電流控制迴路減少了一個控制迴圈,因此可降 低電路複雜造成的誤差。
2. 因取消了電流的控制迴路,減少了電流感測器,因此可以有相較於電流控制迴 路控制更便宜的電路費用。
3. 在本控制推導的方法,亦可用在頻率較高的範圍,且仍保持為理想弦波,使應 用範圍廣泛。
亦有缺點存在:
由於無感測輸入電流,因此我們必須得知電感的感值以及內阻值來加以補 償,其精確程度將與 PFC 效果呈正比。
參考文獻
[1] H. C. Chen,“Duty phase control for single-phase boost-type SMR,”IEEE Trans.
on Power Electron, vol. 23, no. 4,pp. 1927-1934, Jul. 2008.
[2] H. C. Chen,“Single-Loop Current Sensorless Control for Single-Phase Boost-Type SMR,”IEEE Trans. on Power Electron, vol. 24, no. 1, Jan. 2009.
[3] David M. Van de Sype; Koen De Gussemé; Alex P. M. Van den Bossche; Jan A.
Melkebeek, “Duty-Ratio Feedforward for Digitally Controlled Boost PFC Converters,” IEEE Trans on Industrial Electron, vol. 52, no. 1, pp 108-115, Feb.
2005.
[4] PSIM WEBSITE---http://www.powersimtech.com [5] Xilnx, Spartan-3 FPGA Family Data Sheet, 2008.
[6] Laszlo Huber; Yungtaek Jang; Milan M. Jovanovic, “Performance evaluation of bridgeless PFC boost rectifier,” IEEE Trans on Power Electron, vol 23, no. 3,May 2008.
[7] Yungtaek Jang; Milan M. Jovanovic, “A bridgeless PFC boost rectifier with optimized magnetic utilization,” IEEE Trans on Power Electron,vol. 24,no. 1,Jan 2009.
[8]“IEEE Recommended Practices and Requirements for Harmonic Control in Electrical Power Systems,” IEEE Std 519-1992
[9] Jian Sun; Min Chen; Kamiar J. Karimi, “Aircraft Power System Harmonics Involving Single-Phase PFC Converters,” IEEE Trans on Aerospace and Electron, vol. 44, no. 1, pp 217-226, Jan 2008.
[10] Jian Sun, “Analysis and Design of Single-Phase PFC Converters for Airborne Systems,” IEEE, 2003
[11] J. Rajagopalan, F. C. Lee, and P. Nora, “A general technique for derivation of
average current mode control laws for single-phase power-factor correction circuits without input voltage sensing,” IEEE Trans. on Power Electron., vol. 14,no. 4, pp.
663-672, Jul. 1999.
[12] K. Rustom, and I. Batarseh, “Recent Advances in Single-Stage Power Factor Correction,” IEEE International Conference 2003, pp. 1089-1095, vol. 12.
附錄一、程式控制方塊圖
ADC Ad_dip
vs_adin vs_ad ABS
sin_2 s2_final
+ +
vo_ref
ADC Ad_dip2
vo_adin vo_ad
+
-PI error_vo pi_out
<<1
module pfc(clk_40MHz,
da_clk_1,la_1,out_1,out_2,out_3,out_4, //for DA ad_clk_1,sfrm_1,convst_1,sdata_1,sdata_2,dipsw7, //for AD dipsw2,dipsw3,dipsw4, //for KI
dipsw5,dipsw6, //for KP
dipsw1, //for PI
//clk_40k_1,t, //Test Freq
duty,an,bn,startsw); //for tosw
input startsw;
input clk_40MHz;
//output clk_40k_1;
wire [15:0] divider_10M,divider_4M,divider_20k,divider_20M,divider_40k;
wire clk_10MHz,clk_4MHz,clk_4kHz,clk_40kHz;
output duty;
//assign clk_40k_1=clk_40kHz;
//output t;
//除頻器,因為是正緣觸發,本身就除頻為 20MH,再除以(divider+1) assign divider_10M=16'd1;
assign divider_4M=16'd4;
assign divider_20k=16'd999;
assign divider_20M=16'd0;
assign divider_40k=16'd499;
//4 組 DA,硬體電路上的 clk 和 la 腳位共用,故 la_2,la_3,la_4 都設為 la_1,clk 亦同 output da_clk_1,la_1,out_1,out_2,out_3,out_4;
wire la_2,la_3,la_4; //配合程式 DA Module 使用 wire da_clk_2,da_clk_3,da_clk_4; //配合程式 DA Module 使用
wire [15:0] in_1,in_2,in_3,in_4;
assign la_2=la_1;
assign la_3=la_1;
assign la_4=la_1;
assign da_clk_2=da_clk_1;
assign da_clk_3=da_clk_1;
assign da_clk_4=da_clk_1;
assign da_clk_1=clk_10MHz;
//2 組 AD,硬體電路上 sfrm,convst 和 clk 腳位共用
wire adsw; //模組內有設一個開關當 ad 的 switch
assign adsw=1'b0; //adsw=0 時,AD 程式才作用
input sfrm_1,sdata_1,sdata_2;
output ad_clk_1,convst_1;
wire [15:0] vo_adin,vs_adin; //原始 AD 硬體轉換出來的值 wire sfrm_2,ad_clk_2,convst_2; //因 sfrm,convst,adclk 硬體共用
wire [15:0] vo_ad,vs_ad; //修正後的值
assign sfrm_2=sfrm_1;
assign convst_2=convst_1;
assign ad_clk_2=ad_clk_1;
assign ad_clk_1=clk_4MHz;
//assign vo_ad=vo_adin+16'd1224; //補償 MAX121 的 offset,輸入 0V 時,AD 值 FB38=1224 //assign vs_ad=vs_adin+16'd788; //補償 MAX121 的 offset,輸入 0V 時,AD 值 FCEC=788 //誤差放大器
wire [15:0] vo_ref;
wire [15:0] error_vo;
assign vo_ref=16'd13474; //Vo=200V 時,vo_ref=200/92/5*32767=14247,
//Vo=200V 時,60Hz 設 13900 輸出會變低,但 THD 會變好 //Vo=200V 時,400Hz 200W 設 13774,400W 設 13474 波型較佳,600W 設 13574 //PI
input dipsw1; //為 PI 控制器的開關
input dipsw2,dipsw3,dipsw4; //用指撥開關的 3bit module 可以調 KI,KP 或 AD 值 input dipsw5,dipsw6,dipsw7; //同上
wire [15:0] kp;
wire [15:0] ki;
wire [15:0] pi_out;
assign kp=16'd50; //待調整 assign ki=16'd50; //待調整 //zcp
wire vs_plus; //當 Vin 為正時,vs_plus=0 wire [8:0] sin_counter;
//sin_table
wire [15:0] sin,cos,sin_2,cos_2;
wire [15:0] s2_final;
wire [15:0] s2_final2; //s2_final=s2*rL/WL
wire [15:0] s1s2_sum;
wire [15:0] s2_ratio;
wire [2:0] shift_bit1,shift_bit2;
assign s2_ratio=16'd1862; //s2_ratio=rL/WL=0.5/(2*pi*60*4.6*e-3)*32767=9447 //for 1L 60Hz
//s2_ratio=0.3/(2*pi*60*2.6*e-3)*32767=10028 for 2L 60Hz //s2_ratio=0.3/(2*pi*60*2.1*e-3)*32767=12417 for 2L 60Hz //s2_ratio=0.3/(2*pi*400*2.6*e-3)*32767=1504 for 2L 400Hz //s2_ratio=0.3/(2*pi*400*2.1*e-3)*32767=1862 for 2L 400Hz //s2_ratio=0.3/(2*pi*400*0.28*.e-3)*32767=13968 for 2L 400Hz //s2_ratio=0.3/(2*pi*400*0.88*e-3)*32767=4444 for 2L 400Hz assign s2_final2=~s2_final+16'd1; //配合減法器當加法器使用
assign shift_bit1=3'd1; //本查表為最大值 32767 當實際值 1,但 s1+s2>>1 出現, //故先又移 1 位除以 2
assign shift_bit2=3'd1; //同上 //vcont 查表,用查表當 Vcont
//wire [15:0] vcont_200v,vcont_40v,vcont_200v_dis,vcont_40v_dis;
//乘法器
wire [15:0] pi_vlhead,pi_vlhead_2;
wire [15:0] vs_abs_48,vs_abs_92;
wire [15:0] ratio_48_92;
wire [15:0] vf_out;
wire [15:0] v_cont_bef,v_cont_bef2,v_cont,v_cont2;
wire [15:0] vf_comp1,vf_comp2;
wire [2:0] shift_bit3,shift_bit4;
wire [15:0] vo_ratio;
wire duty;
assign vf_comp1=duty?16'd228:16'd199; //導通時壓降為 1.8+1.4,截止時壓降為 //1.4+1.4,vf=壓降/92/5*32767=202(截止) assign vf_comp2=~vf_comp1+16'd1; //配合減法器當加法器使用
assign ratio_48_92=16'd17096; //48/92*32767=17096 assign shift_bit3=3'd1;
assign shift_bit4=3'd2;
assign vo_ratio=16'd18841; //vo_ratio=2.3/4*32737=18841,2.3=92*5/200,需左移 2bit //若輸出為 40V,vo_ratio=92*5/40=11.5,則需左移 4bit,再乘上 11.5/16*32767=23551 //wire [8:0] sin_counter2;
//assign sin_counter2=sin_counter+9'd20;
//將 ZCP 偵測出的零交越點 shift 個值 wire [8:0] triangle_1,triangle_2,vcont;
//tosw
output an,bn;
clk_conversion clk_10M (clk_40MHz,divider_10M,clk_10MHz); //20MHz/(divider+1) clk_conversion clk_4M (clk_40MHz,divider_4M,clk_4MHz);
clk_conversion clk_20k (clk_40MHz,divider_20k,clk_20kHz);
clk_conversion clk_20M (clk_40MHz,divider_20M,clk_20MHz);
clk_conversion clk_40k (clk_40MHz,divider_40k,clk_40kHz);
ad ad_1(ad_clk_1,sdata_1,vo_adin,any1,convst_1,sfrm_1,adsw,t1);
//輸出 vo_ad 為 16bit 值,此 AD 硬體輸入,經取樣轉成 14bit 的值,
//但輸出傳回成 16bit,後面會用到
ad ad_2(ad_clk_2,sdata_2,vs_adin,any2,convst_2,sfrm_2,adsw,t2);
//輸出 vo_ad 為 16bit 值,此 AD 硬體輸入,經取樣轉成 14bit 的值,
//但輸出傳回成 16bit,後面會用到
ad_dip ad_regulator(clk_40kHz,vs_adin,vs_ad,dipsw7,dipsw6,dipsw5,vs_plus);
//判斷輸入電壓 vs 正負,為正時 vs_plus=0,利用指撥開關 5~7 補償一定的數值,調整後為 vs_ad ad_dip2 ad_regulator2(clk_40kHz,vo_adin,vo_ad,dipsw4,dipsw3,dipsw2);
//利用指撥開關 2~4 調整 vo_adin,調整後為 vo_ad
da da_1(la_1,clk_10MHz,out_1,in_1); //DA 出來只有正負 3V,再經過硬體電路放大 3.3 倍 da da_2(la_2,clk_10MHz,out_2,in_2);
da da_3(la_3,clk_10MHz,out_3,in_3);
da da_4(la_4,clk_10MHz,out_4,in_4);
subtraction voltage(vo_ref,vo_ad,error_vo);
//減法器為 vo_ref-vo_adin(或 vo_ad),同 16bit
pi voltage_controller(error_vo,pi_out,kp,ki,clk_40kHz,dipsw1);
//pi_out=VL_head,dipsw1 為 PI 的開關
zcp vin_zcp(clk_40kHz,vs_plus,vs_ad,sin_counter);
//零交越點偵測電路,為了要查表用,輸入為 vs_adin(或 vs_ad)
Hz_sin_table sin_list(sin,cos,sin_counter); //可得到 sin 和 cos 查表值 //60Hz 使用 sin_table,400Hz 使用 Hz_sin_table
shift_R s1(clk_40kHz,shift_bit1,cos,cos_2); //左 shift_bit1 數,最多移 4 位 shift_R s2(clk_40kHz,shift_bit2,sin,sin_2);
multiplication s2_multi(sin_2,s2_ratio,s2_final); //s2_final=sin_2*s2_ratio //1/60 sec 用 40kHz 取樣的話,會有 666 點
//s2_final=s2*rL/WL 值,s2_ratio 為 rL/WL=0.5/(2*pi*60*4.6*e-3)*32767 subtraction s1s2_sum_module(cos_2,s2_final2,s1s2_sum);
//s2_final2 為 s2_final 取負值,配合減法器取代加法器 //因此 s1s2_sum=cos_2+s2_final1
multiplication pi_compensate(pi_out,s1s2_sum,pi_vlhead);
//pi_vlhead=pi_out*s1s2_sum
shift_L pi_vlhead_shift(clk_40kHz,shift_bit3,pi_vlhead,pi_vlhead_2);
//pi_vlhead_2 為 pi_vlhead 左移(shift_bit3)位數
subtraction vf_compensate(pi_vlhead_2,vf_comp2,vf_out);
//vf_out 為 pi_vlhead_2+vf_comp1,vf+comp1 為導通或截止的補償值 absolute vs_voltage(clk_40kHz,vs_ad,vs_abs_48);
//vs_abs_48 為 vs 電壓降為 1/48 之 AD 值
multiplication vs_voltage_multi(vs_abs_48,ratio_48_92,vs_abs_92);
//vs_abs_92 為 vs 電壓轉為 1/92
//cont_table control(vcont_200v,vcont_40v,sin_counter);
//用查表當 vcont
subtraction v_cont_before(vs_abs_92,vf_out,v_cont_bef);
//v_cont_bef=vs_abs_92-vf_out
multiplication v_cont_multi(v_cont_bef,vo_ratio,v_cont_bef2);
//v_cont_bef2=v_cont_bef*vo_ratio
shift_L v_cont_shift(clk_40kHz,shift_bit4,v_cont_bef2,v_cont);
//v_cont=v_cont_bef2 左移(shift_bit4)位數 latch latch_1(v_cont,v_cont2,clk_40kHz);
triangle tr(v_cont2,duty,duty2,clk_40MHz,startsw,triangle_1,triangle_2,vcont);
// clk/1000 為三角波的頻率,vcont=v_cont 取 9bit tosw tosw1(duty,vs_plus,an,bn,startsw);
//startsw=0 時,開關訊號才會送出
//ki_dip ki_ki(clk_40kHz,ki,dipsw4,dipsw3,dipsw2);
//kp_dip kp_kp(clk_40kHz,kp,dipsw4,dipsw3,dipsw2);
//DA 要顯示的 assign in_1=vs_ad;
assign in_2=cos;
assign in_3=sin;
assign in_4=pi_vlhead;
endmodule
減法器(subtraction.v):
module subtraction(minuend,subtrahend,error);
input [15:0] minuend,subtrahend;
output reg [15:0] error;
reg [1:0] sign_bit;
always @(minuend,subtrahend) begin
sign_bit[1]=minuend[15];
sign_bit[0]=subtrahend[15];
case(sign_bit) 2'b00:
error=minuend-subtrahend;
2'b10:
begin
error=minuend-subtrahend;
if(error[15]==0)
error=16'b1000_0000_0000_0000;
end 2'b11:
error=minuend-subtrahend;
2'b01:
begin
error=minuend-subtrahend;
if(error[15]==1)
error=16'b0111_1111_1111_1111;
end endcase
end endmodule
乘法器(multiplication.v):
module multiplication (multiplicand,multiplier,answer);
input [15:0] multiplicand,multiplier;
output reg [15:0] answer;
reg [15:0] multiplicand_p,multiplier_p;
reg [31:0] answer_temp;
reg [1:0] sign_bit;
always @(multiplicand,multiplier) begin
if(multiplicand[15]) begin
if(multiplicand==16'b1000_0000_0000_0000) multiplicand_p=16'b0111_1111_1111_1111;
else
multiplicand_p=~multiplicand+16'd1;
end else
multiplicand_p=multiplicand;
if(multiplier[15]) begin
if(multiplier==16'b1000_0000_0000_0000) multiplier_p=16'b0111_1111_1111_1111;
else
multiplier_p=~multiplier+16'd1;
end else
multiplier_p=multiplier;
sign_bit[0] = multiplicand[15];
sign_bit[1] = multiplier[15];
answer_temp=(multiplicand_p*multiplier_p)<<1;
case (sign_bit) 2'b00:
answer=(answer_temp)>>16;
2'b01:
answer=(~answer_temp+1)>>16;
2'b10:
answer=(~answer_temp+1)>>16;
2'b11:
answer=(answer_temp)>>16;
endcase end
endmodule
PI 控制器(PI.v):
module pi(error,PI_out,kp,ki,clk,start);
input start,clk;
input [15:0] error,kp,ki;
output [15:0] PI_out;
reg [15:0] y;
reg [2:0] contr_win;
reg [15:0] kp_c;
reg [15:0] ki_c;
reg [31:0] multi_temp_kp;
reg [31:0] multi_temp_ki;
reg [31:0] sum_temp_kp;
reg [31:0] sum_temp_ki;
reg [15:0] Duty_PI;
reg buffer;
wire [15:0] PI_out;
always @(negedge clk) begin
if(!start) begin
if(!error[15]) y=error;
else begin
if(error==16'b1000_0000_0000_0000) y=16'b0111_1111_1111_1111;
else
y=~error+16'd1;
end if(ki[15]==1)
begin
if(ki==16'b1000_0000_0000_0000) ki_c=16'b0111_1111_1111_1111;
else
ki_c=~ki+16'd1;
end else
ki_c=ki;
if(kp[15]==1) begin
if(kp==16'b1000_0000_0000_0000) kp_c=16'b0111_1111_1111_1111;
else
kp_c=~kp+16'd1;
end else
kp_c=kp;
contr_win[0] = error[15];
contr_win[1] = ki[15];
contr_win[2] = kp[15];
multi_temp_kp=kp_c*y;
multi_temp_ki=ki_c*y;
multi_temp_kp=multi_temp_kp<<1;
multi_temp_ki=multi_temp_ki<<1;
case (contr_win)
3'b001:
begin
multi_temp_kp=~multi_temp_kp+1;
multi_temp_ki=~multi_temp_ki+1;
end 3'b011:
begin
multi_temp_kp=~multi_temp_kp+1;
multi_temp_ki=multi_temp_ki;
end 3'b010:
begin
multi_temp_kp=multi_temp_kp;
multi_temp_ki=~multi_temp_ki+1;
end 3'b000:
begin
multi_temp_kp=multi_temp_kp;
multi_temp_ki=multi_temp_ki;
end 3'b100:
begin
multi_temp_kp=~multi_temp_kp+1;
multi_temp_ki=multi_temp_ki;
end 3'b101:
begin
multi_temp_kp=multi_temp_kp;
multi_temp_ki=~multi_temp_ki+1;
end 3'b110:
begin
multi_temp_kp=~multi_temp_kp+1;
multi_temp_ki=~multi_temp_ki+1;
end 3'b111:
begin
multi_temp_kp=multi_temp_kp;
multi_temp_ki=multi_temp_ki;
end endcase
buffer=sum_temp_ki[31];
sum_temp_ki=sum_temp_ki+multi_temp_ki;
if((multi_temp_ki[31]==0) & (buffer==0)) begin
if (sum_temp_ki[31]==1)
sum_temp_ki=32'h7FFF_FFFF;
end
if ((multi_temp_ki[31]==1) & (buffer==1)) begin
if (sum_temp_ki[31]==0)
sum_temp_ki=32'h8000_0000;
end
sum_temp_kp=sum_temp_ki+multi_temp_kp;
if((sum_temp_ki[31]==0) & (multi_temp_kp[31]==0)) begin
if (sum_temp_kp[31]==1) sum_temp_kp=32'h7FFF_FFFF;
end
if ((sum_temp_ki[31]==1 )& (multi_temp_kp[31]==1)) begin
if (sum_temp_kp[31]==0) sum_temp_kp=32'h8000_0000;
end
Duty_PI[15:0]=sum_temp_kp[31:16];
end else
begin
Duty_PI=16'd0;
y=16'd0;
contr_win=3'd0;
kp_c=16'd0;
ki_c=16'd0;
multi_temp_kp=32'd0;
multi_temp_ki=32'd0;
sum_temp_kp=32'd0;
sum_temp_ki=32'd0;
buffer=1'd0;
end end
assign PI_out=Duty_PI;
endmodule
左移(shift_L.v)
module shift_L(clk,shift_bit,vin,vin_shift);
input clk;
input [15:0] vin;
input [2:0] shift_bit;
reg vin_sign=1'b0;
reg [15:0] vin_temp;
output reg [15:0] vin_shift=16'd0;
always@(posedge clk) begin
if(vin[15]==1'b0) begin
vin_temp=vin;
case(shift_bit) 3'd1:begin
if((vin_temp[14]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end 3'd2:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end
3'd3:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)||(vin_temp[12]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end 3'd4:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)||(vin_temp[12]==1)||(vin_temp[11]==
1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end
default: vin_temp=vin_temp;
endcase
vin_shift=vin_temp;
end
else //相當 vin 為負值時 begin
vin_temp=~vin+16'd1;
case(shift_bit) 3'd1:begin
if((vin_temp[14]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end 3'd2:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end 3'd3:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)||(vin_temp[12]==1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end 3'd4:begin
if((vin_temp[14]==1)||(vin_temp[13]==1)||(vin_temp[12]==1)||(vin_temp[11]==
1)) vin_temp=16'h7FFF;
else vin_temp=vin_temp<<shift_bit;
end
default: vin_temp=vin_temp;
endcase
vin_shift=~vin_temp+16'd1;
end end endmodule
右移(shift_L.v)
module shift_R(clk,shift_bit,vin,vin_shift);
input clk;
input [15:0] vin;
input [2:0] shift_bit;
reg vin_sign=1'b0;
output reg [15:0] vin_shift=16'd0;
always@(posedge clk) begin
vin_sign=vin[15];
if(vin[15]==1'b1) begin
vin_shift=vin>>shift_bit;
vin_shift[15]=1'b1;
end else
begin
vin_shift=vin>>shift_bit;
vin_shift[15]=1'b0;
end end
endmodule
零交越偵測(zcp.v)
module zcp(clk,vin_plus,vin,sin_counter);
input clk;
input [15:0] vin;
output reg [8:0] sin_counter=9'd1;
output reg vin_plus=1'b0;
reg check_zero=1'b0;
always @(posedge clk) begin
vin_plus=vin[15];
sin_counter=sin_counter+9'd1;
if(check_zero!=vin_plus) begin check_zero=vin_plus;
end endmodule
AD 程式(ad.v)
module ad(clk,in,out_1,out_2,convst,sfrm,start,test);
input clk,sfrm,in,start;
output reg convst=1,test=0;
output reg [15:0] out_1=16'd0,out_2=16'd0;
reg [6:0] counter_1=7'd1;
reg [3:0] counter_2=4'b1110,counter_3=4'd1;
reg [15:0] data=16'd0;
reg i=1'd0;
always @ (negedge clk) begin
if(!start) begin
if(counter_1==5'd0)
begin
convst=1'b0;
counter_1=counter_1+5'b0_0001;
end
else if(counter_1==5'd1) begin
convst=1'b1;
counter_1=counter_1+5'b0_0001;
end
else if(counter_1==5'd19) counter_1=5'b0_0000;
else
counter_1=counter_1+5'b0_0001;
if(sfrm==1'b0) begin if(i==1'd0)
begin
data[counter_2-4'b0001]=in;
counter_2=counter_2-4'b0001;
if(counter_2==4'd0) begin
i=1'd1;
if(counter_3==4'd1) begin
out_1=(data<<2);
counter_3=counter_3+4'd1;
test=1;
end
else if(counter_3==4'd2) begin
out_2=(data<<2);
counter_3=counter_3+4'd1;
test=0;
end
else if(counter_3==4'd5)
//改 counter_3 會改送出資料的頻率,原來 10 是 20K,改成 5 變 40K counter_3=4'd1;
else
counter_3=counter_3+4'd1;
end
counter_2=4'b1110;
end end
else begin
counter_2=4'b1110;
counter_3=4'd1;
out_1=16'd0;
out_2=16'd0;
data=16'd0;
i=1'd0;
counter_1=5'd0;
convst=1;
end end
endmodule
DA 程式(da.v)
module da(la,clk,out,in);
output reg out=0,la=0;
input clk;
reg [15:0] data_save=16'd0;
reg [4:0] counter=5'd15;
input [15:0] in;
always @(negedge clk) begin
if(counter==5'd15) begin
data_save=in;
out=data_save[counter];
la=0;
end
else if(counter==5'd7) begin
la=1;
out=data_save[counter];
end
else if(counter==5'd0) begin
out=data_save[counter];
counter=5'd16;
end else
out=data_save[counter];
counter=counter-1'd1;
end endmodule
除頻程式(clk_conversion.v)
module clk_conversion(clk_in,divider,clk_out);
input clk_in;
input [15:0] divider;
output reg clk_out=1'd0;
reg [15:0] counter=16'd0;
always@(posedge clk_in) begin
if(counter==divider) begin
counter=16'd0;
clk_out=~clk_out;
end else
counter=counter+1;
end endmodule
三角波兼比較器(triangle.v)
module
triangle(vcont_temp,PWM_1_out,PWM_2_out,clk,start,triangle_1,triangle_2,vcont);
output reg PWM_1_out=1'b0,PWM_2_out=1'b0;
output reg [8:0] triangle_1=9'd0,triangle_2=9'd500,vcont=9'd0;
input [15:0] vcont_temp;
reg i=1'b0;
input clk,start;
always @ (negedge clk) begin
//將 vcont 往上移 if(!start)
begin
if(vcont_temp[15]) //vcont_temp[15]=1 的時候,vcont=0 vcont=9'd0;
else begin
vcont[8:0]=vcont_temp[14:6];
if(vcont>9'd500)
vcont=9'd500; //(解析度) end
if(i==1'b1) begn
triangle_1=triangle_1-1'b1;
triangle_2=triangle_2+1'b1;
if(triangle_1==9'd0) i=1'b0;
end else
begin
triangle_1=triangle_1+1'b1;
triangle_2=triangle_2-1'b1;
if(triangle_1==9'd500) i=1'b1;
end
if(vcont>triangle_1) PWM_1_out=1'b0;
else
PWM_1_out=1'b1;
if(vcont<triangle_2) PWM_2_out=1'b0;
else
PWM_2_out=1'b1;
end
else begin
triangle_1=9'd0;
triangle_2=9'd500;
PWM_1_out=1'b0;
PWM_2_out=1'b0;
i=1'b0;
vcont=9'd0;
end end
endmodule
開關(tosw.v)
module tosw(duty,vin_plus,an,bn,startsw);
input duty,vin_plus,startsw;
output reg an=1'b0,bn=1'b0;
always @(duty) begin
if (startsw==1'b0) begin
if (vin_plus==1'b0) //輸入電壓正半週期 begin
if(duty==1'b1) begin
if(duty==1'b1) begin
end endmodule
絕對值(absolute.v)
module absolute(clk,vin,vin_abs);
input clk;
input [15:0] vin;
output reg [15:0] vin_abs=16'd0;
always @(clk) begin
if(vin[15]==1'b1) vin_abs=~vin+16'd1;
else vin_abs=vin;
end endmodu
指撥開關調整 AD 值(ad_dip.v)
module ad_dip(clk,adin,adout,pin_1,pin_2,pin_3,ad_plus);
input [15:0] adin;
input clk,pin_1,pin_2,pin_3,ad_plus;
output reg [15:0] adout;
reg [2:0] x=3'd0;
always @(negedge clk) begin
if(ad_plus==1'b0) begin
adout=adin+16'd788;
//t=1'b1;
x[0]=~pin_3;
case(x)
3'b000: adout=adin+16'd788;
//補償 MAX121 的 offset,輸入 0V 時,AD 值 FCEC=788, 3'b001: adout=adin+16'd1200;
3'b010: adout=adin+16'd1230;
3'b011: adout=adin+16'd1260;
3'b100: adout=adin+16'd1290;
3'b101: adout=adin+16'd1320;
3'b110: adout=adin+16'd1350;
3'b111: adout=adin+16'd1380;
endcase end
end endmodule
指撥開關調整 KI 值(ki_dip.v)
module ki_dip(clk,ki,pin_1,pin_2,pin_3);
input clk,pin_1,pin_2,pin_3;
output reg [15:0] ki;
reg [2:0] x=3'd0;
always @(negedge clk) begin
x[2]=~pin_1;
x[1]=~pin_2;
x[0]=~pin_3;
case(x)
3'b000: ki=16'd10;
3'b001: ki=16'd50;
3'b010: ki=16'd100;
3'b011: ki=16'd200;
3'b100: ki=16'd300;
3'b101: ki=16'd500;
3'b110: ki=16'd700;
3'b111: ki=16'd900;
endcase end
endmodule
指撥開關調整 KP 值(kp_dip.v)
module kp_dip(clk,kp,pin_1,pin_2,pin_3);
input clk,pin_1,pin_2,pin_3;
output reg [15:0] kp;
reg [2:0] x=3'd0;
always @(negedge clk) begin
x[2]=~pin_1;
x[1]=~pin_2;
x[0]=~pin_3;
case(x)
3'b000: kp=16'd50;
3'b001: kp=16'd100;
3'b010: kp=16'd150;
3'b011: kp=16'd200;
3'b100: kp=16'd300;
3'b101: kp=16'd500;
3'b110: kp=16'd800;
3'b111: kp=16'd1000;
endcase end
endmodule
60Hz 三角函數查表(sin_table.v)
module sin_table(sin,cos,sin_counter);
output reg [15:0] sin=16'd0,cos=16'd0;
input [8:0] sin_counter;
always @ (sin_counter) begin
case(sin_counter)
9'd 1 :begin sin=16'd 0 ; cos=16'd 32767 ; end endcase
end endmodule
400Hz 三角函數查表(Hz_sin_table.v)
module Hz_sin_table(sin,cos,sin_counter);
output reg [15:0] sin=16'd0,cos=16'd0;
input [8:0] sin_counter;
always @ (sin_counter) begin
always @ (sin_counter) begin