时序逻辑电路实践练习1

题目一
1、并行数据流转换为一种特殊串行数据流模块,即把输入的4位并行数据转换为协议要求的串行数据流。

分析:设计成两个可综合的电路模块,第一个模块能把四位的并行数据转换为符合以下协议的串行数据流,数据流用scl和sda两条线传输,sclk为时钟信号,data[3:0]为输入数据,ack为模块1请求模块0发新数据信号。
第二个模块则是接收数据模块,并将数据转换为相应16信号线的高电平,即若数据为1,第一条信号线为高电平,数据为n,则第n条线为高电平.
模块0为测试模块,用于接收模块一的ack和产生新的输入数据data[3:0]

通信协议:scl为不断输出的时钟信号,如果scl为高电平,sda由高变低时刻,串行数据流开始,sda由低变高,串行数据流结束。 sda信号的串行数据位必须在scl为低电平时变化,若变高则为1,否则为0
模块1代码

module ptosda(rst,sclk,ack,scl,sda,data);
  input sclk,rst;
  input [3:0] data;
  output ack,scl,sda;
  
  reg scl,ack,link_sda,sdabuf;
  reg [3:0] databuf;
  reg [7:0] state;
  
  assign sda = link_sda?sdabuf:1`b0;//控制sdabuf输出到串行总线上
  
  
  parameter ready = 8`b0000_0000,
            start = 8`b0000_0001,
      bit1  = 8`b0000_0010,
      bit2  = 8`b0000_0100,
      bit3  = 8`b0000_1000,
      bit4  = 8`b0001_0000,
      bit5  = 8`b0010_0000,      
      stop  = 8`b0100_0000,
      IDEA = 8`b1000_0000;
      
      
  always@(posedge sclk or negedge rst)
  begin 
       if(!rst)
     sck<=1;//因为sda只在scl低电平时变化有效,所以复位将它拉高
     else
     scl = ~scl;
    end
  
  always@(posedge ack)//发出ack请求新数据时把老数据存起来
  databuf <=data;
  
  //主状态机:产生控制信号
  always @(negedge sclk or negedge rst)
  if(!rst)
  begin
  link_sda <=0;
  state <=ready;
  sdabuf<=1;
  ack<=0;
  end
  else begin
  case(state)
  ready: if(ack)
           begin 
       link_sda<=1;//把sdabuf与sda串行总线连接       
       state<=start;
       end
      else
                begin 
                  link_sda<=0;
      state<=ready;
      ack<=1;
      end
      
  start: if(scl&&ack)//sda开始传输
           begin 
       sdabuf<=0;//在sda连接的前提下输出开始信号
       state = bit1;
       end
     else state<=start;
  bit1: if(!scl)//时钟为低电平时送出最高位
           begin 
      sdabuf<=databuf[3];
      state<=bit2;
      ack<=0;
     end
     else state<=bit1;
  bit2: if(!scl)
           begin 
     sdabuf<=databuf[2];
     state<=bit3;
     end
    else state <= bit2;
  bit3: if(!scl)
           begin
     sdabuf<=databuf[1];
     state<=bit4;
     end
     else state <= bit3;
  bit4: if(!scl)
           begin
     sdabuf<=databuf[0];
     state<=bit5;
     end
     else state <= bit4;
     //四位并行数据传送完
  bit5: if(!scl)
       begin
     sdabuf <=0;//把sda拉低
     state<=stop;
     end
     else state<=bit5;
  stop: if(scl)//在scl为高时,sda由低变高表示结束
       begin
     sdabuf <=1;//把sda拉高
     state<=IDLe;
     end
     else state<=stop;
  IDLe: begin
           link_sda<=0;//把sdabuf与sda串行总线脱开
     
     state<=ready;
     end
     
  default :begin
            link_sda<=0;
      sdabuf<=1;
      state<=ready;
      end
      endcase
      end
      endmodule

模块2代码

module out16hi(scl,sda);
  input scl,sda;
  output [15:0]outhigh;
  reg [5:0] mstate;
  reg[3:0]pdata,pdatabuf;
  reg [15:0]outhigh;
  reg startflag,endflag;
  //clk为高时,sda由高变低表示串行数据流开始
  always@(negedge sda)
    begin
     if(scl)
     begin
      startflag<=1;
    end
    else if(endflag)
    startflag<=0;
   end
   //clk为高时,sda由低变高表示串行数据流结束
  always@(posedge sda)
     if(scl)
        begin
      endflag<=1;//串行数据结束
      pdatabuf<=pdata;//把收到的四位数据存入寄存器
      end
   else
     endflag<=0;//数据接收还没有结束
     
  parameter ready=6`b00_0000;
            sbit0=6`b00_0001;
       sbit1=6`b00_0010;
        sbit2=6`b00_0100;
       sbit3=6`b00_1000;
        sbit4=6`b01_0000;
        
  always@(pdatabuf)//把收到的数据转换成相应的高电平
    begin
      case (pdatabuf) 
      4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    4`b0001:outhigh = 16`b0000_0000_0000_0001
    endcase
    end
    
  always@(posedge scl)
         if(startflag)
        case(mstate)
       sbit0:begin
               mstate<=sbit1;
         pdata[3]<=sda;
         $display("i am in sdabit0");
        end
       sbit1:begin
               mstate<=sbit2;
         pdata[2]<=sda;
         $display("i am in sdabit1");
        end
       sbit2:begin
               mstate<=sbit3;
         pdata[1]<=sda;
         $display("i am in sdabit2");
        end
       sbit3:begin
               mstate<=sbit4;
         pdata[0]<=sda;
         $display("i am in sdabit3");
        end
      sbit4:begin
               mstate<=sbit0;
        
         $display("i am in sdastop");
        end
         default: mstate<=sbit0;
     endmodule         
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值