用串口控制DAC

使用串口助手发送四个字节的指令,来控制DAC产生对应数值的电压,第一字节为AA指令,使DAC进入准备状态,以防止串口产生的意外数据进行干扰。第二字节为选择寄存器指令,及(A1和A0),只有最低两位有效。PD和LDAC固定为1和0。第三字节的高4位和第四字节的全部位组成12位的数据位。这样我们可以用状态机来控制串口发来的数据与需要给dac模块的16位数据的关系。

输出的电压(VOUT)与输入的12位数据位的数据(D)公式:

VOUT=VREF * D /2^N。

VREF为参考电压,这里选用2.5V。

N为DAC的分辨率,AD5324的分辨率为12位。

例如:我想在DAC-A通道产生一个1.6V的电压:

那么A1和A0位设置为0、0。PD和LDAC固定为1、0。12位的数据位按照以上公式可以计算:1.6=2.5*D/2^12。计算结果D=2621.44,取近似值2621,用二进制表示为1010_0011_1101。那么串口发送的第一个字节为AA指令,第二字节的最低两位为00,第三字节中的高4位为1010,第四字节为0011­­_1101。这四个字节用8进制数可以表示为AA 00 A0 3D。

模型模块图和时序图:

复制代码
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File   : top_dac_ctrl.v
// Create : 2025-10-15 09:48:38
// Revise : 2025-10-16 15:34:58
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale  1ns/1ps


module top_dac_ctrl(
	input 	wire 	clk,
	input	wire	rst_n,
	// input	wire	chn_Valid,
	// input	wire [15:0]	chn_data,	//(A0, A1, LDAC, DATA[11:0])
	//SPI DAC master
	output	wire		sysc_n,
	output	wire		sclk,
	output	wire		sdi,
	//uart
	input	wire		rx

    );

wire 			s_rst_n;
wire [15:0]		chn_data;
wire			chn_Valid;

wire 	valid;
reg	valid_r;

wire	po_flag;
wire[7:0] po_data;

	reset_gen reset_gen_inst (
		.clk(clk), 
		.rst_n(rst_n), 
		.s_rst_n(s_rst_n)
		);

	dac_ctrl_ad5324 dac_ctrl_ad5324_inst(
			.clk       (clk),
			.rst_n     (s_rst_n),
			.chn_Valid (chn_Valid),
			.chn_data  (chn_data),
			.sysc_n    (sysc_n),
			.sclk      (sclk),
			.sdi       (sdi)
		);

	ila_top ila_top_inst (
		.clk(clk), // input wire clk


		.probe0({
			sysc_n,
			sclk,
			sdi,
			chn_data,
			chn_Valid

		}) // input wire [23:0] probe0
	);

	// vio_top vio_top_inst (
	//   .clk(clk),                // input wire clk
	//   .probe_out0(valid),  // output wire [0 : 0] probe_out0
	//   .probe_out1(chn_data)  // output wire [15 : 0] probe_out1
	// );

	uart_cmd inst_uart_cmd(
			.clk        (clk),
			.rst_n      (rst_n),
			.pi_flag    (po_flag),
			.pi_data    (po_data),
			.chn1_valid (chn1_valid),
			.chn1_data  (chn1_data)
		);

	uart_rx #(
			.CNT_BAUD_MAX(5208),
			.CNT_HALF_BAUD_MAX(2603)
		) inst_uart_rx (
			.clk     (clk),
			.rst_n   (rst_n),
			.rx      (rx),
			.po_data (po_data),
			.po_flag (po_flag)
		);


// always @(posedge clk ) begin
// 	valid_r <= valid;
// end

// assign chn_Valid = (valid_r == 1'b0 && valid == 1'b1)? 1'b1 : 1'b0;

endmodule


// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File   : uart_cmd.v
// Create : 2025-10-16 15:30:40
// Revise : 2025-10-16 15:30:40
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale  1ns/1ps


module uart_cmd(
	input	wire 		clk,
	input	wire		rst_n,
	input	wire		pi_flag,
	input	wire[7:0]	pi_data,
	output	reg			chn1_valid,
	output	reg[15:0]	chn1_data		

    );

reg [1:0] 	cmd_cnt;
reg [15:0] 	cmd_data;
reg 		cmd_flag;


always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		cmd_cnt <= 0;
	end
	else if (cmd_cnt == 2 && pi_flag == 1) begin
		cmd_cnt <= 0;
	end
	else if (cmd_cnt != 'd0 && pi_flag == 1'b1) begin
		cmd_cnt <= cmd_cnt + 1;
	end
	else if (pi_flag == 1 && pi_data == 8'hAA && cmd_cnt == 'd0) begin
		cmd_cnt <= 1'd1;
	end
end


always @(posedge clk) begin
	if (rst_n == 0) begin
		// reset
		cmd_data <= 0;
	end
	else if (cmd_cnt == 'd1 && pi_flag == 1'b1) begin
		cmd_data <= {pi_data, cmd_data[7:0]}; 
	end
	else if (cmd_cnt <= 'd2 && pi_flag == 1'b1) begin
		cmd_data <= {cmd_data[15:8], pi_data};
	end
end


always @(posedge clk) begin
	if (rst_n == 0) begin
		// reset
		cmd_flag <= 0;
	end
	else if (cmd_cnt == 'd2 && pi_flag == 1) begin
		cmd_flag <= 1;
	end
	else begin
		cmd_flag <= 1'b0;
	end
end



always @(posedge clk ) begin
	chn1_valid <= cmd_flag;
end

always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		chn1_data <= 0;
	end
	else if (cmd_flag == 1) begin
		chn1_data <= cmd_data;
	end
end


endmodule


// This is a simple example.
// You can make a your own header file and set its path to settings.
// (Preferences > Package Settings > Verilog Gadget > Settings - User)
//
//		"header": "Packages/Verilog Gadget/template/verilog_header.v"
//
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// -----------------------------------------------------------------------------
// Author : yongchan jeon (Kris) poucotm@gmail.com
// File   : uart_rx.v
// Create : 2023-03-31 11:40:44
// Revise : 2023-04-20 14:06:11
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
module uart_rx (
	input	wire					 clk,    
	input	wire					 rst_n, 
	input 	wire					 rx,  
	output  reg		[7:0]			po_data,
	output	reg						po_flag
	
);


reg 					rx1;
reg						rx2;
reg 					rx2_reg;
reg 					rx_flag;
reg 	[12:0]			cnt_baud;
reg 					bit_flag;
reg 	[3:0]			bit_cnt;


parameter	CNT_BAUD_MAX = 5207;
parameter   CNT_HALF_BAUD_MAX = 2603;
//rx1
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		rx1 <= 1'b1;
	end 
	else begin
		rx1 <= rx;
	end
end

//rx2
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		rx2 <= 1'b1;
	end 
	else begin
		rx2 <= rx1;
	end
end

//rx2_reg
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		rx2_reg <= 1'b1;
	end 
	else begin
		rx2_reg <= rx2;
	end
end
//rx_flag
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		rx_flag <= 1'b0;
	end 
	else if (bit_cnt == 'd8&&bit_flag==1'b1) begin
		rx_flag <= 1'b0;
	end
	else if(rx2==1'b0&&rx2_reg==1'b1)begin
		rx_flag <= 1'b1;
	end
	
end

//cnt_baud
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		cnt_baud <= 'd0;
	end 
	else if(bit_flag == 1'b1 && bit_cnt == 'd8)begin
		cnt_baud <= 'd0;
	end
	else if (cnt_baud == CNT_BAUD_MAX && rx_flag == 1'b1) begin
		cnt_baud <= 'd0;
	end
	else if (rx_flag == 1'b1) begin
		cnt_baud <= cnt_baud + 1'b1;
	end
end

//bit_flag
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		bit_flag <= 1'b0;
	end  
	else if(cnt_baud == CNT_HALF_BAUD_MAX && rx_flag == 1'b1)begin
		bit_flag <= 1'b1;
	end
	else begin
		bit_flag <= 1'b0;
	end
end

//bit_cnt
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		bit_cnt <= 'd0;
	end 
	else if(bit_flag == 1'b1 && bit_cnt == 'd8)begin
		bit_cnt <= 1'b0;
	end
	else if (bit_flag == 1'b1) begin
		bit_cnt <= bit_cnt + 1'b1;
	end
end

//po_data
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		po_data <= 'd0;
	end 
	else if(bit_cnt>= 'd1 && bit_flag == 1'b1)begin
		po_data <= {rx2_reg,po_data[7:1]};
	end
end

//po_flag
always @(posedge clk or negedge rst_n) begin 
	if(rst_n == 1'b0) begin
		po_flag <= 1'b0;
	end 
	else if(bit_cnt == 'd8 && bit_flag == 1'b1)begin
		po_flag <= 1'b1;
	end
	else  begin
		po_flag <= 1'b0;
	end
end

endmodule
相关推荐
FPGA_ADDA15 小时前
RFSOC27DR+VU13P 6U VPX板卡
fpga开发·信号处理·adda射频采集·rfsoc27dr·vu13p
ARM+FPGA+AI工业主板定制专家15 小时前
【JETSON+FPGA+GMSL】实测分享 | 如何实现激光雷达与摄像头高精度时间同步?
人工智能·数码相机·机器学习·fpga开发·机器人·自动驾驶
白码王子小张15 小时前
FPGA实现CIC抽取滤波器
fpga开发·vivado·xilinx·cic滤波器
沉默_是金16 小时前
2024年江苏省大学生电子设计竞赛 || 无线传输信号模拟系统
fpga开发
ARM+FPGA+AI工业主板定制专家16 小时前
Jetson AGX Orin+GMSL+AI视觉开发套件,支持自动驾驶,机器人,工业视觉等应用
人工智能·机器学习·fpga开发·机器人·自动驾驶
ARM+FPGA+AI工业主板定制专家19 小时前
【JETSON+FPGA+GMSL+AI】自动驾驶与移动机器人的摄像头如何实现高精度时间同步?
网络·人工智能·机器学习·fpga开发·cnn·自动驾驶
cycf1 天前
源同步接口(六)
fpga开发
电子凉冰1 天前
FPGA强化-简易电压表的设计与验证
fpga开发
国科安芯1 天前
抗辐照MCU芯片在低轨商业卫星原子钟中的适配与优化
单片机·嵌入式硬件·fpga开发·架构·risc-v