题解 | #信号发生器#
信号发生器
http://www.nowcoder.com/practice/39f6766689cc448e928a0921d1d1f858
简析
这道题比较难,想了很久才写出满意的程序。首先,方波的周期是20,锯齿波的周期是21,三角波的周期是40,且wave
的最大值是20。题目没有明确告知,我是从其他人的题解中知道的。下面分别分析一下三种波形如何产生。
方波
方波模式需注意wave
在什么时候翻转。设置一个计数器cnt
,计数范围是0-19。该计数器仅在方波模式也就是wave_choise==0
时工作。
// 仅在方波模式工作的计数器
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= wave_choise!=0 ? 0:
cnt ==19? 0:
cnt + 1;
end
当cnt
值在0~9时,wave==20
;当cnt
值在10~19时,wave==0
。也就是wave
应在cnt==10
时从0变为20。但由于非阻塞赋值,cnt==10
时,wave
应对cnt==9
是否成立进行判断。cnt==19
也是同样原因。
wave <= cnt ==9 ? 20:
cnt ==19? 0 :
wave;
锯齿波
锯齿波比较简单。wave
产生锯齿波时,需要从0增加到20,所以周期是21。 当wave
增加到20时,清零。
wave <= wave==20? 0: wave+1;
三角波
三角波模式需要设置一个标志位flag
。flag
仅在三角波模式也就是wave_chosie==2
时工作。当flag==0
时,wave
减少;当flag==1
时,wave
增加。
wave <= flag==0 ? wave-1: wave+1;
由波形图得知,刚进入三角波模式时,wave
是下降的,所以flag
的默认值是0。wave
在最小值0和最大值20时,flag
应进行翻转。同样由于是非阻塞赋值,所以wave
上升到19时,flag
从1到0,也就是flag <= wave==19&&flag==1? 0: flag
;wave
下降到1时,flag
从0到1,也就是flag <= wave==1&&flag==0? 1: flag
。
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
flag <= 0;
else
flag <= wave_choise!=2 ? 0:
wave ==1 ? 1:
// wave==1&&flag==0 ? 1: // 等价
wave ==19? 0:
// wave==19&&flag==1 ? 0: // 等价
flag;
end
代码
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise,
output reg [4:0]wave
);
reg [4:0] cnt;
reg flag;
// 方波模式下,计数器控制
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cnt <= 0;
else
cnt <= wave_choise!=0 ? 0:
cnt ==19? 0:
cnt + 1;
end
// 三角波模式下,标志位控制
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
flag <= 0;
else
flag <= wave_choise!=2 ? 0:
wave ==1 ? 1:
wave ==19? 0:
flag;
end
// 更新wave信号
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
wave <= 0;
else
case(wave_choise)
0 : wave <= cnt == 9? 20 :
cnt ==19? 0 :
wave;
1 : wave <= wave==20? 0 : wave+1;
2 : wave <= flag==0 ? wave-1: wave+1;
default: wave <= 0;
endcase
end
endmodule
Verilog篇题解 文章被收录于专栏
本人对牛客网verilog篇题目一些理解