题解 | #信号发生器#
信号发生器
https://www.nowcoder.com/practice/39f6766689cc448e928a0921d1d1f858
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise,
output reg [4:0] wave,
output reg [4:0] cnt,
output reg flag
);
/*
这道题多亏了是有人在前面踩坑,
看了一个哥们儿的题解,才能知道生成的方波、锯齿波和三角波的周期分别是:20,21,40
就尼玛离谱
然后如何在ModelSim中看到不同形状的波形呢,就是右键wave信号,选择format->Analog(automatic),
就能根据当前数字信号的值,自动绘制信号的模拟波形。
*/
// 方波的上下沿的值
localparam DIV_HIGH = 5'd20;
localparam DIV_LOW = 5'd0;
// 产生 cnt,控制方波的生成
// reg [4:0] cnt;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
cnt <= 5'd0;
end
else begin
cnt <= (wave_choise==2'b00)?
((cnt==5'd19)? 5'd0 : cnt+1'd1)
:
(5'd0);
end
end
// 产生 flag 信号,控制三角波的生成
// reg flag;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
flag <= 1'b0;
end
else begin
flag <= (wave_choise==2'b10)? (wave==5'd0)? 1'b1 : // 这里加了一句判断,是在锯齿波转换到三角波时做平滑处理,避免wave从0开始自减导致溢出
(wave==5'd1)? 1'b1 :
((wave==5'd19)? 1'b0 : flag) :
1'b0;
end
end
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
wave <= 5'd0;
end
else begin
case (wave_choise)
2'b00: begin // 方波
wave <= (cnt==5'd9)?
DIV_HIGH
:
(cnt==5'd19)? DIV_LOW : wave;
end
2'b01: begin // 锯齿波
wave <= (wave==5'd20)? 5'd0 : wave+1'd1;
end
2'b10: begin // 三角波
wave <= (wave==5'd0)?
wave+1'd1 // 这里加了一句判断,是在锯齿波转换到三角波时做平滑处理,避免wave从0开始自减导致溢出
:
(flag? wave+1'b1 : wave-1'b1);
end
default:
wave <= 5'b0;
endcase
end
end
endmodule
/*
module wave_gen (
clk,
rst_n,
div_period,
div_h,
div_l,
wave,
beat
);
input clk;
input rst_n;
input [4:0] div_period;
input [4:0] div_h;
input [4:0] div_l;
output reg [4:0] wave;
output reg beat;
reg [4:0] cnt;
// cnt
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
cnt <= 5'd0;
end
else begin
cnt <= (cnt==div_period)? 5'd0 : cnt+1'd1;
end
end
// reg beat;
always @(posedge clk or negedge rst_n)
begin
if(~rst_n) begin
beat <= 1'b0;
end
else begin
beat <= (cnt==div_period)? ~beat : beat;
end
end
always @(posedge clk or negedge rst_n)
begin
if(~rst_n)
wave <= 5'd0;
else begin
if(beat)
wave <= div_h;
else
wave <= div_l;
end
end
endmodule
*/
以下是自测testbench:
`timescale 1ns/1ns
module tb;
reg clk;
reg rst_n;
reg [1:0] wave_choise;
wire [4:0] wave;
wire [4:0] cnt;
wire flag;
initial begin
clk = 1'b0;
rst_n = 1'b0;
wave_choise = 2'b00;
#20;
rst_n = 1'b1;
#10;
wave_choise = 2'b00;
#910;
wave_choise = 2'b01;
#890;
wave_choise = 2'b10;
#1000;
#10;
rst_n = 1'b1;
#10;
$finish;
end
always#5 clk = ~clk;
signal_generator ins (
.clk (clk ),
.rst_n (rst_n ),
.wave_choise (wave_choise ),
.wave (wave ),
.cnt (cnt),
.flag (flag)
);
endmodule
