赞
踩
距离上一篇CSDN又有两个月了,这两个月学了好多,感觉这半年我还是有很大进步了的,没有一开始那么心力憔悴了。但是水管依旧到处漏……
最近和老虞还有刘同学吃饭,两个不同领域下的大佬,一个做考古,一个做AI,虽然聊的内容差异巨大,但两个人给我的感触都是,他们好厉害,小汤要好好努力!同时也让我想到了,世界可以分为哲学和数学,但最后都会归结于美学。我身边几个特别厉害的程序员,往往审美也是很好的,可能不是那么艺术,但做出来的东西一定是让人看着舒服的。
首先推荐一个画波形原理图的在线网站WaveDrom Online Editor,他们家也有软件可以下载WaveDrom Download Github,使用方法在他家官网上也有介绍Tutorial,可以保存多种格式: json/png/svg,很好用。
在时序电路里,一般系统时钟都是高频的,不同外设对时钟频率的要求不同,所以需要通过分频来获得相应的时钟频率,一般都是将高频的时钟转换为低频的时钟。最简单的分频就是2分频,也就是把时钟频率减半,输出时钟和输入时钟上升沿对齐,波形图是这样的:
当然也会有遇到需要奇数分频的时候,这时候上升沿和下降沿都需要用到,3分频波形图是这样的:
上面两张图都是50%占空比的,有的时候我们只需要用输出时钟的上升沿,不需要考虑下降沿,这样的话我们的输出时钟只需要是单脉冲的就可以了,设计的时候会简单很多,单脉冲的3分频波形图是这样的:
偶数分频又可以分成两种,一种是2的倍数,一种是2的次方。当分频系数是2的次方时,分频的方法会简单很多。这里还是要吐槽一下,CSDN为什么不支持verilog语法!!!
原理:
`define __DIVEVEN_V__ module DivEven #( parameter PRRWIDTH = 4 )( input wire clk, input wire rst, // negetive valid input wire en, input wire [PRRWIDTH-1:0] prr, output reg clkOut ); reg [PRRWIDTH-1:0] cnt; wire [PRRWIDTH-1:0] cntValue; wire direct; // when prr is 0 or 1, clkOut = clk directly assign direct = (prr == {PRRWIDTH{1'b0}}) | (prr == {{(PRRWIDTH-1){1'b0}}, 1'b1}); assign cntValue = direct ? {PRRWIDTH{1'b0}} : (prr - 1'b1); // positive edge count always @(posedge clk or negedge rst) begin if (!rst) begin cnt <= {PRRWIDTH{1'b0}}; end else if (!en) begin cnt <= {PRRWIDTH{1'b0}}; end else if (cnt == cntValue) begin cnt <= {PRRWIDTH{1'b0}}; end else begin cnt <= cnt + 1'b1; end end // overturn clkOut when cnt = (cntValue - 1) / 2 or cntValue always @(posedge clk or negedge rst) begin if (!rst) begin clkOut <= 1'b0; end else if (!en) begin clkOut <= 1'b0; end else if (direct) begin clkOut <= clk; end else if ((cnt == (cntValue >> 1)) || (cnt == cntValue)) begin clkOut <= !clkOut; end end endmodule
原理:
`define __DIVEVEN_V__ module DivEven ( input wire clk, input wire rst, // negetive valid input wire en, input wire [1:0] div, // div = 0 means prr = 0; // div = 1 means prr = 2; // div = 2 means prr = 4; // div = 3 means prr = 8; output wire clkOut ); reg [2:0] cnt; assign clkOut = (!rst | !en) ? 1'b0 : div == 2'b00 ? clk : div == 2'b01 ? cnt[0] : // prr = 2 div == 2'b10 ? cnt[1] : // prr = 4 div == 2'b11 ? cnt[2] : // prr = 8 1'b0; // positive edge count always @(posedge clk or negedge rst) begin if (!rst) begin cnt <= 3'b000; end else if (!en) begin cnt <= 3'b000; end else if (cnt == 3'b111) begin cnt <= 3'b000; end else begin cnt <= cnt + 1'b1; end end endmodule
原理:
`define __DIV50PCT_V__ module Div50Pct #( parameter PRRWIDTH = 4 )( input wire clk, input wire rst, // negetive valid input wire en, input wire [PRRWIDTH-1:0] prr, output wire clkOut ); reg [PRRWIDTH-1:0] cntP; reg [PRRWIDTH-1:0] cntN; reg clkP; reg clkN; wire [PRRWIDTH-1:0] cntValue; wire direct; // when prr is 0 or 1, clkOut = clk directly assign direct = (prr == {PRRWIDTH{1'b0}}) | (prr == {{(PRRWIDTH-1){1'b0}}, 1'b1}); assign cntValue = direct ? {PRRWIDTH{1'b0}} : (prr - 1'b1); // when prr is odd, clkOut = clkP || clkN // when prr is even, clkOut = clkP assign clkOut = direct ? clk : (prr[0] ? (clkP | clkN) : clkP); // positive edge count always @(posedge clk or negedge rst) begin if (!rst) begin cntP <= {PRRWIDTH{1'b0}}; end else if (!en) begin cntP <= {PRRWIDTH{1'b0}}; end else if (cntP == cntValue) begin cntP <= {PRRWIDTH{1'b0}}; end else begin cntP <= cntP + 1'b1; end end // positive edge clock // overturn clkP when cntP = (cntValue - 1) / 2 or cntValue always @(posedge clk or negedge rst) begin if (!rst) begin clkP <= 1'b0; end else if (!en) begin clkP <= 1'b0; end else if (direct) begin clkP <= 1'b0; end else if ((cntP == (cntValue >> 1)) || (cntP == cntValue)) begin clkP <= !clkP; end end // negetive edge count for odd prr always @(negedge clk or negedge rst) begin if (!rst) begin cntN <= {PRRWIDTH{1'b0}}; end else if (!en) begin cntN <= {PRRWIDTH{1'b0}}; end else if (prr[0]) begin if (cntN == cntValue) begin cntN <= {PRRWIDTH{1'b0}}; end else if (cntP != {PRRWIDTH{1'b0}})begin cntN <= cntN + 1'b1; end end else begin cntN <= {PRRWIDTH{1'b0}}; end end // negetive edge clock for odd prr // overturn clkN when cntN = (cntValue - 1) / 2 or cntValue always @(negedge clk or negedge rst) begin if (!rst) begin clkN <= 1'b0; end else if (!en) begin clkN <= 1'b0; end else if (direct) begin clkN <= 1'b0; end else if (prr[0]) begin clkN <= ((cntN == (cntValue >> 1)) || (cntN == cntValue)) ? !clkN : clkN; end else begin clkN <= 1'b0; end end endmodule
思路:
`define __DIVSINGLEPULSE_V__ module DivSinglePulse #( parameter PRRWIDTH = 4 )( input wire clk, input wire rst, // negetive valid input wire en, input wire [PRRWIDTH-1:0] prr, output wire clkOut ); reg clkOutReg; reg [PRRWIDTH-1:0] cnt; wire [PRRWIDTH-1:0] cntValue; wire direct; // when prr is 0 or 1, clkOut = clk directly assign direct = (prr == {PRRWIDTH{1'b0}}) | (prr == {{(PRRWIDTH-1){1'b0}}, 1'b1}); assign cntValue = direct ? {PRRWIDTH{1'b0}} : (prr - 1'b1); assign clkOut = direct ? clk : clkOutReg & clk; // positive edge count always @(posedge clk or negedge rst) begin if (!rst) begin cnt <= {PRRWIDTH{1'b0}}; end else if (!en) begin cnt <= {PRRWIDTH{1'b0}}; end else if (cnt == cntValue) begin cnt <= {PRRWIDTH{1'b0}}; end else begin cnt <= cnt + 1'b1; end end // clkOut is high when cnt == cntValue always @(posedge clk or negedge rst) begin if (!rst) begin clkOutReg <= 1'b0; end else if (!en) begin clkOutReg <= 1'b0; end else if (direct) begin clkOutReg <= 1'b0; end else if (cnt == cntValue) begin clkOutReg <= 1'b1; end else begin clkOutReg <= 1'b0; end end endmodule
以上代码及testbench都可以在verilog任意整数分频及测试.zip中下载噢!
12月到处都是节日的氛围,相信圣诞老人,相信爱、童话和魔法。
昨晚听了Westlife线上演唱会,感觉回到了初中的时候,Seasons in the Sun可能是我最早接触的英文歌。十多年过去了,我工作了,西城男孩也有了岁月的痕迹。They have raised me up and hope to see them once again.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。