简易示波器

2021/8/1 23:06:09

本文主要是介绍简易示波器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、顶层设计

 button_in_out模块是对按键做去抖动

DUT模块内有信号激励stimulus,触发strigger,状态机timebase

二、模块代码

1、stimulus模块

输入:时钟I_CLK,归零I_RST,位宽I_N_CLKNUM(=3),增量I_INC=(111000H)产生信号的类型I_MODE(=1表示DDS电路产生正弦信号)

输出:数据O_DOUT,使能/溢出O_DOV

module stimulus(
  I_CLK           ,   // clock, posedge valid
  I_RST           ,   // reset, high level reset
  I_N_CLKNUM      ,   // N_CLKNUM >= 1, every N_CLKNUM period output 1 data sample
  I_N_INC         ,   // counter increase value or dds phase increase word
  I_MODE          ,   // 0 : counter, 1: DDS
  O_DOUT          ,   // data output
  O_DOV           );  // data output valid


parameter FW_WL = 32;   // frequency word word length in bit
parameter RA_WL = 10;   // rom address word length in bit
parameter RD_WL =  8;   // rom data  word word length in bit

input               I_CLK     ;
input               I_RST     ;
input [FW_WL -1:0]  I_N_CLKNUM;
input [FW_WL -1:0]  I_N_INC   ;
input               I_MODE    ;
output[RD_WL -1:0]  O_DOUT    ;
output              O_DOV     ;


wire    [FW_WL -1:0]    cnt_max_W;
reg     [FW_WL -1:0]    clk_cnt_R;
reg     [FW_WL -1:0]    acc_cnt_R;
reg                     work_en_W, work_en_W_R1, work_en_W_R2; 
wire    [RA_WL -1:0]    addr_W    ;  
wire    [RD_WL -1:0]    romout_W  ;
reg     [RA_WL -1:0]    addr_W_R1 ;  
reg     [RD_WL -1:0]    O_DOUT    ;
reg                     O_DOV     ;

assign                  cnt_max_W = I_N_CLKNUM -1;

// pipeline design
// work_en_W | acc_cnt_R    | romout_W      |   O_DOUT
//           | addr_W       | addr_W_R1     |
//           | work_en_W_R1 | work_en_W_R2  |   O_DOV

// update work cycle counter 
always @ (posedge I_CLK or posedge I_RST) begin
  if(I_RST) begin
    clk_cnt_R <= 0;
  end
  else begin
    if(clk_cnt_R < cnt_max_W) begin
      clk_cnt_R <= clk_cnt_R + 1'b1;
    end // if
    else begin
      clk_cnt_R <= 0;
    end // else clk_cnt_R
  end // else RST
end // always
// generate work cycle enable
always @ (*) begin
  if(clk_cnt_R == cnt_max_W) begin
    work_en_W = 1'b1;
  end
  else begin
    work_en_W = 1'b0;
  end
end
// update acc
always @ (posedge I_CLK or posedge I_RST) begin
  if(I_RST) begin
    acc_cnt_R <= 0;
  end
  else begin
    if(work_en_W) begin
      acc_cnt_R <= acc_cnt_R + I_N_INC;
    end
  end
end
// get addr wire
assign addr_W = acc_cnt_R[FW_WL -1: FW_WL -1-RA_WL +1];
DDS_CORE_ROM u_sinrom(
  .CLK    (I_CLK    ),  // clock
  .RA     (addr_W   ),  // read address
  .RD     (romout_W )); // read data


always @ (posedge I_CLK ) begin
  addr_W_R1    <= addr_W;
  work_en_W_R1 <= work_en_W   ;
  work_en_W_R2 <= work_en_W_R1;
  if(I_MODE == 0)begin // mode == 0, counter
    O_DOUT <=  addr_W_R1[RD_WL-1:0];
  end
  else begin
    O_DOUT <=  {{~romout_W[RD_WL-1]},{romout_W[RD_WL-2:0]}}     ; // signed 2's complement code to unsigned code
  end
  O_DOV  <=  work_en_W_R2;

end

endmodule // module dds_core

2、trigger

输入:触发电平的区间I_TRIG_V_MAX,I_TRIG_V_MIN,触发模式I_T_MODE(00表示自由触发;01表示上升沿触发;10表示下降沿触发;11表示双向触发)

输出:O_TRIG_ON表示开始触发

触发方式:

自由触发=李萨如波形

上升沿触发:达到电平区间且在上升沿

module trigger(
  I_CLK           ,   // clock, posedge valid
  I_RST           ,   // reset, high level reset
  I_DIN           ,
  I_DEN           ,
  I_TRIG_V_MAX    ,   // trigger range max value 
  I_TRIG_V_MIN    ,   // trigger range min value 
  I_T_MODE        ,   // trigger mode 00 free trig , 01 value inc trig,  10 value dec trig, 11 value trig both inc or dec
  O_DOUT          ,
  O_DOV           ,
  O_TRIG_ON       );     

parameter  DWL = 8;
localparam DMAX = (1 << DWL) - 1;

input            I_CLK         ;
input            I_RST         ;

input  [DWL-1:0] I_DIN           ;
input            I_DEN           ;
input  [2-1:0]   I_T_MODE        ;
input  [DWL-1:0] I_TRIG_V_MAX    ;
input  [DWL-1:0] I_TRIG_V_MIN    ;
output [DWL-1:0] O_DOUT          ;
output           O_DOV           ;
output           O_TRIG_ON       ;



reg   [DWL-1:0] din_Z1R            ; // previous din
reg   [DWL-1:0] din_d1R, din_d2R, din_Z1d1R ; 
reg             den_d1R, den_d2R            ;
reg   [DWL-1:0] t_v_max_R, t_v_min_R;
reg  W_trig_on;
reg  W_in_trig_range, W_din_increase, W_din_decrease;
reg  O_TRIG_ON;


assign O_DOUT = din_d2R;
assign O_DOV  = den_d2R;

// pipeline design
// I_DIN | din_d1R, din_Z1d1R | din_d2R
// I_DEN | den_d1R            | den_d2R
//       | W_in_trig_range    | O_DOUT   
//       | W_din_increase     | O_DOV    
//       | W_din_decrease     | O_TRIG_ON
//       | W_trig_on          |

always @ (posedge I_CLK ) begin
    t_v_max_R <= I_TRIG_V_MAX ;
    t_v_min_R <= I_TRIG_V_MIN ;
    din_d1R <= I_DIN;
    den_d1R <= I_DEN;
    din_d2R <= din_d1R;
    den_d2R <= den_d1R;
    O_TRIG_ON <= W_trig_on;
    din_Z1d1R <= din_Z1R;
    if(I_DEN) din_Z1R <= I_DIN;
end // always

always @ (*) begin
  if((din_d1R >= t_v_min_R) && (din_d1R <= t_v_max_R)) begin
    W_in_trig_range = 1'b1;
  end
  else begin
    W_in_trig_range = 1'b0;
  end
  if(din_d1R > din_Z1d1R) W_din_increase = 1'b1; else W_din_increase = 1'b0;
  if(din_d1R < din_Z1d1R) W_din_decrease = 1'b1; else W_din_decrease = 1'b0;
  // trigger mode 00 free trig , 01 value inc trig,  10 value dec trig, 11 value trig both inc or dec
  case (I_T_MODE)
    2'b00:  begin W_trig_on = 1'b1; end
    2'b01:  begin W_trig_on = (W_din_increase && W_in_trig_range); end
    2'b10:  begin W_trig_on = (W_din_decrease && W_in_trig_range); end
    2'b11:  begin W_trig_on = (den_d1R && W_in_trig_range) ; end
  endcase
end // always
endmodule // module 

3、timebase

产生触发后开始存储数据,根据START,TRIG_ON,RAM_FULL信号形成状态机

 三、signaltap波形

在START上升沿时开始检测触发,产生触发后,产生地址信号把波形数据存储到RAM,存储到RAM后产生RAM_FULL信号,告知单片机可以读取RAM了



这篇关于简易示波器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程