• 方法2—并行数据流转换为一种特殊串行数据流模块的设计,


    参考文献1,并行数据流转换为一种特殊串行数据流模块的设计
    参考文献2,Vivado解决仿真不出波形的问题(并行数据流转串行数据流)

    并行数据流转换为一种特殊串行数据流模块的设计:
    设计两个可综合的电路模块,第一个模块(M1)能把4位的并行数据转换为符合以下协议的串行数据流,数据流用scl和sda两条线传输,sclk为输入的时钟信号,data[3:0]为输入数据,ack为M1请求M0发新数据信号。第二个模块(M2)能把串行数据流内的信息接收到,并转换为相应16条信号线的高电平,即若数据为1,则第一条线路为高电平,数据为n,则第N条线路为高电平。M0为测试用信号模块。该模块接收M1发出的ack信号,并产生新的测试数据[3:0].

    在这里插入图片描述

    1,第一个可综合模块,M1。

    第一个模块M1能把4位的并行数据转换为符合以下协议的串行数据流,数据流用scl和sda两条线传输,sclk 为输入的时钟信号,data[3:0]为输入数据,ack为M1请求M0发新数据信号。

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

    模块功能,按照设计要求,把输入的 4位 并行数据转换为 协议要求的串行数据流,并由scl 和sda配合输出
    本模块为RTL 可综合模块,已通过综合后 门级网表 仿真

    `timescale 1ns / 1ps
    //
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2022/11/21 11:25:20
    // Design Name: 
    // Module Name: ptosda
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //
    
    
    // 并行数据流转换为一种特殊串行数据流模块的设计
    // 模块功能,按照设计要求,把输入的 4位 并行数据转换为 协议要求的串行数据流,
    // 并由scl 和sda配合输出
    // 本模块为RTL 可综合模块,已通过综合后 门级网表 仿真
    
    module ptosda(rst, sclk, ack, scl, sda, data);
    input  sclk, rst;
           // sclk,输入的时钟信号
    
    input  [3:0] data;     // 并行口数据输入
    output ack;            // 请求新的转换数据
    output scl;            // 通信协议,scl为不断输出的时钟信号
                                  // scl是1, sda由1变0,串行数据流开始;
                                  // scl是0, sda由0变1,串行数据流结束;
    
    output sda;            // 定义sda为单向的串行输出
    // inout sda;
    
    reg    scl, link_sda, ack, sdabuf;      // 不断输出时钟信号
                      // 连接 sda        // 设计 一个寄存器
                   // ask_for_new_data
                        // sda 缓存器      // 设计 一个寄存器  
    
    reg  [3:0] databuf;         // 数据 缓存器 ,用来接收 data 数据
    reg  [7:0] state;           // 状态
    
    
    out16hi m2(.scl(scl), .sda(sda), .outhigh());
    assign sda = link_sda?sdabuf:1'b0;   // link_sda 控制 sdabuf 输出到串行总线上
    // assign sda = link_sda?sdabuf:1'bz;  // link_sda 控制 sdabuf 输出到双向串行总线上
    
    parameter  ready = 8'b0000_0000,     // 设计  9个  状态参数
                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,
                idle  = 8'b1000_0000;
      
    always@(posedge sclk or negedge rst)   // 由输入的  sclk时钟信号  产生串行输出时钟scl
      if(!rst)
              scl <= 1;
      else 
              scl <= ~scl;
    
    always@(posedge ack)   // 请求新数据时 存入 并行总线上 要转换的数据
              databuf <= data;
    
    // 主状态机,产生控制信号,根据databuf 中保存的数据,按照协议产生sda串行信号
    
    // always@(posedge sclk or negedge rst)
    always@(negedge sclk or negedge rst)
      if(!rst)  begin
               link_sda <= 0;       // 把 sdabuf 与 sda 串行总线断开
               state    <= ready;
               sdabuf   <= 1;  
               ack      <= 0;       // 请求新数据置0
         end
      else begin
      	  case(state)
      	    ready: if(ack)    // 并行数据已经到达
      	           begin
      	                 link_sda <= 1;    // 把 sdabuf 与 sda 串行总线连接
      	                 state    <= start;    // 
      	            end
      	           else       // 并行数据尚未到达
      	            begin
      	                  link_sda <= 0;    // 把 sda 总线让出,若前面把 sda 定义成双向串行总线,
      	                                    // 则此时 sda 可作为输入
    
      	                  state    <= ready;
      	                  ack      <= 1;	  // 请求新数据信号置 1 
      	            end
      	    start: if(scl && ack)     // 产生 sda 的开始信号
      	            begin
      	           	      sdabuf   <= 0;    // 在 sda 连接的前提下,输出开始信号
      	           	      state    <= bit1;
      	            end
      	           else 
      	                  state   <= start;
      	    bit1:   if(!scl)          // 在 scl 为低电平时送出最高位 databuf[3]
      	             begin
      	              	   sdabuf <= databuf[3];
      	              	   state  <= bit2;
      	              	   ack    <= 0;
        	         end
        	        else 
        	                state <= bit1;
        	bit2:   if(!scl)          // 在 scl 为低电平时送出次高位 databuf[2]
        	          begin
        	          	   sdabuf <= databuf[2];
        	          	   state  <= bit3;
        	          end
        	        else 
        	               state  <= bit2;
            bit3:   if(!scl)          // 在 scl 为低电平时送出次低位 databuf[1]
                      begin
                      	   sdabuf <= databuf[1];
                      	   state  <= bit4;
                      end
                    else 
                           state   <= bit3;
            bit4:   if(!scl)          // 在 scl 为低电平时送出最低位 databuf[0]
                      begin
                      	   sdabuf <= databuf[0];
                      	   state  <= bit5;
                      end
                    else 
                           state  <= bit4;
            bit5:   if(!scl)          // 为产生结束信号做准备,先把 sda 变为低
                      begin
                      	   sdabuf <= 0;
                      	   state  <= stop;
                      end
                    else 
                           state  <= bit5;
            stop:   if(scl)          // 在scl为高时,把 sda 由低变高 产生结束信号
                      begin
                      	   sdabuf <= 1;
                      	   state  <= idle;
                      end
                    else 
                           state  <= stop;
            idle:     begin
            	            link_sda <= 0;        // 把 sdabuf 与 sda 串行总线脱开
            	            state    <= ready;
               	  //          sdabuf   <= 1;
                      end 
            default:  begin
                            link_sda <= 0;
                            sdabuf   <= 1;
                            state    <= ready;	
                      end
            endcase
         end
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162

    2,描述M2模块

    模块功能: 按照协议接收串行数据,进行处理并按照数据值在相应位输出高电平;
    本模块为RTL可综合模块,已通过综合后门级网表仿真。

    `timescale 1ns / 1ps
    //
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2022/11/21 11:29:07
    // Design Name: 
    // Module Name: out16hi
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //
    
    // 描述 M2 模块的Verilog 代码
    // 模块功能,按照协议接收 串行数据,进行处理 并按照数据值 在相应位 输出高电平
    // 本模块为 RTL可综合模块,已通过综合后 门级网表仿真
    
    module out16hi(scl, sda, outhigh);
    
    input         scl, sda;   // 串行数据输入
    output [15:0] outhigh;   // 根据输入的串行数据设置高电平位
    reg    [5:0]  mstate;    // synthesis preserve*/;
            // 本模块的主状态
            //  /* synthesis preserve*/ 为综合指令, 使综合器布局布线后仍能保留状态信号,
            // 以便于观察,不同的综合器综合指令并不相同,必须参考综合器的技术资料才能掌握
    // 
    
    reg [3:0] pdata,  pdatabuf;
                               // 记录串行数据位时, 用寄存器和最终数据寄存器
    
    reg [15:0] outhigh;     // 输出 位寄存器;
    
    reg  startflag, endflag; // 数据开始和结束标志
    
    //   always@(posedge sda)
    always@(negedge sda)
       if(scl)
               startflag <= 1;     // 串行数据开始标志
       else if(endflag)
               startflag <= 0;
    
    always@(posedge sda)
       if(scl)  begin
                       endflag   <= 1;        //  串行数据 结束标志
                       pdatabuf  <= pdata;    // 把收到的 4位数据 存入寄存器
                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@( padabuf)         // 把收到的数据变为相应位的高电平
    always@(pdatabuf)        // 把收到的数据变为相应位的高电平
        begin
        	case(pdatabuf)
        	    4'b0001: outhigh = 16'b0000_0000_0000_0001;
        	    4'b0010: outhigh = 16'b0000_0000_0000_0010;
        	    4'b0011: outhigh = 16'b0000_0000_0000_0100;
        	    4'b0100: outhigh = 16'b0000_0000_0000_1000;
    
        	    4'b0101: outhigh = 16'b0000_0000_0001_0000;
        	    4'b0110: outhigh = 16'b0000_0000_0010_0000;
        	    4'b0111: outhigh = 16'b0000_0000_0100_0000;
        	    4'b1000: outhigh = 16'b0000_0000_1000_0000;
    
        	    4'b1001: outhigh = 16'b0000_0001_0000_0000;
        	    4'b1010: outhigh = 16'b0000_0010_0000_0000;
        	    4'b1011: outhigh = 16'b0000_0100_0000_0000;
        	    4'b1100: outhigh = 16'b0000_1000_0000_0000;
    
        	    4'b1101: outhigh = 16'b0001_0000_0000_0000;
        	    4'b1110: outhigh = 16'b0010_0000_0000_0000;
        	    4'b1111: outhigh = 16'b0100_0000_0000_0000;
        	    4'b0000: outhigh = 16'b1000_0000_0000_0000;
            endcase
        end
    
    always@(posedge scl)    // 在检测到开始标志后, 每次 scl 正跳变 沿 时接收数据,共 4位
       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;
           endcase
        else 
                       mstate <= sbit0;
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    3,描述M0模块的Verilog代码

    模块功能: 本模块产生测试信号对设计中的模块进行测试。
    本模块只用于测试,不能通过综合转换为电路。

    `timescale 1ns / 1ps
    //
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2022/11/21 14:03:48
    // Design Name: 
    // Module Name: sigdata
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //
    
    // 描述 M0 模块的 Verilog代码如下:
    // 模块功能:本模块产生测试信号对设计中的模块进行测试
    // 本模块只用于测试,不能通过综合转换为电路
    `timescale 1ns/1ns
    `define halfperiod 50
    module sigdata(rst, sclk, data, ask_for_data
    	);
    output    rst;             // 复位信号
    output    [3:0] data;      // 输出的数据信号
    output    sclk;            // 输出的时钟信号
    input     ask_for_data;    // 从并串转换器来的请求数据信号
    
    reg       rst, sclk;
    reg       [3:0] data;
    
    initial  begin
                     	   rst = 1;
                     #10   rst = 0;
    #(`halfperiod * 2 + 3) rst = 1;
    
    end
    
    initial  begin
    	sclk = 0;
    	data = 0;
    #(`halfperiod * 1000) $stop;
    
    end
    
    always #(`halfperiod)  sclk = ~sclk;    // 产生第一个模块需要的输入时钟
    // 每次请求新数据信号的整跳变沿,等一段时间后将输出数据增加1
    
    always@(posedge ask_for_data)
      #(`halfperiod/2 + 3) data = data + 1;
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    4,描述顶层模块

    模块功能: 对所设计的两个可综合模块ptosdaout16hi进行联合测试。观察ptosda模块能否正确地把并行数据转换成符合协议要求的串行码流;串行码流能否通过out16hi模块的处理输出符合设计要求的信号。本模块是为教学需要专门设计的。为了使大家容易理解接口功能,作了许多简化,因此无实用价值。

    模块说明: 本模块还可以用于综合或布局布线后的电路网表模块的测试。做后仿真时,把包括的文件改为布局布线后的门级电路文件,即由综合工具生成的ptosda.vmout16hi.vm文件,或布局布线工具产生的ptosda.voout16hi.vo文件。为了能使门级电路网表模块进行仿真,有时还需要包括一个布线所用的FPGA或ASIC基本元件仿真库模块

    `timescale 1ns / 1ps
    //
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2022/11/21 14:05:43
    // Design Name: 
    // Module Name: top
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //
    
    
    // 描述顶层模块的 Verilog代码如下:
    // top.v
    
    // 模块功能:对所设计的两个可综合模块 ptosda 和 out16hi 进行联合测试
    // 观察 ptosda 模块能否正确地把 并行数据转换成 符合协议要求的串行码流;
    // 串行码流能否通过 out16hi 模块的处理输出符合设计要求的信号。
    // 本模块是为教学需要专门设计的。
    // 为了使大家容易理解接口功能,作了许多简化,因此无 实用价值
    
    // 模块说明:本模块还可以用于综合或布局布线后的电路网表模块的测试。
    // 做后仿真时, 把包括的文件 改为 布局布线后的 门级电路网表文件,即由综合工具生成的
    // pstosda.vo 和 out16hi.vo 文件。
    // 为了能使门级电路网表模块进行仿真,有时还需要包括一个布线所用的FPGA 或 ASIC 
    // 基本元件仿真库模块
    
    // `timescale 1ns/1ns
    
    `include "sigdata.v"
    `include "ptosda.v"
    `include "out16hi.v"
    
    
    // 可用综合后产生的 门级 Verilog网表(netlist)文件 和 布局布线后产生的带延迟参数的Verilog 网表
    // (netlist)文件来代替上面两个文件。 分别进行门级后仿真和布线后仿真。
    // 这两种文件的扩展名不同,但都是Verilog门级模块
    
    module top;
    wire   [3:0] data;
    wire   sclk;
    wire   scl;
    wire   sda;
    wire   rst;
    wire  [15:0] outhigh;
    
    sigdata m0(.rst(rst), .sclk(sclk), .data(data), .ask_for_data(ack));
    ptosda  m1(.rst(rst), .sclk(sclk), .ack(ack), .scl(scl), .sda(sda), .data(data));
    out16hi m2(.scl(scl), .sda(sda), .outhigh(outhigh));
    
    
    endmodule 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    5,电路生成的门级网表,netlist

    在这里插入图片描述

    6,前仿真波形验证

    在这里插入图片描述

  • 相关阅读:
    Python150题day10
    递归算法(及其衍生算法:缓存,分治,回溯)
    Jmeter_逻辑控制器
    【离散数学】第三章 测试
    leetcode:152. 乘积最大子数组
    ES选举:Elasticsearch中Master选举完全解读
    git学习
    软件测试简历投递小技巧,百分百避免已读不回,成功入职增加30%
    Unity-2D游戏-打击感与敌人AI
    Sybase连接详解
  • 原文地址:https://blog.csdn.net/qq_21952195/article/details/127963760