自己写的分频程序,贴出来!

[复制链接]
2392|13
 楼主| jlgcumt 发表于 2012-11-26 09:41 | 显示全部楼层 |阅读模式
任意整数分频,50%占空比!
  1. module PWMDIV(clk_in,clk_out,clk_div,clk_dutycycle,rst);

  2. input  clk_in;    //  输入时钟频率
  3. output clk_out;        //  分频后的时钟输出
  4. input [15:0] clk_div;
  5. input [15:0] clk_dutycycle;
  6. input  rst;        //  异步复位信号

  7. reg [23:0] cnt_p;  // 上升沿脉冲计数
  8. reg clk_p;
  9. reg [23:0] cnt_n;  // 下降沿脉冲计数
  10. reg [23:0] cnt;
  11. reg clk_n;
  12. reg clk_even;
  13. wire clk_odd;

  14. reg [15:0] clk_div_r;
  15. reg [15:0] clk_dutycycle_r;
  16. reg [15:0] pulse_num_r;
  17. reg [15:0] cnt_pulse;

  18. always @(posedge clk_in or negedge rst)
  19. begin
  20.         if(!rst)
  21.                 cnt_p <= 0;       
  22.         else if((clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
  23.                 cnt_p <= 0;
  24.         else if(cnt_p == clk_div[15:0] -1)
  25.            cnt_p <= 0;
  26.         else
  27.                 cnt_p <= cnt_p+1;
  28. end


  29. always @(posedge clk_in or negedge rst)
  30. begin
  31.         if(!rst)
  32.                 clk_p <= 0;
  33.         else if( (clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
  34.                 clk_p <= 0;
  35.         else if(cnt_p < (clk_div[15:0]-1)/2)
  36.                 clk_p <= 0;
  37.         else if(cnt_p == (clk_div[15:0]-1)/2)
  38.                 clk_p <= ~clk_p;
  39.         else if(cnt_p == clk_div[15:0] -1)               
  40.                         clk_p <= ~clk_p;                       
  41. end


  42. always @(negedge clk_in or negedge rst)
  43. begin
  44.         if(!rst)
  45.                 cnt_n <= 0;
  46.         else if((clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
  47.                 cnt_n <= 0;
  48.         else if(cnt_n == clk_div[15:0] -1)
  49.                 cnt_n <= 0;
  50.         else
  51.                 cnt_n <= cnt_n+1;
  52. end

  53. always @(negedge clk_in or negedge rst)
  54. begin
  55.         if( !rst )
  56.                 clk_n <= 0;
  57.         else if( (clk_div[15:0]%2 == 0)|| (clk_div[15:0] == 0) )
  58.                 clk_n <= 0;
  59.         else if(cnt_n < (clk_div[15:0]-1)/2)
  60.                 clk_n <= 0;
  61.         else if(cnt_n == (clk_div[15:0]-1)/2)           
  62.                 clk_n <= ~clk_n;
  63.         else if(cnt_n == clk_div[15:0]-1)
  64.                 clk_n <= ~clk_n;
  65. end

  66. // 偶数分频
  67. always @(posedge clk_in or negedge rst)
  68. begin
  69.         if(!rst)
  70.                 cnt <= 0;
  71.         else if( (clk_div[15:0]%2 == 1) || (clk_div[15:0] == 0)  )
  72.                 cnt <= 0;
  73.         else if(cnt == clk_div[15:0] -1)
  74.            cnt <= 0;
  75.         else
  76.                 cnt <= cnt+1;
  77. end

  78. always @(posedge clk_in or negedge rst)
  79. begin
  80.         if(!rst)
  81.                 clk_even <= 0;       
  82.         else if( (clk_div[15:0]%2 == 1) || (clk_div[15:0] == 0)  )
  83.                 clk_even <= 0;
  84.         else if(cnt < clk_div[15:0]/2-1)
  85.                 clk_even <= 0;
  86.         else if( cnt == clk_div[15:0]/2-1 )
  87.                 clk_even <= ~clk_even;
  88.                
  89.         else if(cnt == clk_div[15:0] -1)
  90.                 clk_even <= ~clk_even;
  91. end


  92. assign clk_odd = clk_p | clk_n;                                                                        //分频系数为奇数时的脉冲输出信号
  93. assign clk_out = (clk_div[15:0]%2) ? clk_odd : clk_even;        // 当分频系数为偶数时,输出clk_even,否则输出clk_odd

  94. endmodule
 楼主| jlgcumt 发表于 2012-11-26 09:42 | 显示全部楼层
任意整数n分频,占空比为任意1/n的分频程序!

module PWMDIV_ANY(clk_in,clk_out,clk_div,clk_dutycycle,rst);

input  clk_in;                                            //  输入系统时钟频率
output clk_out;                                                //  分频后的时钟输出
input  [23:0] clk_div;                                 // 9200写入的分频系数
input  [23:0] clk_dutycycle;                // 9200写入的占空比
input  rst;                                               //  异步复位信号

reg [23:0] cnt_p;                                          // 上升沿脉冲计数
reg clk_p;
reg [23:0] cnt_n;                                          // 下降沿脉冲计数
reg [23:0] cnt;
reg clk_n;
reg clk_even;
wire clk_odd;

// 奇数分频电路
always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                cnt_p <= 0;
        else if( (clk_div[23:0]%2 == 0) || (clk_div[15:0] == 0) )
                cnt_p <= 0;
        else if(cnt_p == clk_div[23:0] -1)
           cnt_p <= 0;
        else
                cnt_p <= cnt_p+1;
end

always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                clk_p <= 0;
        else if((clk_div[23:0]%2 == 0) || (clk_div[23:0] == 0) )
                clk_p <= 0;
        else if(cnt_p < clk_dutycycle[23:0]-1)
                clk_p <= 0;
        else if(cnt_p == clk_dutycycle[23:0]-1)
                clk_p <= ~clk_p;
        else if(cnt_p == clk_div[23:0] -1)
                clk_p <= ~clk_p;
end


always @(negedge clk_in or negedge rst)
begin
        if(!rst)
                cnt_n <= 0;
        else if((clk_div[23:0]%2 == 0) || (clk_div[23:0] == 0)  )
                cnt_n <= 0;
        else if(cnt_n == clk_div[23:0] -1)
                cnt_n <= 0;
        else
                cnt_n <= cnt_n+1;
end

always @(negedge clk_in or negedge rst)
begin
        if( !rst )
                clk_n <= 0;
        else if( (clk_div[23:0]%2 == 0) || (clk_div[23:0] == 0)  )
                clk_n <= 0;
        else if(cnt_n < clk_dutycycle[23:0]-1)
                clk_n <= 0;
//////////////////////////////////////////////////////////////////////////////////////////////
//        else if(cnt_n == clk_dutycycle[15:0]-1)  // 此处删掉,因为会多出半个时钟,只限在50%占空比里面使用!
//                clk_n <= ~clk_n;
//////////////////////////////////////////////////////////////////////////////////////////////
        else if(cnt_n == clk_div[23:0]-1)
                clk_n <= ~clk_n;
end


// 偶数分频电路
always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                cnt <= 0;
        else if( (clk_div[23:0]%2 == 1) || (clk_div[23:0] == 0)  )
                cnt <= 0;
        else if(cnt == clk_div[23:0] -1)
           cnt <= 0;
        else
                cnt <= cnt+1;
end

always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                clk_even <= 0;       
        else if( (clk_div[23:0]%2 == 1) || (clk_div[23:0] == 0)  )
                clk_even <= 0;
        else if(cnt < clk_dutycycle[23:0]-1 )
                clk_even <= 0;
        else if( cnt == clk_dutycycle[23:0]-1 )
                clk_even <= ~clk_even;
               
        else if(cnt == clk_div[23:0] -1)
                clk_even <= ~clk_even;
end

assign clk_odd = clk_p | clk_n;                          //分频系数为奇数时的脉冲输出信号
assign clk_out = (clk_div[23:0]%2) ? clk_odd : clk_even; // 当分频系数为偶数时,输出clk_even,否则输出clk_odd

endmodule
 楼主| jlgcumt 发表于 2012-11-26 09:43 | 显示全部楼层
输出规定脉冲个数,50%占空比的程序!

// 输出脉冲计数模块///////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
module PusleCnt(clk_in,clr_cmd,pulse_num,out_flag,rst);
input clk_in;
input clr_cmd;
input [15:0] pulse_num;
output out_flag;
input rst;

reg [15:0] pulse_num_cnt;
reg out_flag_r;

always @(negedge clk_in or negedge rst)
begin
        if(!rst)
                begin
                        pulse_num_cnt[15:0] <= 0;
                        out_flag_r <= 0;
                end
        else if( clr_cmd == 1'b1)
                begin
                        pulse_num_cnt[15:0] <= 0;
                        out_flag_r <= 0;
                end
        else
                begin
                        if( pulse_num_cnt[15:0] < pulse_num[15:0] )
                                begin
                                        pulse_num_cnt[15:0] <= pulse_num_cnt[15:0] + 1;       
                                        out_flag_r <= 1;
                                end
                        else if( pulse_num_cnt[15:0] == pulse_num[15:0])
                                begin
                                        out_flag_r <= 0;
                                end
                end
       
end

        assign out_flag = out_flag_r;
       
endmodule

///////////////////////////////////////////////////////////////////////////
//固定个数脉冲输出模块///////////////////////////////////////////////////////
//实现方法:利用计数脉冲的完成来关掉时钟输出////////////////////////////////////
//程序存在问题:响应时间会随着分频系数的变大而变大//////////////////////////////
//////////////////////////////////////////////////////////////////////////
module PulseCtl(clk_in,clk_out,clk_div,clk_dutycycle,pulse_num,clr_cmd,rst);

input  clk_in;    //  输入时钟频率
output clk_out;        //  分频后的时钟输出
input [15:0] clk_div;   
input [15:0] clk_dutycycle;
input [15:0] pulse_num;
input clr_cmd;
input  rst;        //  异步复位信号

reg [23:0] cnt_p;  // 上升沿脉冲计数
reg clk_p;
reg [23:0] cnt_n;  // 下降沿脉冲计数
reg [23:0] cnt;
reg clk_n;
reg clk_even;
wire clk_odd;

wire pulse_en_flag;
wire clk_out_tmp;

reg [15:0] clk_div_r;
reg [15:0] clk_dutycycle_r;
reg [15:0] pulse_num_r;
reg [15:0] cnt_pulse;

always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                cnt_p <= 0;       
        else if((clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
                cnt_p <= 0;
        else if(cnt_p == clk_div[15:0] -1)
           cnt_p <= 0;
        else
                cnt_p <= cnt_p+1;
end


always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                clk_p <= 0;
        else if( (clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
                clk_p <= 0;
        else if(cnt_p < (clk_div[15:0]-1)/2)
                clk_p <= 0;
        else if(cnt_p == (clk_div[15:0]-1)/2)
                clk_p <= ~clk_p;
        else if(cnt_p == clk_div[15:0] -1)               
                        clk_p <= ~clk_p;                       
end


always @(negedge clk_in or negedge rst)
begin
        if(!rst)
                cnt_n <= 0;
        else if((clk_div[15:0]%2 == 0) || (clk_div[15:0] == 0))
                cnt_n <= 0;
        else if(cnt_n == clk_div[15:0] -1)
                cnt_n <= 0;
        else
                cnt_n <= cnt_n+1;
end

always @(negedge clk_in or negedge rst)
begin
        if( !rst )
                clk_n <= 0;
        else if( (clk_div[15:0]%2 == 0)|| (clk_div[15:0] == 0) )
                clk_n <= 0;
        else if(cnt_n < (clk_div[15:0]-1)/2)
                clk_n <= 0;
        else if(cnt_n == (clk_div[15:0]-1)/2)           
                clk_n <= ~clk_n;
        else if(cnt_n == clk_div[15:0]-1)
                clk_n <= ~clk_n;
end

// 偶数分频
always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                cnt <= 0;
        else if( (clk_div[15:0]%2 == 1) || (clk_div[15:0] == 0)  )
                cnt <= 0;
        else if(cnt == clk_div[15:0] -1)
           cnt <= 0;
        else
                cnt <= cnt+1;
end

always @(posedge clk_in or negedge rst)
begin
        if(!rst)
                clk_even <= 0;       
        else if( (clk_div[15:0]%2 == 1) || (clk_div[15:0] == 0)  )
                clk_even <= 0;
        else if(cnt < clk_div[15:0]/2-1)
                clk_even <= 0;
        else if( cnt == clk_div[15:0]/2-1 )
                clk_even <= ~clk_even;               
        else if(cnt == clk_div[15:0] -1)
                clk_even <= ~clk_even;
end


assign clk_odd = clk_p | clk_n;
assign clk_out = (pulse_en_flag) ? ((clk_div[15:0]%2) ? clk_odd : clk_even) : 0;
assign clk_out_tmp = (clk_div[15:0]%2) ? clk_odd : clk_even;

PusleCnt PusCnt(.clk_in(clk_out_tmp),.clr_cmd(clr_cmd),.pulse_num(pulse_num),.out_flag(pulse_en_flag),.rst(rst));

endmodule
 楼主| jlgcumt 发表于 2012-11-26 11:46 | 显示全部楼层
问一下上面写的程序消耗资源都比较大,怎么优化?
GoldSunMonkey 发表于 2012-11-26 20:16 | 显示全部楼层
什么资源耗费的大?
Backkom80 发表于 2012-11-27 08:10 | 显示全部楼层
取作余%,除 /,这些操作占资源了
虽然新的综合器对%,/,这些都支持其综合了,但综合出来占的资源及性能不是很理想。
改变设计思路,尽量避开这些
 楼主| jlgcumt 发表于 2012-11-27 09:47 | 显示全部楼层
5# GoldSunMonkey 逻辑宏消耗的比较多,在CPLD里面写的!
 楼主| jlgcumt 发表于 2012-11-27 09:48 | 显示全部楼层
6# Backkom80 我试试看,谢谢!
GoldSunMonkey 发表于 2012-11-27 18:05 | 显示全部楼层
5# GoldSunMonkey  逻辑宏消耗的比较多,在CPLD里面写的!
jlgcumt 发表于 2012-11-27 09:47
贝壳说的供参考。乘除是比较占资源的。
GoldSunMonkey 发表于 2012-11-28 21:12 | 显示全部楼层
是呀。要修改啊。
Tianya283 发表于 2012-11-29 19:56 | 显示全部楼层
学习了。
GoldSunMonkey 发表于 2012-11-29 20:23 | 显示全部楼层
解决了么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:善攻者,动于九天之上,善守者,藏于九地之下!

183

主题

733

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部