差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
脉冲发生器 [2016/06/13 16:37] anran [工作原理] |
脉冲发生器 [2016/06/29 10:20] (当前版本) anran [代码设计] |
||
---|---|---|---|
行 17: | 行 17: | ||
周期:在数字信号的领域中是信号变化的过程中,某段波形重复出现,其某一次开始至结束的这段时间就称为“周期"。 | 周期:在数字信号的领域中是信号变化的过程中,某段波形重复出现,其某一次开始至结束的这段时间就称为“周期"。 | ||
+ | |||
占空比:是在一串理想的脉冲系列中,正脉冲的持续时间与脉冲周期的比值。例如在下图中t为正脉冲的持续时间,T为脉冲周期,占空比为t/T。 | 占空比:是在一串理想的脉冲系列中,正脉冲的持续时间与脉冲周期的比值。例如在下图中t为正脉冲的持续时间,T为脉冲周期,占空比为t/T。 | ||
{{ :占空比.jpg |占空比}} | {{ :占空比.jpg |占空比}} | ||
- | |||
- | 分频比:指方波的周期和高频信号手气之间发的比例关系,通过控制分频比来生成不同频率的方波。例如,开发系统上的时钟频率是25MHz,如果要生成5MHz的方波,则分频比为5。 | ||
脉冲发生一般通过对一个高频的脉冲信号进行分频来生成。 | 脉冲发生一般通过对一个高频的脉冲信号进行分频来生成。 | ||
+ | |||
+ | 分频比:指方波的周期和高频信号周期之间发的比例关系,通过控制分频比来生成不同频率的方波。例如,开发系统上的时钟频率是25MHz,如果要生成5MHz的方波,则分频比为5。 | ||
+ | |||
行 29: | 行 31: | ||
====硬件连接==== | ====硬件连接==== | ||
------ | ------ | ||
- | 为了方便我们在硬件平台上更直观的观察,我们使用25MHz时钟晶振分频产生1Hz的信号作为序列检测的时钟,同时使用LED灯LD1指示1Hz信号,按键信号作为序列检测的信号输入,LED灯LD2作为序列检测的输出指示。 | + | 为了方便在硬件平台上演示,我们使用25MHz的系统时钟作为高频信号做分频处理,产生脉冲信号,通过调节脉冲信号的周期和正脉冲的宽度,最终生成我们需要的脉冲信号。 |
- | {{ :按键硬件图.jpg |按键硬件图}} | + | 三路按键输入: |
+ | * key_menu:使用按键K5作为输入,按动K5按键控制周期和脉宽调节模式的切换。 | ||
+ | * key_up:使用按键K1作为输入,按动K1按键根据所处的模式控制周期或脉宽参数的增加。 | ||
+ | * key_down:使用按键K3作为输入,按动K3按键根据所处的模式控制周期或脉宽参数的减小。 | ||
+ | 两路LED输出: | ||
+ | * menu_state:使用小脚丫核心板上的LD1作为输出,当LED点亮或熄灭时分别表示脉宽调节模式或周期调节模式。 | ||
+ | * pulse_out:使用小脚丫核心板上的LD2作为输出,可以根据LED的亮度表示周期和脉宽的变化(注意:当输出低电平时LED点亮)。 | ||
{{ :led电路连接.jpg |LED电路连接}} | {{ :led电路连接.jpg |LED电路连接}} | ||
+ | {{ :图9.按键模块电路连接.png |按键模块电路连接}} | ||
====代码设计==== | ====代码设计==== | ||
---- | ---- | ||
===设计文件=== | ===设计文件=== | ||
- | {{ :序列检测状态转移图.jpg |序列检测状态转移图}} | + | {{ :脉冲发生程序设计.jpg |脉冲发生程序设计}} |
- | 为了得到1Hz的信号,我们设计了25位的计数器cnt进行0.5s周期的循环计数,同时clk_1hz信号进行翻转,这样就得到了序列检测的时钟信号,然后再以序列检测的时钟信号为触发条件进行状态机的控制最终实现序列检测。 | + | 我们在硬件连接中也提到了脉冲发生器设计需要的硬件资源作为接口外设,整个设计的接口定义如下: |
- | 首先是计数器的设计,计数器的计数范围为0~CNT_NUM-1,设计文件代码中我们定义参数CNT_NUM为12500000,但是在仿真文件调用设计文件时,为了方便仿真,我们会将参数CNT_NUM重新赋值为5. | + | <code verilog> |
+ | input clk_in, | ||
+ | input rst_n_in, | ||
+ | input key_menu, | ||
+ | input key_up, | ||
+ | input key_down, | ||
+ | output menu_state, | ||
+ | output reg pulse_out | ||
+ | </code> | ||
+ | |||
+ | 本设计中我们用到三个按键作为输入,需要对按键输入做消抖处理,消抖模块的原理及设计请参考[[按键消抖]]设计,这里我们增加了按键输入信号的位宽,同时对三路按键输入做消抖处理 ,如下: | ||
<code verilog> | <code verilog> | ||
- | reg [24:0] cnt = 25'd0; | + | //Debounce for key |
- | always@(posedge clk or negedge rst_n) begin | + | wire [2:0] key_state,key_pulse; |
- | if(!rst_n) begin | + | Debounce1 Debounce_uut |
- | cnt <= 25'd0; | + | ( |
- | clk_1hz <= 1'b0; | + | .clk(clk_in), |
- | end else if(cnt>=(CNT_NUM-1)) begin | + | .rst_n(rst_n_in), |
- | cnt <= 25'd0; | + | .key_n({key_menu,key_up,key_down}), |
- | clk_1hz <= ~clk_1hz; | + | .key_state(key_state), |
- | end else begin | + | .key_pulse(key_pulse) |
- | cnt <= cnt + 25'd1; | + | ); |
- | end | + | |
- | end | + | wire menu_state = key_state[0]; |
+ | wire up_pulse = key_pulse[1]; | ||
+ | wire down_pulse = key_pulse[2]; | ||
</code> | </code> | ||
- | 然后按照状态机的状态转移图实现状态机的设计。 | + | 对三路按键做消抖后的信号可以实现周期和脉宽的控制,本设计中我们的分频比范围为2~16分级可调,0%<脉宽<100%分级可调,控制脉宽参数duty要始终小于周期参数cycle, |
+ | {{ ::脉冲发生器原理.jpg |脉冲发生器原理}} | ||
+ | 实现方法如下: | ||
<code verilog> | <code verilog> | ||
- | reg[1:0]state; | + | //Control cycle and duty cycle |
- | always @(posedge clk_1hz or negedge rst_n) begin | + | always @(posedge clk_in or negedge rst_n_in) begin |
- | if(!rst_n) begin | + | if(!rst_n_in) begin |
- | state<=s0; | + | cycle<=4'd8; |
- | vout<=0; | + | duty<=4'd4; |
- | end else case(state) | + | end else begin |
- | s0: begin | + | if(menu_state) begin |
- | if(vin==0) begin state<=s0;vout<=0; end | + | if(up_pulse && (cycle<4'd15)) cycle <= cycle + 4'd1; |
- | else begin state<=s1;vout<=0; end | + | else if(down_pulse && (cycle>(duty+4'd1))) cycle <= cycle - 4'd1; |
- | end | + | else cycle <= cycle; |
- | s1: begin | + | end else begin |
- | if(vin==0) begin state<=s2;vout<=0; end | + | if(up_pulse && (cycle>(duty+4'd1))) duty <= duty + 4'd1; |
- | else begin state<=s1;vout<=0; end | + | else if(down_pulse && (duty>4'd0)) duty <= duty - 4'd1; |
- | end | + | else duty <= duty; |
- | s2: begin | + | end |
- | if(vin==0) begin state<=s0;vout<=0; end | + | end |
- | else begin state<=s1;vout<=1; end | + | |
- | end | + | |
- | default:state<=s0; | + | |
- | endcase | + | |
end | end | ||
</code> | </code> | ||
- | 我们在设计中将序列检测的时钟信号设计为1Hz,并且使用LED指示序列检测的时钟信号的变化,方便在板子上按键及观察输出的情况。 | + | 最后根据周期参数cycle控制计数器的计数范围,根据脉宽参数duty控制正电压脉冲的宽度,产生脉冲信号。 |
- | + | ||
- | ===测试文件=== | + | |
- | + | ||
- | 测试文件中我们需要对设计文件中的参数CNT_NUM进行重新赋值,同时对vin信号每400ns(序列检测时钟 = 系统时钟周期*分配系数*2 = 40*5*2 = 400ns)间隔取随机值。 | + | |
<code verilog> | <code verilog> | ||
- | always vin = # 400 $random; | + | reg [3:0] cnt; |
+ | //counter for cycle | ||
+ | always @(posedge clk_in or negedge rst_n_in) begin | ||
+ | if(!rst_n_in) begin | ||
+ | cnt<=4'd0; | ||
+ | end else begin | ||
+ | if(cnt>=cycle) cnt<=4'd0; | ||
+ | else cnt <= cnt + 4'd1; | ||
+ | end | ||
+ | end | ||
- | wire clk_1hz,vout; | + | //pulse generate with duty |
- | Serial_Detect # | + | always @(posedge clk_in or negedge rst_n_in) begin |
- | ( | + | if(!rst_n_in) begin |
- | .CNT_NUM(CNT_NUM) | + | pulse_out<=1'b1; |
- | ) | + | end else begin |
- | Serial_Detect_uut | + | if(cnt<=duty) pulse_out<=1'b1; |
- | ( | + | else pulse_out<=1'b0; |
- | .clk(sys_clk), | + | end |
- | .rst_n(sys_rst_n), | + | end |
- | .vin(vin), | + | |
- | .clk_1hz(clk_1hz), | + | |
- | .vout(vout) | + | |
- | ); | + | |
</code> | </code> | ||
引脚分配如下: | 引脚分配如下: | ||
- | ^ 管脚名称 | clk| rst_n | vin |clk_1hz |vout | | + | ^ 管脚名称 | clk_in| rst_n_in| key_menu|key_up|key_down|menu_state|pulse_out| |
- | ^ FPGA管脚 | C1 | A2 |B7 |A3 |A7 | | + | ^ FPGA管脚 | C1 | A2 | A12 |B8 |A10 |A3 |A7 | |
- | ====仿真结果==== | + | ====运行结果==== |
- | {{:序列检测仿真.jpg|序列检测仿真}} | + | {{:img20160614134850.jpg?500 |LED灯亮度}} |
+ | |||
+ | {{:img20160614135014.jpg?500|示波器测量结果}} | ||
====资源报告==== | ====资源报告==== | ||
^ 资源 | 数量 | 比例 | 说明 | | ^ 资源 | 数量 | 比例 | 说明 | | ||
- | ^ LUTs | 39 | 3% | | | + | ^ LUTs | 65 | 5% | | |
- | ^ 寄存器 | 28 | 2% | | | + | ^ 寄存器 | 42 | 3% | | |
^ 存储器 | 0 | 0% | | | ^ 存储器 | 0 | 0% | | | ||
- | ^ IO管脚 | 5 | | | | + | ^ IO管脚 | 7 | | | |
^ 时钟频率 | 25MHz | | | | ^ 时钟频率 | 25MHz | | | | ||
====知识点==== | ====知识点==== | ||
- | * 分频设计 | + | * 按键消抖 |
- | * 时序控制 | + | * PWM脉宽调节 |
- | * 简单状态机 | + | * 脉冲发生原理 |
====参考文档==== | ====参考文档==== | ||
+ | * [[按键消抖]] | ||
* {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} | * {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}} | ||
+ | |||
行 140: | 行 164: | ||
^ **文件名称** | **功能** | | ^ **文件名称** | **功能** | | ||
- | ^ **[[Serial_Detect.v]]** | **流水灯** | | + | ^ **[[Pulse_gen.v]]** | **脉冲发生器TOP文件** | |
- | ^ **[[Serial_Detect_test.v]]** | **测试文件** | | + | ^ **[[Debounce1.v]]** | **按键消抖** | |