一、顶层设计
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了