题解 | #信号发生器#
信号发生器
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