搜索
bottom↓
回复: 10

兑现:前两天扯过的CPLD实现PWM的一种方法

[复制链接]

出0入0汤圆

发表于 2005-10-19 21:34:12 | 显示全部楼层 |阅读模式
是用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 [7:0] DATA;                       /* 数据总线 */

  reg   DATA_switch;                      /* 数据总线方向控制寄存器 */

  input RD, WR, CE, RESET;                /* 输入控制端口(全部为低有效) */

  input A0;                               /* 寄存器地址操作选择: 0 - PWM控制寄存器; 1 - 预分频器  */

  

  reg [7:0] pwm_count;                    /* PWM计数器 */

  reg [7:0] prescale_count;               /* 预分频计数器 */

  reg [7:0] pwm_reg;                      /* 比较数据寄存器 */

  reg [7:0] DATA_out;                     /* 单片机数据总线输出驱动寄存器 */

  reg [7:0] 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

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2005-10-20 16:24:15 | 显示全部楼层
7064  能用吗?

出0入0汤圆

 楼主| 发表于 2005-10-21 00:09:02 | 显示全部楼层
不能。因为综合的结果是占用了76个逻辑单元,所以maxplus自动选用了7096。



如果去掉预分频部分,就能缩减到30多个逻辑单元,7064就可以用了。不过要注意:当您锁定管脚后,有可能布线路径不够了,导致实际占用的逻辑单元增加。

出0入0汤圆

发表于 2007-10-2 19:26:23 | 显示全部楼层
原来也想回复一个现在正在用的,但是由于是在其他工程里的,摘出来比较麻烦。看了AA55 的已经很完善了,思路基本一样,没必要拿来献丑了。只是想说一点。为什么还要用 EPM7000 论性能、价格、采购方便 MAXII 和 MAX3000系列都比他强的多。而且MAXII 逻辑容量要高出 MAX7000和MAX3000 系列很多。
我在北京中发买一次10片 EPM7128 40多RMB EPM3128 20RMB EPM240 15RMB 容量EPM7128=3128<240 而且240还有User Flash 可用

出0入0汤圆

发表于 2007-10-2 19:46:05 | 显示全部楼层
不好意思,没看时间是2005的帖子 不过那时候也应该是 MAX3000系列为主了

出0入0汤圆

发表于 2007-11-13 20:59:23 | 显示全部楼层
明天我帮你写一个

出0入0汤圆

发表于 2013-7-25 14:50:47 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2014-12-19 10:08:32 | 显示全部楼层
感谢lz,试着用ise综合了一下,居然要xc95144以上才能搞定,打算做个16位带分频的pwm(如82c54这样的芯片),资源耗得真多

出0入0汤圆

发表于 2014-12-22 22:46:39 | 显示全部楼层
不错,还是喜欢用FPGA产生PWM好用

出0入0汤圆

发表于 2015-1-17 10:29:48 | 显示全部楼层
不错的东东。赞一个

出0入0汤圆

发表于 2015-1-25 22:12:47 | 显示全部楼层
这是我现在用的PWM,交流一下。使用FPGA实现的。
  1. module pwm(clk,pwm0,pwm1,pwm2,pwm3,in_pwm_0,in_pwm_1,in_pwm_2,in_pwm_3,rst);

  2. input clk;                                                                                                     //50MHz时钟信号
  3. input rst;
  4. input [7:0]        in_pwm_0,in_pwm_1,in_pwm_2,in_pwm_3;        //PWM控制波输入
  5. output reg         pwm0,pwm1,pwm2,pwm3;                                             //PWM波输出

  6. reg[16:0] cnt,cnt50;     //计时变量
  7. reg[16:0] clk_50;

  8. always @(posedge clk or negedge rst)
  9. begin
  10. //---------------计数器计数-----------------------------
  11. if (!rst)
  12.         begin
  13.                 cnt=0;
  14.         end
  15. else if(cnt=='d999)
  16.     begin
  17.                 cnt<='b00000;
  18.                 clk_50=1;
  19.          end
  20.   else
  21.     begin
  22.                 cnt<=cnt+1;
  23.                 clk_50=0;
  24.          end
  25. end
  26. //--------------pwm的产生---------------
  27. always @(posedge clk_50 or negedge rst)
  28. begin
  29.         if (!rst)
  30.                 begin
  31.                         pwm0=0;
  32.                         pwm1=0;
  33.                         pwm2=0;
  34.                         pwm3=0;
  35.                 end
  36.         else
  37.                 begin
  38.                         if (cnt50==999)                 cnt50=0;        else        cnt50=cnt50+1;
  39.                         if (cnt50<in_pwm_0)        pwm0=1;        else        pwm0=0;
  40.                         if (cnt50<in_pwm_1)        pwm1=1;        else        pwm1=0;
  41.                         if (cnt50<in_pwm_2)        pwm2=1;        else        pwm2=0;
  42.                         if (cnt50<in_pwm_3)        pwm3=1;        else        pwm3=0;
  43.                 end
  44. end

  45. endmodule
复制代码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 23:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表