题解 | #信号发生器#

信号发生器

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

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务