📄 pwm_gen.v
字号:
module pwm_gen(clk_in,rst_in,add_in,wr_in,rd_in,data_in,data_out,pwm_out);
`define CLK_DIV 2:0
`define TIME_START 3
`define PWM0_EN 4
`define PWM1_EN 5
input clk_in,rst_in,wr_in,rd_in;
input [7:0] data_in;
input [15:0] add_in;
output [7:0] data_out;
output [1:0] pwm_out;
reg [15:0] cnt;
reg [15:0] cmpr0;
reg [15:0] cmpr0_sh;
reg [15:0] cmpr1;
reg [15:0] cmpr1_sh;
reg [15:0] cntpr;
reg [15:0] cntpr_sh;
reg [7:0] tccr;
reg cnt_link;
reg cmpr0_link;
reg cmpr1_link;
reg cntpr_link;
reg tccr_link;
wire cnt_link_rd;
wire cmpr0_link_rd;
wire cmpr1_link_rd;
wire cntpr_link_rd;
wire tccr_link_rd;
wire cnt_link_wr;
wire cmpr0_link_wr;
wire cmpr1_link_wr;
wire cntpr_link_wr;
wire tccr_link_wr;
always@(add_in)
begin
if(add_in[15:4]==11'b0001_0001_0011)
begin
case(add_in[3:1])
3'b000:
begin
tccr_link=1'b1;
cnt_link=1'b0;
cmpr0_link=1'b0;
cmpr1_link=1'b0;
cntpr_link=1'b0;
end
3'b001:
begin
tccr_link=1'b0;
cnt_link=1'b1;
cmpr0_link=1'b0;
cmpr1_link=1'b0;
cntpr_link=1'b0;
end
3'b010:
begin
tccr_link=1'b0;
cnt_link=1'b0;
cmpr0_link=1'b1;
cmpr1_link=1'b0;
cntpr_link=1'b0;
end
3'b011:
begin
tccr_link=1'b0;
cnt_link=1'b0;
cmpr0_link=1'b0;
cmpr1_link=1'b1;
cntpr_link=1'b0;
end
3'b100:
begin
tccr_link=1'b0;
cnt_link=1'b0;
cmpr0_link=1'b0;
cmpr1_link=1'b0;
cntpr_link=1'b1;
end
default:
begin
tccr_link=1'b0;
cnt_link=1'b0;
cmpr0_link=1'b0;
cmpr1_link=1'b0;
cntpr_link=1'b0;
end
endcase
end
else
begin
tccr_link=1'b0;
cnt_link=1'b0;
cmpr0_link=1'b0;
cmpr1_link=1'b0;
cntpr_link=1'b0;
end
end
assign tccr_link_rd=(!rd_in)?tccr_link:1'b0;
assign cmpr0_link_rd=(!rd_in)?cmpr0_link:1'b0;
assign cmpr1_link_rd=(!rd_in)?cmpr1_link:1'b0;
assign cntpr_link_rd=(!rd_in)?cntpr_link:1'b0;
assign cnt_link_rd=(!rd_in)?cnt_link:1'b0;
assign tccr_link_wr=(!wr_in)?tccr_link:1'b0;
assign cmpr0_link_wr=(!wr_in)?cmpr0_link:1'b0;
assign cmpr1_link_wr=(!wr_in)?cmpr1_link:1'b0;
assign cntpr_link_wr=(!wr_in)?cntpr_link:1'b0;
assign cnt_link_wr=(!wr_in)?cnt_link:1'b0;
assign data_out=tccr_link_rd?tccr:8'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
tccr<=8'b0;
end
else
if(tccr_link_wr)
tccr<=data_in;
else
tccr<=tccr;
end
assign data_out=cntpr_link_rd?(add_in[0]?cntpr[15:8]:cntpr[7:0]):8'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cntpr_sh<=16'b0;
end
else
if(cntpr_link_wr)
case(add_in[0])
1'b0:cntpr_sh[7:0]<=data_in;
1'b1:cntpr_sh[15:8]<=data_in;
endcase
else
cntpr_sh<=cntpr_sh;
end
assign data_out=cmpr0_link_rd?(add_in[0]?cmpr0[15:8]:cmpr0[7:0]):8'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cmpr0_sh<=16'b0;
end
else
if(cmpr0_link_wr)
case(add_in[0])
1'b0:cmpr0_sh[7:0]<=data_in;
1'b1:cmpr0_sh[15:8]<=data_in;
endcase
else
cmpr0_sh<=cmpr0_sh;
end
assign data_out=cmpr1_link_rd?(add_in[0]?cmpr1[15:8]:cmpr1[7:0]):8'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cmpr1_sh<=16'b0;
end
else
if(cmpr1_link_wr)
case(add_in[0])
1'b0:cmpr1_sh[7:0]<=data_in;
1'b1:cmpr1_sh[15:8]<=data_in;
endcase
else
cmpr1_sh<=cmpr1_sh;
end
`define NO_CLK 10'd0
`define CLK_DIV_1 10'd1
`define CLK_DIV_8 10'd7
`define CLK_DIV_64 10'd63
`define CLK_DIV_256 10'd255
`define CLK_DIV_1024 10'd1023
reg [9:0] div_reg;
reg [10:0] div_cnt;
wire div_carry;
assign div_carry=tccr[`TIME_START]?(div_cnt==div_reg?1'b1:1'b0):1'b0;
assign data_out=cnt_link_rd?(add_in[0]?cnt[15:8]:cnt[7:0]):8'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cnt<=16'b0;
end
else
if(cnt_link_wr)
case(add_in[0])
1'b0:cnt[7:0]<=data_in;
1'b1:cnt[15:8]<=data_in;
endcase
else
if(div_carry)
begin
case(prflag)
1'b0:cnt<=cnt+16'b1;
1'b1:cnt<=cnt-16'b1;
endcase
end
else
cnt<=cnt;
end
reg prflag;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
prflag<=1'b0;
cntpr<=16'h0000;
end
else
begin
if(cnt==16'h0000)
begin
prflag<=1'b0;
cntpr<=cntpr_sh;
end
else if(cnt==cntpr)
prflag<=1'b1;
else
prflag<=prflag;
end
end
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
div_cnt<=11'b0;
end
else
if(tccr[`TIME_START])
begin
if(div_carry)
div_cnt<=11'b0;
else
div_cnt<=div_cnt+11'b1;
end
end
always@(tccr)
begin
case(tccr[`CLK_DIV])
3'b000: div_reg<=`NO_CLK;
3'b001: div_reg<=`CLK_DIV_1;
3'b010: div_reg<=`CLK_DIV_8;
3'b011: div_reg<=`CLK_DIV_64;
3'b100: div_reg<=`CLK_DIV_256;
3'b101: div_reg<=`CLK_DIV_1024;
default:
div_reg<=`NO_CLK;
endcase
end
reg [1:0] pwm_reg;
assign pwm_out[0]=tccr[`PWM0_EN]?pwm_reg[0]:1'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
pwm_reg[0]<=1'b0;
end
else
if(div_carry)
if(cmpr0==16'b0)
pwm_reg[0]<=1'b0;
else
if(cmpr0==cntpr)
pwm_reg[0]<=1'b1;
else
if(cnt==cmpr0)
begin
pwm_reg[0]<=~pwm_reg[0];
end
else
begin
pwm_reg[0]<=pwm_reg[0];
end
else
pwm_reg[0]<=pwm_reg[0];
end
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cmpr0<=16'b0;
end
else
if(cnt==16'b0)
begin
cmpr0<=cmpr0_sh;
end
else
begin
cmpr0<=cmpr0;
end
end
assign pwm_out[1]=tccr[`PWM1_EN]?pwm_reg[1]:1'bz;
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
pwm_reg[1]<=1'b0;
end
else
if(div_carry)
if(cmpr1==16'b0)
pwm_reg[1]<=1'b0;
else
if(cmpr1==cntpr)
pwm_reg[1]<=1'b1;
else
if(cnt==cmpr1)
begin
pwm_reg[1]<=~pwm_reg[1];
end
else
begin
pwm_reg[1]<=pwm_reg[1];
end
else
pwm_reg[1]<=pwm_reg[1];
end
always@(posedge clk_in or negedge rst_in)
begin
if(!rst_in)
begin
cmpr1<=16'b0;
end
else
if(cnt==16'b0)
begin
cmpr1<=cmpr1_sh;
end
else
begin
cmpr1<=cmpr1;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -