学员作品(为AS5600编码器建立模型)

Posted by

我们学员在项目中需要编码盘来了解电机的位置,工程中采用了AS5600,该编码盘采用I2C接口来传输当前位置,theta角度。在设计FPGA与编码盘通信的代码中需要AS5600的模型,网上没有公开资料,我们开发了以上资料。模型对FPGA开发过程中的重要性不言而喻,需要的朋友可以与我们联系沟通。

我们在这篇文章贴出部分代码,以供参考。

`timescale 1ns/1ns
`define timeslice 380
module model_as5600(
scl,
sda
);
input scl; 
inout sda; 
reg out_flag; 
reg[7:0] memory[15:0]; 		//宽度为8 :menmory数量16
reg[7:0]register_addr; 				//寄存器地址
reg[7:0]memory_buf; 			//缓存
reg[7:0]sda_buf; 				//sda数据缓存
reg[7:0]shift; 					//移位寄存器
reg[7:0]addr_byte; 			
reg[7:0]ctrl_byte; 				//设备地址
reg[1:0]State;					//状态
integer i;						//integer整型(不可综合)
reg sda_state;

//设备地址
parameter
	r = 8'b01101101, w = 8'b01101100;
assign sda = (out_flag == 1) ? sda_buf[7] : 1'bz;

initial
begin
addr_byte = 0;
ctrl_byte = 0;
out_flag = 0;
sda_buf = 0;
State = 2'b00;
memory_buf = 0;
register_addr = 0;
shift = 0;
for(i=0;i<=15;i=i+1)
memory[i] = i;
end
always@(negedge sda)
begin
if(scl == 1)
begin
State = State + 1;
if(State == 2'b11)
disable write_to_as5600;  //disable 不能
end
@(negedge scl) sda_state = 1;
#`timeslice sda_state = 0;

end

always@(posedge sda_state)
begin
	if(scl == 1) 
		stop_W_R;
else
	begin
	casex(State)
		2'b01:begin
			read_in;
	if( ctrl_byte == w)
	begin
		State = 2'b10;
		write_to_as5600; 
	end
	else
		State = 2'b00;
	end
		2'b11:
			read_from_as5600;
	default:
		State = 2'b00;
	endcase
	end
end 
task stop_W_R;
begin
State = 2'b00;
addr_byte = 0;
ctrl_byte = 0;
out_flag = 0;
sda_buf = 0;
end
endtask

task read_in;
begin
shift_in(ctrl_byte);
shift_in(addr_byte);
end
endtask

task write_to_as5600;
begin
shift_in(memory_buf);
register_addr =  addr_byte;
memory[register_addr] = memory_buf;
State = 2'b00;
end
endtask

task read_from_as5600;
begin
shift_in(ctrl_byte);
if( ctrl_byte == r)
	begin
		register_addr =  addr_byte;
		sda_buf = memory[register_addr];
shift_out;
State = 2'b00;
end
end
endtask

task shift_in;
	output[7:0]shift;
	begin
		@(posedge scl) shift[7] = sda;
		@(posedge scl) shift[6] = sda;
		@(posedge scl) shift[5] = sda;
		@(posedge scl) shift[4] = sda;
		@(posedge scl) shift[3] = sda;
		@(posedge scl) shift[2] = sda;
		@(posedge scl) shift[1] = sda;
		@(posedge scl) shift[0] = sda;
		@(negedge scl)
	begin
	#(`timeslice);   ////延时看是否上拉电阻有效
		out_flag = 1;
		sda_buf = 0;
	end
	@(negedge scl)
	begin
		#(`timeslice-60);
		out_flag = 0;
	end
	end
endtask
task shift_out;
begin
out_flag = 1;
for(i=6; i>=0; i=i-1)
begin
@(negedge scl);
#`timeslice;
sda_buf = sda_buf << 1;  //读数据高位往低读
end
@(negedge scl) #`timeslice sda_buf[7] = 1;
@(negedge scl) #`timeslice out_flag = 0;
end
endtask
endmodule

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

我们将24小时内回复。
取消