完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
实验要求:设计两个可综合的电路模块:第一个模块(M1)能把4位的并行数据转化为符合以下协议的串行数据流,数据流用scl和sda两条线传输,sclk为输入的时钟信号,data[3:0]为输入数据,ack为M1请求M0发送数据信号。第二个模块(M2)能够把串行数据流内的信息接收到,并转换为相应的16条信号线的高电平,即若数据为1,则第一条线路为高电平,数据为n,则第N条线路为高电平。M0为测试用信号模块。该模块接收M1发出的ack信号,并产生新的测试数据data[3:0],如图1所示。
图1 可综合模块结构及波形 通信协议:scl为不断输出的时钟信号,如果scl为高电平时,sda由高变低时刻,串行数据流开始;如果scl为高电平时,sda由低变高时刻,串行数据结束。sda信号的串行数据位必须在scl为低电平时变化,若变为高则为1,否则为零。 RTL级数据流:根据图1的可综合结构图,我们可以得到各模块之间的数据传输流程。 模块M1发送ack(高电平)信号 → 模块M0在检测到ack上升沿后,开始发送数据 → 模块M1在检测到ack为高电平之后开始数据。同时M1启动状态机将并行数据转化为串行数据,M2按照协议接收串行数据,进行处理并按照数据值在相应位输出高电平。图2,为M1和M2模块的RTL视图。 图2 M1和M2模块的RTL视图 时序:本题的时序可以分成三个部分进行理解,产生开始阶段、产生结束信号阶段、数据传输阶段。只要按照时序图,在scl相应的状态时,控制sda变化即可。 if(scl && ack) //generate start signal begin sdabuf <= 0; state <= bit1; end else begin state <= start; end bit1: if(!scl) //change data in low of scl begin sdabuf <= databuf[3]; state <= bit2; end else state <= bit1; bit2: if(!scl) //change data in low of scl begin sdabuf <= databuf[2]; state <= bit3; end else state <= bit2; bit3: if(!scl) //change data in low of scl begin sdabuf <= databuf[1]; state <= bit4; end else state <= bit3; bit4: if(!scl) //change data in low of scl begin sdabuf <= databuf[0]; state <= bit5; end else state <= bit4; bit5: if(!scl) begin sdabuf <= 0;//pull down the bus state <= stop; end else state <= bit5; stop: if(scl) begin sdabuf <= 1;//pull on the bus state <= IDLE; end else state <= stop; IDLE: begin link_sda <= 0;//drop out from bus ack <= 0; state <= ready; end 这个题目只有一个开关变量相对比较简单。 状态转换图:本想画张图,但感觉花1个小时画张并不实用的图,不如简单一些,用几个变量表达一下。 1.对于M1模块 parameter ready = 8'b0000_0000,//等待ack=1 start = 8'b0000_0001,//开始信号 bit1 = 8'b0000_0010,//第三位数 bit2 = 8'b0000_0100,//第二位数 bit3 = 8'b0000_1000,//第一位数 bit4 = 8'b0001_0000,//第0位数 bit5 = 8'b0010_0000,//为结束信号做准备 stop = 8'b0100_0000,//结束信号 IDLE = 8'b1000_0000;// 2.对于M2模块 开始信号和结束信号分别拥有单独的always进行检测,当满足条件时置位相应的标志位,然后开始传输数据。 always @ (negedge sda) if(scl) StartFlag <= 1; else if(EndFlag) StartFlag <= 0; always @ (posedge sda) if(scl) begin EndFlag <= 1; pdatabuf <= pdata;//得到数据,放入寄存器中.只有在接收完毕之后,patabuf才能得到数据 end else EndFlag <= 0; always @ (posedge scl) begin if(StartFlag) begin case(mstate) ***it0: begin mstate <= ***it1; pdata[3] <= sda; //$display("This is sdabit0"); end ***it1: begin mstate <= ***it2; pdata[2] <= sda; //$display("This is sdabit1"); end ***it2: begin mstate <= ***it3; pdata[1] <= sda; //$display("This is sdabit2"); end ***it3: begin mstate <= ***it4; pdata[0] <= sda; //$display("This is sdabit3"); end ***it4: begin mstate <= ***it0; //$display("Stop"); end default: mstate <= ***it0; endcase end//if else mstate <= ***it0;//这句话可以确保每次进入case时,首先进入***it0 end//always 虽然,看明白了这个状态机,但自己写时依然感觉力不从心。只能是多总结,多思考,多练习。 |
|
相关推荐
6 个讨论
|
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 18:20 , Processed in 0.679019 second(s), Total 57, Slave 46 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号