dac8830是一种16分辨率的基于spi通信的dac模块,且spi时钟速率最高50mhz,支持单极性与双极性输出,支持5v和10v两种挡位,制作成电子模块后的样子如下

通过黄色跳线帽来决定输出幅度和极性,所谓极性可以简单理解为,单极性会输出0v以上的直流电,双极性输出正负电压的交流电
时序图如下,可以看到只是一个简单的spi协议

由于电子模块采用双通道,因此要交替执行cs1和cs2的片选,代码如下
module da8830_driver(
input i_clk ,
input i_rst ,
input i_da_en ,
input [15:0] i_cha_data ,
input [15:0] i_chb_data ,
input i_cha_dvld ,
input i_chb_dvld ,
output reg o_cha_cs ,
output reg o_chb_cs ,
output o_mosi ,
output reg o_sclk ,
output o_ready
);
localparam S_IDLE = 4'b0001,
S_CS_DOWN = 4'b0010,
S_DATA = 4'b0100,
S_CS_UP = 4'b1000;
reg [3:0] r_cstate ;
reg [3:0] r_nstate ;
wire w_busy ;
assign w_busy = r_cstate == S_DATA;
assign o_ready = r_cstate == S_IDLE;
// 分频计数器
reg [1:0] r_clk_cnt ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_clk_cnt <= 'd0;
else if(r_cstate == S_DATA)
r_clk_cnt <= r_clk_cnt + 1;
else
r_clk_cnt <= 'd0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst)
o_sclk <= 'b0;
else if(r_cstate == S_DATA)
o_sclk <= r_clk_cnt[0] ? ~o_sclk : o_sclk;
else
o_sclk <= 'b0;
end
//通道选择
reg r_ch_sel ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_ch_sel <= 'b0;
else if(r_cstate == S_CS_UP)
r_ch_sel <= !r_ch_sel;
else
r_ch_sel <= r_ch_sel;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
o_cha_cs <= 'b1;
o_chb_cs <= 'b1;
end
else if(r_cstate == S_CS_UP) begin
o_cha_cs <= 'b1;
o_chb_cs <= 'b1;
end
else if(r_cstate == S_CS_DOWN) begin
o_cha_cs <= r_ch_sel ? 'b1 : 'b0;
o_chb_cs <= r_ch_sel ? 'b0 : 'b1;
end
else begin
o_cha_cs <= o_cha_cs;
o_chb_cs <= o_chb_cs;
end
end
//数据
reg [15:0] r_cha_data ;
reg [15:0] r_chb_data ;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst) begin
r_cha_data <= 'd0;
r_chb_data <= 'd0;
end
else if(w_busy & r_clk_cnt == 2'b11) begin
r_cha_data <= r_ch_sel ? r_cha_data : r_cha_data << 1;
r_chb_data <= r_ch_sel ? r_chb_data << 1 : r_chb_data;
end
else begin
r_cha_data <= i_cha_dvld ? i_cha_data : r_cha_data;
r_chb_data <= i_chb_dvld ? i_chb_data : r_chb_data;
end
end
assign o_mosi = r_ch_sel ? r_chb_data[15] : r_cha_data[15];
reg [3:0] r_bit_cnt ;
wire w_txdone ;
assign w_txdone = r_clk_cnt == 2'b10 & r_bit_cnt == 4'b1111;
always@(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_bit_cnt <= 'd0;
else if(r_cstate == S_DATA)
r_bit_cnt <= r_clk_cnt == 2'b11 ? r_bit_cnt + 1 : r_bit_cnt;
else
r_bit_cnt <= 'd0;
end
always@(posedge i_clk or posedge i_rst) begin
if(i_rst)
r_cstate <= S_IDLE;
else
r_cstate <= r_nstate;
end
always@(*) begin
case(r_cstate)
S_IDLE: r_nstate = i_da_en ? S_CS_DOWN : S_IDLE;
S_CS_DOWN: r_nstate = S_DATA;
S_DATA: r_nstate = w_txdone ? S_CS_UP : S_DATA;
S_CS_UP: r_nstate = r_ch_sel ? S_IDLE : S_CS_DOWN;
default:r_nstate = S_IDLE;
endcase
end
endmodule
采用下面代码测试
`timescale 1ns / 1ps
module test_top(
input i_clk ,
input i_rst_n ,
output o_mosi ,
output o_cha_cs,
output o_chb_cs,
output o_sclk
);
wire w_clk200m;
wire w_clk200m_lked;
clk_wiz_0
mmcm(
.clk_out1 (w_clk200m ),
.reset (!i_rst_n ),
.locked (w_clk200m_lked), // output locked
.clk_in1 (i_clk )
);
reg [15:0] r_cha_data ;
reg [15:0] r_chb_data ;
reg r_cha_dvld ;
reg r_chb_dvld ;
wire w_ready ;
wire w_dds_ovld ;
wire [31:0] w_dds_out ;
reg [31:0] r_dds_out ;
always@(posedge w_clk200m or negedge w_clk200m_lked) begin
if(~w_clk200m_lked)
r_dds_out <= 'd0;
else if(w_dds_ovld)
r_dds_out <= w_dds_out;
else
r_dds_out <= r_dds_out;
end
always@(posedge w_clk200m or negedge w_clk200m_lked) begin
if(~w_clk200m_lked) begin
r_cha_data <= 'd0;
r_chb_data <= 'd0;
r_cha_dvld <= 'd0;
r_chb_dvld <= 'd0;
end
else if(w_ready) begin
r_cha_data <= $signed(r_dds_out[31:16]) + $signed(16'h8000);
r_chb_data <= $signed(r_dds_out[15:0]) + $signed(16'h8000);
r_cha_dvld <= 'd1;
r_chb_dvld <= 'd1;
end
else begin
r_cha_data <= r_cha_data;
r_chb_data <= r_chb_data;
r_cha_dvld <= 'd0;
r_chb_dvld <= 'd0;
end
end
dds_200m
dds (
.aclk (w_clk200m ), // input wire aclk
.aresetn (w_clk200m_lked),
.m_axis_data_tvalid (w_dds_ovld ), // output wire m_axis_data_tvalid
.m_axis_data_tdata (w_dds_out ) // output wire [31 : 0] m_axis_data_tdata
);
da8830_driver
da8830_driver_u(
.i_clk (w_clk200m ),
.i_rst (!w_clk200m_lked ),
.i_da_en (w_clk200m_lked ),
.i_cha_data (r_cha_data ),
.i_chb_data (r_chb_data ),
.i_cha_dvld (r_cha_dvld ),
.i_chb_dvld (r_chb_dvld ),
.o_cha_cs (o_cha_cs ),
.o_chb_cs (o_chb_cs ),
.o_mosi (o_mosi ),
.o_sclk (o_sclk ),
.o_ready (w_ready )
);
ila_1 your_instance_name (
.clk(w_clk200m), // input wire clk
.probe0(r_cha_data), // input wire [15:0] probe0
.probe1(r_chb_data), // input wire [15:0] probe1
.probe2(w_dds_ovld) // input wire [0:0] probe2
);
endmodule
1103

被折叠的 条评论
为什么被折叠?



