兑现:前两天扯过的CPLD实现PWM的一种方法
是用verilog实现的。能实现8位PWM,有8位预分频,能够随机读写pPWM设定值和分频系数,最高使用频率为20MHz,可以产生305Hz到78KHz的PWM波形 。
我是用MAXPLUS仿真测试的。注意:MAXPLUS自动选定的是MAX7096,但是在工程中不能选用MAX7096
。原因是具体实现上,管脚分配不同于MAXPLUS自动分配的管脚,具体绑定到管脚时候,要损失一些路径、导致实际占用逻辑单元增加;2、MAX7096比较难购买,MAX7128更容易采购到。
/* 有预分频功能的8位PWM可读写模块 */
module chinesemode( CLOCK, DATA, A0, RD, WR, CE, RESET, PWM_OUT );
input CLOCK; /* 系统时钟 */
inout DATA; /* 数据总线 */
reg DATA_switch; /* 数据总线方向控制寄存器 */
input RD, WR, CE, RESET; /* 输入控制端口(全部为低有效) */
input A0; /* 寄存器地址操作选择: 0 - PWM控制寄存器; 1 - 预分频器*/
reg pwm_count; /* PWM计数器 */
reg prescale_count; /* 预分频计数器 */
reg pwm_reg; /* 比较数据寄存器 */
reg DATA_out; /* 单片机数据总线输出驱动寄存器 */
reg prescale_reg; /* 预分频寄存器 */
output PWM_OUT; /* PWM输出端口 */
reg pwm_status; /* PWM输出状态 */
assign DATA = ( DATA_switch == 1'b0 )? DATA_out : 8'hzz; /* 数据总线控制(低为输出) */
assign PWM_OUT = ( pwm_status == 1'b1 )? 1'b1 : 1'b0; /* PWM输出驱动 */
always@( posedge CLOCK or negedge RESET ) /* 计数器块:对CLOCK上升沿敏感 */
begin
if( RESET == 1'b0 ) /* 如果复位,清除计数器内容 */
begin
pwm_count = 8'h00;
prescale_count = 8'h00;
end
else
begin
if( WR == 1'b0 )
begin
if( A0 == 0 )
begin
pwm_count = 8'h00; /* 如果写入新的PWM控制数据,清除计数器 */
end
else
begin
pwm_count = 8'h00;
prescale_count = 8'h00; /* 如果写入新的分频系数数据,清除预分频计数器和计数器 */
end
end
else
begin
if( prescale_count == prescale_reg )
begin
pwm_count = pwm_count + 1; /* 行波计数。对这种计数器进行比较、译码特别容易产生竞争冒险,所以要采用同步逻辑避免 */
prescale_count = 0;
end
else
begin
prescale_count = prescale_count + 1;
end
end
end
end
always@( negedge CLOCK or negedge RESET ) /* 单片机读写数据块。注意:这对CLOCK下降沿敏感,不在逐级翻转计数器的上升沿做比较,消除了竞争冒险 */
begin
if( RESET == 1'b0 ) /* 如果复位,清除寄存器内容 */
begin
DATA_switch <= 1'b1;
pwm_reg <= 8'h00;
prescale_reg <= 8'h00;
pwm_status <= 1'b0;
end
else
begin
if( pwm_count > pwm_reg ) /* PWM比较过程 */
begin
pwm_status <= 1'b1;
end
else
begin
pwm_status <= 1'b0;
end
if (CE == 1'b0 ) /* 如果芯片使能有效,执行读写操作 */
begin
if( WR == 1'b0 )
begin
DATA_switch <= 1'b1;
if( A0 == 0 )
begin
pwm_reg <= DATA; /* PWM控制数据写入PWM寄存器 */
end
else
begin
pwm_reg <= DATA; /* PWM控制数据写入预分频寄存器 */
end
end
else
begin
if( RD == 1'b0 )
begin
DATA_switch <= 1'b0;
if( A0 == 0 )
begin
DATA_out <= pwm_reg; /* PWM寄存器内容传送到总线(读出) */
end
else
begin
DATA_out <= prescale_reg; /* 预分频寄存器内容传送到总线(读出) */
end
end
else
begin
DATA_switch <= 1'b1;
end
end
end
else
begin
DATA_switch <= 1'b1;
end
end
end
endmodule 7064能用吗? 不能。因为综合的结果是占用了76个逻辑单元,所以maxplus自动选用了7096。
如果去掉预分频部分,就能缩减到30多个逻辑单元,7064就可以用了。不过要注意:当您锁定管脚后,有可能布线路径不够了,导致实际占用的逻辑单元增加。 原来也想回复一个现在正在用的,但是由于是在其他工程里的,摘出来比较麻烦。看了AA55 的已经很完善了,思路基本一样,没必要拿来献丑了。只是想说一点。为什么还要用 EPM7000 论性能、价格、采购方便 MAXII 和 MAX3000系列都比他强的多。而且MAXII 逻辑容量要高出 MAX7000和MAX3000 系列很多。
我在北京中发买一次10片 EPM7128 40多RMB EPM3128 20RMB EPM240 15RMB 容量EPM7128=3128<240 而且240还有User Flash 可用 不好意思,没看时间是2005的帖子 不过那时候也应该是 MAX3000系列为主了 明天我帮你写一个 学习一下 感谢lz,试着用ise综合了一下,居然要xc95144以上才能搞定,打算做个16位带分频的pwm(如82c54这样的芯片),资源耗得真多 不错,还是喜欢用FPGA产生PWM好用 不错的东东。赞一个 这是我现在用的PWM,交流一下。使用FPGA实现的。
module pwm(clk,pwm0,pwm1,pwm2,pwm3,in_pwm_0,in_pwm_1,in_pwm_2,in_pwm_3,rst);
input clk; //50MHz时钟信号
input rst;
input in_pwm_0,in_pwm_1,in_pwm_2,in_pwm_3; //PWM控制波输入
output reg pwm0,pwm1,pwm2,pwm3; //PWM波输出
reg cnt,cnt50; //计时变量
reg clk_50;
always @(posedge clk or negedge rst)
begin
//---------------计数器计数-----------------------------
if (!rst)
begin
cnt=0;
end
else if(cnt=='d999)
begin
cnt<='b00000;
clk_50=1;
end
else
begin
cnt<=cnt+1;
clk_50=0;
end
end
//--------------pwm的产生---------------
always @(posedge clk_50 or negedge rst)
begin
if (!rst)
begin
pwm0=0;
pwm1=0;
pwm2=0;
pwm3=0;
end
else
begin
if (cnt50==999) cnt50=0; else cnt50=cnt50+1;
if (cnt50<in_pwm_0) pwm0=1; else pwm0=0;
if (cnt50<in_pwm_1) pwm1=1; else pwm1=0;
if (cnt50<in_pwm_2) pwm2=1; else pwm2=0;
if (cnt50<in_pwm_3) pwm3=1; else pwm3=0;
end
end
endmodule
页:
[1]