BMP280之IIC写部分的 verilog代码

下面为写部分代码

module bmp280_wr(
	input	wire		sclk,//system clock 100MHz
	input	wire		rst,//system reset,active high
	input	wire		start,//starting  signal for  sending datas
	input	wire[7:0]	regaddr,//register address
	input	wire[7:0]	data,//data to be send
	output	reg 		send_ok,
	output	reg 		send_fail, 
	output	reg 		wr_scl,//400kHz clock for slave device
	output	wire 		wr_sdo,//define slave device address bit[0]=111011_bit[0]
	inout 	wire		wr_sda //iic data port for input and output
);

	
	parameter	SCLKCNT_MAX=250-1;//100_000_000/400_000=250 for 400kHz scl

	parameter	IDLE =4'b0001;
	parameter	START=4'b0010;
	parameter	SEND =4'b0100;
	parameter	STOP =4'b1000;

	reg [3:0]	state;
	reg [7:0]	sclk_cnt;
	reg [6:0]	slave_addr;
	reg 		sda_r;
	reg 		oe;
	reg [3:0]	bit_cnt;
	reg [3:0]	byte_cnt;
	reg [23:0]	data_temp;

	always @(posedge sclk) begin
		if (rst==1'b1) begin
			data_temp<='d0;
		end
		else if (start==1'b1) begin
			data_temp<={slave_addr,1'b0,regaddr,data};
		end
		else if(state==SEND && bit_cnt!='d8 && sclk_cnt=='d0)begin
			data_temp<=data_temp<<1;
		end
		
	end

	always @(*) begin
		oe=(bit_cnt=='d8)?1'b0:1'b1;
	end

	assign wr_sda = (oe==1'b1)?sda_r:1'bz;

	assign wr_sdo = 1'b0;//slave device address 1110_110

	always @(posedge sclk) begin
		if (rst==1'b1) begin
			slave_addr<='d0;
		end
		else if (wr_sdo==1'b1) begin
			slave_addr<=7'b1110_111;
		end
	    else begin
	        slave_addr<=7'b1110_110;
	    end
	end

	//sclk_cnt
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			sclk_cnt<='d0;
		end
		else if ((state==IDLE) || (sclk_cnt==SCLKCNT_MAX)) begin
			sclk_cnt<='d0;
		end
	    else begin
	        sclk_cnt<=sclk_cnt+1'b1;
	    end
	end

	//bit_cnt
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			bit_cnt<='d0;
		end
		if(state!=SEND)begin
			bit_cnt<='d0;
		end
		else if (state==SEND && sclk_cnt==SCLKCNT_MAX) begin
			if(bit_cnt=='d8)begin
				bit_cnt<='d0;
			end
			else begin
				bit_cnt<=bit_cnt+1'b1;
			end
		end
	end

	//byte_cnt
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			byte_cnt<='d0;
		end
		else if (state==SEND) begin
			if(byte_cnt=='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)
				byte_cnt<='d0;
			else if(byte_cnt!='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)begin
				 byte_cnt<=byte_cnt+1'b1;
			end
		end
	    else begin
	    	byte_cnt<='d0;
	    end
	end
	
	//state
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			state<=IDLE;
		end
		else  begin
			case(state)
				IDLE:begin
					if(start==1'b1)begin
						state<=START;
					end
				end
				START:begin
					if(sclk_cnt==SCLKCNT_MAX)begin
						state<=SEND;
					end
				end
				SEND:begin
					if(bit_cnt=='d8 && sclk_cnt==(SCLKCNT_MAX>>1) && wr_sda==1'b1)begin
						state<=IDLE;
					end
					else if(byte_cnt=='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)begin
						state<=STOP;
					end
				end
				STOP:begin
					if(sclk_cnt==SCLKCNT_MAX)begin
						state<=IDLE;
					end
				end
				default:state<=IDLE;
			endcase
		end
	end

	//sda_r
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			sda_r<=1'b1;
		end
		else begin
			case(state)
				START:begin
					if(sclk_cnt>(SCLKCNT_MAX>>1))begin
						sda_r<=1'b0;
					end
					else begin
						sda_r<=1'b1;
					end
				end
				SEND:begin
					if(bit_cnt!='d8 && sclk_cnt=='d0)begin
						sda_r<=data_temp[23];
					end
				end
				STOP:begin
					if(sclk_cnt>((SCLKCNT_MAX>>1)+(SCLKCNT_MAX>>2)))begin
						sda_r<=1'b1;
					end
					else begin
						sda_r<=1'b0;
					end
				end
				default:sda_r<=1'b1;
			endcase
		end
	end

	//wr_scl
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			wr_scl<=1'b1;
		end
		else begin
			case(state)
				START:begin
					if(sclk_cnt==SCLKCNT_MAX)begin
						wr_scl<=1'b0;
					end
					else begin
						wr_scl<=1'b1;
					end
				end
				SEND:begin
					if(sclk_cnt==SCLKCNT_MAX)begin
						wr_scl<=1'b0;
					end
					else if(sclk_cnt==(SCLKCNT_MAX>>1))begin
						wr_scl<=1'b1;
					end
				end
				STOP:begin
					if(sclk_cnt=='d0)begin
						wr_scl<=1'b0;
					end
					else if(sclk_cnt==(SCLKCNT_MAX>>1))begin
						wr_scl<=1'b1;
					end
				end
				default:wr_scl<=1'b1;
			endcase
		end
	end
	//send_fail
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			send_fail<=1'b0;
		end
		else if (state==SEND && bit_cnt=='d8 && sclk_cnt==(SCLKCNT_MAX>>1) && wr_sda==1'b1) begin
			send_fail<=1'b1;
		end
	    else begin
	        send_fail<=1'b0;
	    end
	end
	//send_ok
	always @(posedge sclk) begin
		if (rst==1'b1) begin
			send_ok<=1'b0;
		end
		else if (state==STOP && sclk_cnt==SCLKCNT_MAX) begin
			send_ok<=1'b1;
		end
	    else begin
	        send_ok<=1'b0;
	    end
	end

endmodule 

接着就是写代码仿真文件:


`timescale 1ns/1ns

module tb_bmp280_wr (); /* this is automatically generated */

	// 
	reg 		clk;
	reg       	rst;
	reg       	start;
	reg [7:0] 	regaddr;
	reg [7:0] 	data;
	wire       	send_ok;
	wire       	send_fail;
	wire       	wr_scl;
	wire       	wr_sdo;
	wand       	wr_sda;

	reg 		wr_sda_r;

	initial begin
		clk = 0;
		forever #(5) clk = ~clk;
	end

	// synchronous reset
	initial begin
		rst = 1;
		start=0;
		regaddr=0;
		data=0;
		repeat(100)@(posedge clk)
		rst = 0;
		repeat(100)@(posedge clk);
		send(8'hf5,8'h55);
		send(8'hf4,8'haa);
		$stop;
	end

	bmp280_wr inst_bmp280_wr (
			.sclk      (clk),
			.rst       (rst),
			.start     (start),
			.regaddr   (regaddr),
			.data      (data),
			.send_ok   (send_ok),
			.send_fail (send_fail),
			.wr_scl    (wr_scl),
			.wr_sdo    (wr_sdo),
			.wr_sda    (wr_sda)
		);
	
	task send;
		input [7:0] regaddr_r;
		input [7:0] data_r; 
		begin
			start=0;
			regaddr=regaddr_r;
			data=data_r;
			@(negedge clk) start=1;
			@(negedge clk) start=0;
			@(posedge send_ok or posedge send_fail);
			#1000;
		end
	endtask

	always @(posedge clk) begin
		if (rst==1'b1) begin
			wr_sda_r<=1'b1;
		end
		else if ( inst_bmp280_wr.bit_cnt==8) begin
			wr_sda_r<=1'b0;
		end
		else begin
			wr_sda_r<=1'b1;
		end
	end

	assign wr_sda = wr_sda_r;

endmodule

仿真波形:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值