这次错误导致我调了半天DAC也没有正常的波形,坑了做硬件的队友
* 错误1:时序图有问题
错误2:数据DIN计算有问题
这个公式给的明明白白,就是让你计算补码为偏移二进制,你的数学敏感还是要锻炼!
* 反思:写驱动一定要认真分析时序图,那些Interface Timing是你一定要认真分析好好关注的
附上我写的DAC8811驱动程序:
`timescale 1ns / 1ps
//
// Company:
// Engineer: Peter
//
// Create Date: 2017/03/19 12:23:48
// Design Name:
// Module Name: DAC8811_Drive
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module DAC8811_Drive
(
output reg CS,
output reg DIN,
input clk,
output wire sclk,
//output reg [4:0]state,
input [15:0]DATA
);
//All reg definition and initial
reg[25:0]count;
reg[9:0]wait_count;
reg encount;
reg [15:0]temp_buff;
reg[4:0]state; //use 18 states to describe the state machine
//Verilog simulation requires initialization of reg
initial begin
encount = 0; count = 1'b0; state = 5'b0;
DIN = 0;CS = 1;
temp_buff=0;
end
//FSM
parameter S0 = 5'd0;
parameter S1 = 5'd1;
parameter S2 = 5'd2;
parameter S3 = 5'd3;
parameter S4 = 5'd4;
parameter S5 = 5'd5;
parameter S6 = 5'd6;
parameter S7 = 5'd7;
parameter S8 = 5'd8;
parameter S9 = 5'd9;
parameter S10 = 5'd10;
parameter S11 = 5'd11;
parameter S12 = 5'd12;
parameter S13 = 5'd13;
parameter S14 = 5'd14;
parameter S15 = 5'd15;
parameter S16 = 5'd16;
parameter Start = 5'd17;
parameter wait_time_0 = 10'd4;
parameter wait_time_1 = 10'b100;
//time div counter
parameter clk_div_time = 26'd8;
always@(negedge clk)begin
if(count < 4'd1)
//if(count < 26'd499)
count <= count + 4'b1;
else
count <=0;
end
wire en_count = (count == 4'd1);
//wire encount = (count == 26'd499);
assign sclk = (count>4'b0);
//wait time counter
initial wait_count=0;
always@(negedge clk)begin
if(encount)
wait_count = wait_count + 10'b1;
else
wait_count = 10'b0;
end
//Finite state machine. One paragraph
always@(negedge sclk)begin
case(state)
S0:begin CS=1'b1;encount=1'b1;state = S1; end
//CS must be brought high for a minimum of 20 ns
//before the next write sequence
S1:begin
if(wait_count >wait_time_0)begin
temp_buff[15:0] = DATA[15:0];
CS<=1'b0;encount <= 1'b0;DIN <= DATA[15];state <= S2;D15~D0 data output from FPGA
end
else begin
CS <= 1'b1; encount <= encount;state <= S1;
end
end
D15~D0 data output from FPGA
//Start:begin DIN =DATA[15];state = S2; end
S2:begin DIN = temp_buff[14]; state = S3; end
S3:begin DIN = temp_buff[13]; state = S4; end
S4:begin DIN = temp_buff[12]; state = S5; end
S5:begin DIN = temp_buff[11]; state = S6; end
S6:begin DIN = temp_buff[10]; state = S7; end
S7:begin DIN = temp_buff[9] ; state = S8; end
S8:begin DIN = temp_buff[8] ; state = S9; end
S9:begin DIN = temp_buff[7]; state = S10; end
S10:begin DIN=temp_buff[6]; state = S11; end
S11:begin DIN=temp_buff[5]; state = S12; end
S12:begin DIN=temp_buff[4]; state = S13; end
S13:begin DIN=temp_buff[3]; state = S14; end
S14:begin DIN=temp_buff[2]; state = S15; end
S15:begin DIN=temp_buff[1]; state = S16; end
S16:begin DIN=temp_buff[0]; state = S0; end
default : state = S0;
endcase
end
endmodule
module top
(
input clk,
output CS,
output DIN,
output sclk,
output Mul_CS,
output Mul_DIN,
output Mul_sclk,
output [2:0]led,
input [1:0]freq_ctr,
input phase
);
wire tick;
wire signed [15:0] sin;
wire [39:0]freqword ;
assign freqword = (freq_ctr==2'b01)?40'd10995116:((freq_ctr==2'b10)?40'd109951163:40'd1099511628);
assign led = (freq_ctr==2'b01)?3'b001:((freq_ctr==2'b10)?'b010:'b100);
wire [39:0]phaseword;
assign phaseword = (phase==1'b1)?40'd274877906900:40'd0;
dds
#(
.PHASE_W(40),
.DATA_W(16),
.TABLE_AW(8),
.MEM_FILE("sin256x16.dat")
)
//100Hz sin signal
the_dds
(
.FreqWord(freqword),
.PhaseShift(phaseword),
.Clock(clk),
.ClkEn(1'b1),
.Out(sin)
);
wire [15:0]data;
wire signed [15:0]out;
wire signed [15:0]out1;
// assign data = sin +16'd32768;
wire signed[32:0] sum = (33'sd1*sin) * 33'sd12582;
assign out=(sum >>>15)+16'd32768;
// wire signed[34:0] sum1 = (35'sd1*sin) * 35'sd12582* 35'sd2;
// assign out1=(sum1 >>>15)+16'd32768;
assign out1=sin+16'd32768;
DAC8811_Drive Sin
(
. CS (CS),
. DIN (DIN),
. clk (clk),
. sclk (sclk),
. DATA (out)
);
DAC8811_Drive MUL
(
. CS (Mul_CS),
. DIN (Mul_DIN),
. clk (clk),
. sclk (Mul_sclk),
. DATA (out1)
);
endmodule
注意!我的正弦表是有符号16位,所以才要加上2^15