网站后台服务,网站建设的前期投入,怎么把网站源码,打开网站说建设中是什么问题?文章目录 前言1. 结构2.代码2.1 iic_slave.v2.2 sync.v2.3 wr_fsm.v2.3.1 状态机状态解释 2.4 ram.v 3. 波形展示4. 建议5. 资料总结 前言
首先就不啰嗦iic协议了#xff0c;网上有不少资料都是叙述此协议的。
下面将是我本次设计的一些局部设计汇总#xff0c;如果对读者有… 文章目录 前言1. 结构2.代码2.1 iic_slave.v2.2 sync.v2.3 wr_fsm.v2.3.1 状态机状态解释 2.4 ram.v 3. 波形展示4. 建议5. 资料总结 前言
首先就不啰嗦iic协议了网上有不少资料都是叙述此协议的。
下面将是我本次设计的一些局部设计汇总如果对读者有借鉴意义那最好如果没有的话也无所谓互相交流而已。这是我早期的版本注释比较少代码编写比较混乱读者自便
希望读者发现问题可在下方留言我会及时回答或者修改。 1. 结构 顶层结构图 master结构图 slave结构图 2.代码
2.1 iic_slave.v
timescale 1ns/1psmodule iic_slave (input rstn,input clk,input scl,inout sda,input [7:0] q, // RAM data to slaveoutput wen,output [7:0] d, // Slave data to RAMoutput [7:0] a // Slave address to RAM
);// Internal signals
wire sync_scl_1;
wire sync_sda_1;
wire sda_posedge;
wire sda_negedge;
wire scl_posedge;
wire scl_negedge;
wire sda_out;
wire sda_oen;// Three-state gate for SDA
assign sda (sda_oen) ? sda_out : 1bz;// Instantiate sync module
sync sync (.clk(clk),.rstn(rstn),.scl(scl),.sda(sda),.sync_scl_1(sync_scl_1),.sync_sda_1(sync_sda_1),.sda_posedge(sda_posedge),.sda_negedge(sda_negedge),.scl_posedge(scl_posedge),.scl_negedge(scl_negedge)
);// Instantiate RAM module
ram ram (.clk(clk),.rstn(rstn),.d(d),.a(a),.q(q),.wen(wen)
);// Instantiate write FSM module
wr_fsm wr_fsm (.clk(clk),.rstn(rstn),.sync_scl_1(sync_scl_1),.sync_sda_1(sync_sda_1),.scl_posedge(scl_posedge),.scl_negedge(scl_negedge),.sda_posedge(sda_posedge),.sda_negedge(sda_negedge),.d(d),.a(a),.q(q),.wen(wen),.sda_out(sda_out),.sda_oen(sda_oen)
);endmodule2.2 sync.v
timescale 1ns/1ps
module sync (rstn,clk,scl,sda,sync_scl_1,sync_sda_1,sda_posedge,sda_negedge,scl_posedge,scl_negedge
);input rstn;input clk;input scl;input sda;output sync_scl_1;output sync_sda_1;output sda_posedge;output sda_negedge;output scl_posedge;output scl_negedge;reg sync_scl_1;reg sync_sda_1;reg sync_scl_0;reg sync_sda_0;always (posedge clk or negedge rstn) beginif (!rstn) beginsync_scl_1 1b0;sync_sda_1 1b0;sync_scl_0 1b0;sync_sda_0 1b0;end else beginsync_scl_0 scl;sync_sda_0 sda;sync_scl_1 sync_scl_0;sync_sda_1 sync_sda_0;endendassign sda_posedge (sync_sda_0) (~sync_sda_1);assign sda_negedge (~sync_sda_0) (sync_sda_1);assign scl_posedge (sync_scl_0) (~sync_scl_1);assign scl_negedge (~sync_scl_0) (sync_scl_1);endmodule2.3 wr_fsm.v
timescale 1ns/1ps
module wr_fsm (rstn,clk,sync_scl_1,sync_sda_1,scl_posedge,scl_negedge,sda_posedge,sda_negedge,q,d,a,wen,sda_out,sda_oen
);input rstn, clk;input sync_scl_1;input sync_sda_1;input scl_posedge;input scl_negedge;input sda_posedge;input sda_negedge;input [7:0] q;output [7:0] d;output [7:0] a;output wen;output sda_out;output sda_oen;reg wen; // write and read flags regreg [7:0] scl_cnt; // clk delay counterreg [3:0] bit_cnt; // valid transfer bytereg [7:0] a; // a save word addr, shift data to ramreg sda_out; // data out regreg sda_oen; // three state gate flag bitreg [7:0] save_ctrl; // store ctrl wordreg [7:0] save_q_data; // store data of qwire [7:0] q;parameter slave_addr 7b1101101; // parameter slave addrparameter scl_cnt_max 60-1;reg [3:0] state; // state transformparameter idle 4d0,w_start 4d1,w_ctrl 4d2,ack1 4d3,w_addr 4d4,ack2 4d5,w_data 4d6,ack3 4d7,r_start 4d8,r_ctrl 4d9,ack4 4d10,r_data 4d11,ack5 4d12,stop 4d13;always (posedge clk or negedge rstn)beginif (!rstn) beginstate idle;sda_oen 1b0;sda_out 1b1;scl_cnt 8b0;bit_cnt 4b0;sda_out 1b0;end else begincase (state)idle: begin// Initialize state and signalsstate w_start;sda_oen 1b0;sda_out 1b1;scl_cnt 8b0;bit_cnt 4b0;sda_out 1b0;endw_start: begin// Wait for start conditionif (sync_scl_1 sda_negedge)beginstate w_ctrl;bit_cnt 4d8;endelsestate w_start;endw_ctrl: begin// Control word transferif (scl_negedge)beginsave_ctrl {save_ctrl[6:0], sync_sda_1};bit_cnt bit_cnt - 1;if (bit_cnt 4d0)beginstate ack1;bit_cnt 4d8;endelsestate w_ctrl;endelsestate w_ctrl;endack1: begin// Acknowledge control wordif (save_ctrl[7:1] slave_addr)beginscl_cnt scl_cnt 8b1;if (scl_cnt scl_cnt_max 2)beginsda_out 0;sda_oen 1;state ack1;endelse if (scl_cnt (scl_cnt_max 2) scl_cnt_max)beginstate w_addr;sda_oen 0;scl_cnt 8b0;bit_cnt 4d7;endelsestate ack1;endelsestate stop;endw_addr: begin// Write addressif (scl_negedge)beginbit_cnt bit_cnt - 4b1;wen save_ctrl[0]; // write operationa {a[6:0], sync_sda_1};if (bit_cnt 4d0)beginbit_cnt 4d7;state ack2;endelsestate w_addr;endelsestate w_addr;endack2: begin// Acknowledge addressscl_cnt scl_cnt 8b1;if (scl_cnt scl_cnt_max 2)beginsda_out 1b0;sda_oen 1b1;state ack2;endelse if (scl_cnt (scl_cnt_max 2) scl_cnt_max)beginsda_oen 1b0;scl_cnt 8b0;if (wen 0) // decide write or readstate w_data;elsestate r_start;endelsestate ack2;endw_data: begin// Write dataif (scl_negedge)begind {d[6:0], sync_sda_1};bit_cnt bit_cnt - 4b1;if (bit_cnt 4d0)beginbit_cnt 4d7;state ack3;endelsestate w_data;endelsestate w_data;endack3: begin// Acknowledge datascl_cnt scl_cnt 8b1;if (scl_cnt scl_cnt_max 2)beginsda_out 0;sda_oen 1b1;state ack3;endelse if (scl_cnt (scl_cnt_max 2) scl_cnt_max)beginsda_oen 1b0;scl_cnt 8b0;state stop;endelsestate ack3;endr_start: begin// Read start conditionif (sync_scl_1 sda_negedge)beginsda_oen 1b0;bit_cnt 4d8;state r_ctrl;endelsestate r_start;endr_ctrl: begin// Read control wordif (scl_negedge)beginbit_cnt bit_cnt - 4b1;save_ctrl {save_ctrl[6:0], sync_sda_1};if (bit_cnt 4d0)beginwen save_ctrl[0];bit_cnt 4d7;state ack4;endelsestate r_ctrl;endelsestate r_ctrl;endack4: begin// Acknowledge control wordif (save_ctrl[7:1] slave_addr)beginscl_cnt scl_cnt 8b1;if (scl_cnt scl_cnt_max 2)beginsda_out 0;sda_oen 1;state ack4;endelse if (scl_cnt (scl_cnt_max 2) scl_cnt_max)beginsda_oen 1b0;scl_cnt 8b0;if (wen)beginstate r_data;sda_oen 1b1;sda_out sync_sda_1;endelsestate w_data;endelsestate ack4;endelsestate stop;endr_data: begin// Read dataif (scl_negedge)beginsave_q_data q[7:0];bit_cnt bit_cnt - 4b1;sda_out save_q_data[7];if (bit_cnt 4d0)beginstate ack5;bit_cnt 4d7;sda_oen 0;endelsebeginstate r_data;sda_oen 1;save_q_data {save_q_data[6:0], 1b0};endendelsestate r_data;endack5: begin// Acknowledge dataif (scl_posedge)beginif (sync_sda_1 1)state stop;elsestate idle;endelsestate ack5;endstop: begin// Stop conditionif (sync_scl_1 sda_posedge)beginstate idle;sda_oen 1b0;sda_out 1b1;endelsestate stop;enddefault: state idle;endcaseendend
endmodule
2.3.1 状态机状态解释
当然可以以下是优化后的代码中每个状态的作用解释
reg [3:0] state; // state transform
parameter idle 4d0,w_start 4d1,w_ctrl 4d2,ack1 4d3,w_addr 4d4,ack2 4d5,w_data 4d6,ack3 4d7,r_start 4d8,r_ctrl 4d9,ack4 4d10,r_data 4d11,ack5 4d12,stop 4d13;状态作用解释
idle (4’d0):
作用: 初始状态等待复位信号或起始条件。描述: 在这个状态下所有信号被初始化状态机等待复位信号 rstn 或起始条件sync_scl_1 和 sda_negedge。
w_start (4’d1):
作用: 等待起始条件。描述: 在这个状态下状态机检测起始条件sync_scl_1 和 sda_negedge。如果检测到起始条件状态机进入 w_ctrl 状态。
w_ctrl (4’d2):
作用: 接收控制字。描述: 在这个状态下状态机接收控制字save_ctrl并将其存储在寄存器中。控制字的接收通过 scl_negedge 信号完成。当接收到完整的控制字后状态机进入 ack1 状态。
ack1 (4’d3):
作用: 发送 ACK 信号。描述: 在这个状态下状态机发送 ACK 信号sda_out 和 sda_oen。如果接收到的控制字匹配从设备地址slave_addr状态机进入 w_addr 状态。否则状态机进入 stop 状态。
w_addr (4’d4):
作用: 接收地址。描述: 在这个状态下状态机接收地址数据a并将其存储在寄存器中。地址的接收通过 scl_negedge 信号完成。当接收到完整的地址后状态机进入 ack2 状态。
ack2 (4’d5):
作用: 发送 ACK 信号。描述: 在这个状态下状态机发送 ACK 信号sda_out 和 sda_oen。根据控制字中的写入标志wen状态机决定进入 w_data 状态写入数据或 r_start 状态读取数据。
w_data (4’d6):
作用: 写入数据。描述: 在这个状态下状态机接收数据d并将其存储在寄存器中。数据的接收通过 scl_negedge 信号完成。当接收到完整的数据后状态机进入 ack3 状态。
ack3 (4’d7):
作用: 发送 ACK 信号。描述: 在这个状态下状态机发送 ACK 信号sda_out 和 sda_oen。然后状态机进入 stop 状态。
r_start (4’d8):
作用: 等待读取起始条件。描述: 在这个状态下状态机检测读取起始条件sync_scl_1 和 sda_negedge。如果检测到起始条件状态机进入 r_ctrl 状态。
r_ctrl (4’d9):
作用: 接收控制字。描述: 在这个状态下状态机接收控制字save_ctrl并将其存储在寄存器中。控制字的接收通过 scl_negedge 信号完成。当接收到完整的控制字后状态机进入 ack4 状态。
ack4 (4’d10):
作用: 发送 ACK 信号。描述: 在这个状态下状态机发送 ACK 信号sda_out 和 sda_oen。如果接收到的控制字匹配从设备地址slave_addr状态机进入 r_data 状态。否则状态机进入 stop 状态。
r_data (4’d11):
作用: 读取数据。描述: 在这个状态下状态机读取数据q并将其存储在寄存器中。数据的读取通过 scl_negedge 信号完成。当读取完数据后状态机进入 ack5 状态。 13。 ack5 (4’d12):作用: 发送 ACK 信号。描述: 在这个状态下状态机发送 ACK 信号sda_out 和 sda_oen。然后状态机进入 idle 状态。
stop (4’d13):
作用: 停止状态。描述: 在这个状态下状态机等待停止条件sync_scl_1 和 sda_posedge。如果检测到停止条件状态机进入 idle 状态。
每个状态的作用如下
idle: 初始状态等待复位或起始条件。w_start: 等待起始条件。w_ctrl: 接收控制字。ack1: 发送 ACK 信号确认控制字接收。w_addr: 接收地址。ack2: 发送 ACK 信号确认地址接收。w_data: 写入数据。ack3: 发送 ACK 信号确认数据写入。r_start: 等待读取起始条件。r_ctrl: 接收控制字。ack4: 发送 ACK 信号确认控制字接收。r_data: 读取数据。ack5: 发送 ACK 信号确认数据读取。stop: 停止状态等待停止条件。
这些状态共同构成了一个完整的 I2C 从设备写入和读取的有限状态机确保数据的正确传输和接收。
2.4 ram.v
timescale 1ns/1ps
module ram (clk,rstn,d,a,q,wen
);// Input portsinput clk, rstn;input [7:0] a; // Address inputinput [7:0] d; // Data inputinput wen; // Write enable// Output portsoutput [7:0] q; // Data output// Internal registersreg [7:0] ram [255:0]; // RAM arrayinteger i; // Loop counterreg [7:0] q; // Output data register// Always block for RAM operationsalways (posedge clk or negedge rstn)beginif (!rstn) begin// Initialize RAM on resetfor (i 0; i 255; i i 1)ram[i] 8b0;end else beginif (!wen) begin// Write operation: wen 0ram[a] d;end else begin// Read operation: wen 1q ram[a];endendendendmodule
3. 波形展示 4. 建议
必看 此设计还存在一些问题后续有时间我会完善的。
在同步的时候我建议还是使用两个寄存器缓冲而不是使用一个使用多个更加的稳妥一些我这个就是使用了较少的寄存器缓冲所以波形中有问题。我把这段字打个红色背景。是因为在边沿检测的时候无法确认信号是否同步还是异步所以在设计的时候还是使用双寄存器进行消除亚稳态。
5. 资料总结
练习时的一些思路。
https://blog.csdn.net/weixin_46163885/article/details/107170689