使用stm32与fpga之间的spi通信,stm32通过fpga控制DAC输出模拟电压,使用三线制。
使用FPGA驱动MS5541,采用3线制,输出时钟(20MHz),片选信号,输出信号,主机端时钟为100MHz,将时钟5分频,然后设置片选信号与并行转串行输出信号在20MHz时钟上升沿输出
input | clk |
input | rst |
input | start |
input | i16_dac_data |
output | o_dac_sclk |
output | o_dac_cs |
output | o_dac_MOSI |
module dac_core(
input clk,
input rst,
input start,
input [15:0] i16_dac_data,
output wire o_dac_sclk,
output reg o_dac_cs,
output reg o_dac_mosi
);
reg [5:0] tri_cnt;
reg [4:0] data_count;
reg [15:0] i16_dac_data_reg;
wire sclk_posedge;
reg o_dac_sclk_buf;
/**************************************************************************
100MHz 5分频
**************************************************************************/
reg [3:0] state1;
reg [3:0] state2;
always@(posedge clk)
begin
if(rst)
begin
state1 <= 4'b0000;
end
else
begin
case(state1)
4'b0000: state1 <= 4'b0010;
4'b0010: state1 <= 4'b0110;
4'b0110: state1 <= 4'b0001;
4'b0001: state1 <= 4'b0011;
4'b0011: state1 <= 4'b0000;
default: state1 <= 4'b0000;
endcase
end
end
always@(negedge clk)
begin
if(rst)
begin
state2 <= 4'b0 ;
end
else
begin
case(state2)
4'b0000: state2 <= 4'b0010;
4'b0010: state2 <= 4'b0110;
4'b0110: state2 <= 4'b0001;
4'b0001: state2 <= 4'b0011;
4'b0011: state2 <= 4'b0000;
default: state2 <= 4'b0000;
endcase
end
end
assign o_dac_sclk = state1[0] | state2[0];
/******************************************************************************
输出时钟边沿
******************************************************************************/
always@(posedge clk) begin
if(rst) begin
o_dac_sclk_buf <= 1'b0;
end
else begin
o_dac_sclk_buf <= o_dac_sclk;
end
end
assign sclk_posedge = (o_dac_sclk_buf == 1'b0 && o_dac_sclk == 1'b1);
/**************************************************************************
状态转移
**************************************************************************/
reg [2:0] cnt;
reg [2:0] state_cur;
reg [2:0] state_nex;
parameter SM01 = 3'b001,
SM02 = 3'b010,
SM03 = 3'b100;
always@(posedge clk) begin
if(rst) begin
cnt <= 2'd0;
end
else begin
if((state_cur == 3'd0 && cnt <3'd3)) begin
cnt <= cnt + 1'b1;
end
else begin
cnt <= 3'd0;
end
end
end
always@(*) begin
if(rst) begin
state_cur <= 3'd0;
end
else begin
state_cur <= state_nex;
end
end
always @(posedge clk) begin
if (rst) begin
o_dac_cs <= 1'b1;
o_dac_mosi <= 1'b0;
data_count <= 4'd0;
i16_dac_data_reg<= i16_dac_data;
state_nex <= 3'b0;
tri_done <= 1'b0;
end
else begin
case(state_cur)
SM01: begin
o_dac_cs <= 1'b1;
o_dac_mosi <= 1'b0;
tri_done <= 1'b0;
if(cnt == 3'd3) begin
state_nex <= SM02;
i16_dac_data_reg<= i16_dac_data;
end
end
SM02: begin
tri_done <= 1'b1;
if (start) begin
if(o_dac_cs == 1'b1) begin
o_dac_cs <= 1'b0;
data_count <= 4'd0;
o_dac_mosi <= i16_dac_data_reg[15];
i16_dac_data_reg <= i16_dac_data_reg << 1;
end
else begin
if(sclk_posedge == 1'b1)begin
if (data_count < 4'd15) begin
o_dac_mosi <= i16_dac_data_reg[15];
i16_dac_data_reg <= i16_dac_data_reg << 1;
data_count <= data_count + 4'd1;
end
else begin
data_count <= 2'd0;
o_dac_mosi <= 1'b0;
state_nex <= SM03;
o_dac_cs <= 1'b1;
end
end
else begin
o_dac_cs <= o_dac_cs;
data_count <= data_count;
o_dac_mosi <= o_dac_mosi;
i16_dac_data_reg <= i16_dac_data_reg;
end
end
end
end
SM03: begin
state_nex <= SM01;
end
endcase
end
end
endmodule