IIC协议的Verilog代码(1)——主机写模块开发
发布日期:2021-05-07 22:56:20 浏览次数:23 分类:精选文章

本文共 5298 字,大约阅读时间需要 17 分钟。

Verilog代码

//Module Name:IIC Write//Author:Yang Cheng Yu//Date:2020/4/21//==================defines=====================`define SIMmodule	iic_write(	//================System Signal================	input				clk				,	input				rst_n			,	//================Interface====================	output	reg 		scl				,	inout 				sda				,	output reg 			flag_wr			,	input				wr_req			,	output	reg 		flag_wr_done	,	input[6:0]			dev_addr		,	input[7:0]			data_wr			,	output reg[5:0]		state			);	//================parameters===================	parameter			SYS_FRE				=50_000_000;	parameter			IIC_FRE				=10_000;	`ifndef SIM	localparam			CNT_BAUD			=SYS_FRE/IIC_FRE;	localparam			CNT_BAUD_HALF		=CNT_BAUD/2;	`else	localparam			CNT_BAUD 			= 500;	localparam			CNT_BAUD_HALF 		= 250;	`endif	//state machine	localparam			S_IDLE				=6'b0000_01;	localparam			S_START				=6'b0000_10;	localparam			S_DEV_ADDR			=6'b0001_00;	localparam			S_ACK_DEV_ADDR		=6'b0010_00;	localparam			S_DATA				=6'b0100_00;	localparam			S_ACK_DATA			=6'b1000_00;	//================System regs==================	reg[15:0]			cnt_baud;	reg[2:0]			cnt_bit;	wire				flag_bit;	reg 				flag_start_bit;	reg 				SDA;	reg 				wr_req_t0;	reg 				wr_req_t1;	wire 				wr_req_trig;	reg 				flag_get_ack;	reg[6:0]			dev_addr_reg;	reg[7:0]			data_wr_reg;	//================Main Codes===================	//scl	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			scl <= 1'b1;		else if(flag_start_bit==1'b1&&flag_wr==1'b1)			scl <= 1'b1;		else if(flag_start_bit==1'b0&&flag_wr==1'b1)			if(cnt_baud<=CNT_BAUD_HALF-1)				scl <= 1'b0;			else if(cnt_baud>CNT_BAUD_HALF-1)				scl <= 1'b1;		else			scl <= 1'b1;	end		//flag_wr	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			flag_wr <= 1'b0;		else if(flag_wr==1'b0&&wr_req_trig==1'b1)			flag_wr <= 1'b1;		else if(state==S_ACK_DATA&&flag_bit==1'b1)			flag_wr <= 1'b0;	end		//sda		assign sda = (state==S_ACK_DATA||state==S_ACK_DEV_ADDR)?1'bz:SDA;	//cnt_baud	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			cnt_baud <= 'd0;		else if(flag_start_bit==1'b1&&flag_wr==1'b1)			if(cnt_baud==CNT_BAUD_HALF-1)				cnt_baud <= 'd0;			else				cnt_baud <= cnt_baud + 1'b1;		else if(flag_start_bit==1'b0&&flag_wr==1'b1)			if(cnt_baud==CNT_BAUD-1)				cnt_baud <= 'd0;			else				cnt_baud <= cnt_baud + 1'b1;		else			cnt_baud <= 'd0;	end		//cnt_bit	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			cnt_bit <= 'd0;		else case(state)			S_IDLE:cnt_bit <= 'd0;					S_START:cnt_bit <= 'd0;			S_DEV_ADDR:begin				if(cnt_bit==3'd7&&flag_bit==1'b1)					cnt_bit <= 'd0;				else if(flag_bit==1'b1)					cnt_bit <= cnt_bit + 1'b1;			end			S_ACK_DEV_ADDR:cnt_bit <= 'd0;			S_DATA:begin				if(cnt_bit==3'd7&&flag_bit==1'b1)					cnt_bit <= 'd0;				else if(flag_bit==1'b1)					cnt_bit <= cnt_bit + 1'b1;			end			S_ACK_DATA:cnt_bit <= 'd0;		endcase	end		//flag_bit	assign flag_bit = (cnt_baud==CNT_BAUD-1)?1'b1:1'b0;	//flag_start_bit	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			flag_start_bit <= 1'b0;		else if(flag_wr==1'b0&&wr_req_trig==1'b1)			flag_start_bit <= 1'b1;		else if(flag_start_bit==1'b1&&cnt_baud==CNT_BAUD_HALF-1)			flag_start_bit <= 1'b0;	end		//state machine	always	@(posedge clk or negedge rst_n)begin		if(rst_n==1'b0)			state <= S_IDLE;		else case(state)			S_IDLE:begin				if(wr_req_trig==1'b1)					state <= S_START;				else					state <= S_IDLE;			end			S_START:begin				if(cnt_baud==CNT_BAUD_HALF-1)					state <= S_DEV_ADDR;				else					state <= S_START;			end			S_DEV_ADDR:begin				if(cnt_bit==3'd7&&flag_bit==1'b1)					state <= S_ACK_DEV_ADDR;				else					state <= S_DEV_ADDR;			end			S_ACK_DEV_ADDR:begin				if(cnt_baud

Test Bench

`timescale	1ns/1ns		//时间精度`define clock_period 20	//时钟周期module tb_iic_write;	//实体名称	//state machine	localparam			S_IDLE				=6'b0000_01;	localparam			S_START				=6'b0000_10;	localparam			S_DEV_ADDR			=6'b0001_00;	localparam			S_ACK_DEV_ADDR		=6'b0010_00;	localparam			S_DATA				=6'b0100_00;	localparam			S_ACK_DATA			=6'b1000_00;//=====================
<系统端口>
============================= reg clk ; reg rst_n ;//=====================
<外设端口>
============================= wire scl ; wire sda ; wire flag_wr ; reg wr_req ; wire flag_wr_done ; reg[6:0] dev_addr ; reg[7:0] data_wr ; wire[5:0] state ; assign sda = (state==S_ACK_DATA||state==S_ACK_DEV_ADDR)?1'b1:1'bz; iic_write iic_write_inst( //================System Signal================ .clk (clk), .rst_n (rst_n), //================Interface==================== .scl (scl), .sda (sda), .flag_wr (flag_wr), .wr_req (wr_req), .flag_wr_done (flag_wr_done), .dev_addr (dev_addr), .data_wr (data_wr), .state (state));//=====================
<时钟信号>
=============================initial begin clk = 1; forever #(`clock_period/2) clk = ~clk;end//=====================
<复位信号>
=============================initial begin rst_n = 0;#(`clock_period*20+1); rst_n = 1;end//=====================
<激励信号>
=============================initial begin dev_addr = 7'b011_0101; data_wr = 8'h00; wr_req = 0; #(`clock_period*20+1);//初始化 data_wr = 8'h56; #20; wr_req = 1; #20; wr_req = 0; #20_0000; data_wr = 8'h78; dev_addr = 7'b100_1010; #20; wr_req = 1; #20; wr_req = 0;end endmodule

波形图

在这里插入图片描述

上一篇:FPGA的矩阵键盘驱动( 修正版)
下一篇:SPI主机的Verilog代码及验证(优化版)

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月02日 02时36分15秒