精华内容
下载资源
问答
  • 具有串行并行数据转换功能的是
    万次阅读
    2017-07-24 12:04:16

    这篇文章写一下今天早上设计的并行数据到串行数据的转换器,也算是对并行总线和串行总线一个小小的应用,编码过程中也用到了task。

    该转换器主要实现的功能是:

    1、把并行地址存入寄存器

    2、把并行数据存入寄存器

    3、连接串行单总线

    4、地址的串行输出

    5、数据的串行输出

    6、挂起串行单总线

    7、给信号源应答

    8、让信号源给出下一个操作对象

    9、结束写操作

    该设计利用嵌套的状态机实现,主状态机分为四个状态:idle,addr_write,data_write,stop,主状态机中会涉及到任务shift8out的调用,该任务主要实现并行数据到串行数据的转换,也是由一个状态机实现。下面给出整个设计的代码:

    设计代码:

    ///并串转换器//
    module ps_convertor(clk,rst,data,addr,sda,ack);
    parameter idle=4'b0001,addr_write=4'b0010,data_write=4'b0100,stop=4'b1000;//独热编码
    parameter sh8_start=9'b00000_0001;
    parameter bit6     =9'b00000_0010;
    parameter bit5     =9'b00000_0100;
    parameter bit4     =9'b00000_1000;
    parameter bit3     =9'b00001_0000;
    parameter bit2     =9'b00010_0000;
    parameter bit1     =9'b00100_0000;
    parameter bit0     =9'b01000_0000;
    parameter sh8_stop =9'b10000_0000;
    
              
    input clk,rst;
    input [7:0]addr,data;
    inout sda;//串行总线
    output ack;//应答信号将输入测试模块
    
    reg ack;
    
    reg link_write;//写开关
    reg [7:0] sh8out_buf;//并行总线缓冲器
    
    reg [3:0] mstate;//主状态机的状态寄存器
    reg [8:0] sh8_state;//并串转换状态机状态寄存器
    
    reg FF;//标志寄存器,用来表示任务是否完成
    
    assign sda=(link_write)?sh8out_buf[7]:1'hz;//串行总线数据传输
    
    always@(posedge clk)
    begin
     if(!rst)//同步复位
     begin
      mstate<=idle;
      link_write<=0;
      FF<=0;
      sh8out_buf<=0;
      //sh8_state<=sh8_start;
      ack<=0;
     end
     else 
     begin
     case (mstate)
      idle: begin
             mstate<=addr_write;
    		 link_write<=0;
    		 FF<=0;
    		 sh8out_buf<=addr;
    		 sh8_state<=sh8_start;
    		 ack<=0;
            end
      addr_write: 
            begin
    		 if(FF==0)
    		  begin
    		   shift8out;
    		  end
    		 else 
    		  begin
    		   FF<=0;
    		   mstate<=data_write;
    		   sh8out_buf<=data;
    		   sh8_state<=sh8_start;
    		  end
    		end
      data_write:
            begin
    		 if(FF==0)
    		  begin
    		   shift8out;
    		  end
    		 else 
    		  begin
    		   FF<=0;
    		   mstate<=stop;
    		   ack<=1;
    		  end
    		end
      stop: begin
             ack<=0;
    		 mstate<=idle;
            end
      //default: mstate<=idle;       
     endcase
     end
    end
    //并串转换模块
    task shift8out;
     begin
      case(sh8_state)
       sh8_start: begin
                   link_write<=1;
    			   sh8_state<=bit6;
                  end
       bit6:      begin
                   //link_write<=1;
                   sh8_state<=bit5;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit5:      begin
                   sh8_state<=bit4;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit4:      begin
                   sh8_state<=bit3;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit3:      begin
                   sh8_state<=bit2;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit2:      begin
                   sh8_state<=bit1;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit1:      begin
                   sh8_state<=bit0;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       bit0:      begin
                   sh8_state<=sh8_stop;
    			   sh8out_buf<=sh8out_buf<<1;
                  end
       sh8_stop: begin 
                  FF<=1;
    			  sh8_state<=sh8_start;
    			  link_write<=0;
    			 end
    			  
      endcase
     end
    endtask
    
    endmodule
    

    测试模块:

    `timescale 1ns/1ns
    `define half_cycle 10
    module signal;
    reg clk,rst;
    reg [7:0]data,addr;
    wire sda,ack;
    always #(`half_cycle) clk=~clk;
    initial 
    begin
      rst=1;
      clk=0;
      data=8'b1010_1010;
      addr=0;
      #100 rst=0;
      #100 rst=1;
      #(200* `half_cycle)$stop;
    end
    
    always @(posedge ack)
    begin
     data=data+1;
     addr=addr+1;
    end
     ps_convertor m(clk,rst,data,addr,sda,ack);
    endmodule
    


    最终在modelsim中得到的仿真图如下:



    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    更多相关内容
  • 51单片机Proteus仿真实例 串行数据转换并行数据51单片机Proteus仿真实例 串行数据转换并行数据51单片机Proteus仿真实例 串行数据转换并行数据51单片机Proteus仿真实例 串行数据转换并行数据51单片机Proteus...
  • 单片机C语言程序设计 并行数据转换串行数据(有源码)单片机C语言程序设计 并行数据转换串行数据(有源码)单片机C语言程序设计 并行数据转换串行数据(有源码)单片机C语言程序设计 并行数据转换串行数据(有...
  • 最新单片机仿真 串行数据转换并行数据最新单片机仿真 串行数据转换并行数据最新单片机仿真 串行数据转换并行数据最新单片机仿真 串行数据转换并行数据最新单片机仿真 串行数据转换并行数据最新单片机仿真 ...
  • 单片机C语言程序设计43 串行数据转换并行数据(基于8051+Proteus仿真)单片机C语言程序设计43 串行数据转换并行数据(基于8051+Proteus仿真)单片机C语言程序设计43 串行数据转换并行数据(基于8051+Proteus...
  • 它包含两个功能—— 1.ser2par : 将串行数据转换为并行数据2.par2ser : 将并行数据转换串行数据
  • 单片机C语言程序设计 串行数据转换并行数据(有源码)单片机C语言程序设计 串行数据转换并行数据(有源码)单片机C语言程序设计 串行数据转换并行数据(有源码)单片机C语言程序设计 串行数据转换并行数据(有...
  • 51单片机Proteus仿真实例 并行数据转换串行数据51单片机Proteus仿真实例 并行数据转换串行数据51单片机Proteus仿真实例 并行数据转换串行数据51单片机Proteus仿真实例 并行数据转换串行数据51单片机Proteus...
  • 名称:串行数据转换并行数据 说明:串行数据由 RXD 发送给串 并转换芯片 74164,TXD 则用于输出移位时钟脉冲,74164 将串行输入的 1 字节转换为并行数据,并将转换的数据通过 8 只 LED 显示出来。本例串口工作...
  • 最新单片机仿真 并行数据转换串行数据最新单片机仿真 并行数据转换串行数据最新单片机仿真 并行数据转换串行数据最新单片机仿真 并行数据转换串行数据最新单片机仿真 并行数据转换串行数据最新单片机仿真 ...
  • 单片机C语言程序设计44 并行数据转换串行数据(基于8051+Proteus仿真)单片机C语言程序设计44 并行数据转换串行数据(基于8051+Proteus仿真)单片机C语言程序设计44 并行数据转换串行数据(基于8051+Proteus...
  • 名称:并行数据转换串行数据 说 明 : 切 换 连 接 到 并 串 转 换 芯 片74LS165 的拨码开关,该芯片将并行数据以串行方式发送到 8051 的 RXD 引脚,移位脉冲由 TXD 提供,显示在 P0 口。
  • 单片机并行数据转换串行数据,比赛练习案例,仿真实例,现成调用封装使用,可运行的仿真电路图和调好的程序,开箱即用。适用于教学案例、毕业设计、电子设计比赛、出书项目实例,实际设计、个人DIY参考。 已调试好...
  • 单片机串行数据转换并行数据,比赛练习案例,仿真实例,现成调用封装使用,可运行的仿真电路图和调好的程序,开箱即用。适用于教学案例、毕业设计、电子设计比赛、出书项目实例,实际设计、个人DIY参考。 已调试好...
  • 并行数据转换串行数据.zip
  • 串行数据转换并行数据.zip
  • 摘要:串行并行接口模式是A/D转换器诸多分类中的一种,但却是应用中器件选择的一个重要指标。在同样的转换分辨率及转换速度的前提下,不同的接口方式不但影响了电路结构,更重要的是将在高速数据采集的过程中对...
  • 基于89C51单片机/89C52单片机通用的并行数据转换串行数据,Proteus软件测试运行环境7.8版本,包含内容:keil vision5项目文件、C语言程序源码、hex后缀编译文件、DSN仿真后缀文件项目
  • 44 并行数据转换串行数据.zip
  • 并行数据转换串行数据.rar,44 并行数据转换串行数据,Keil C,并行数据转换串行数据,并行数据转换串行数据.hex,code,44.M51,44.LST,44.OBJ,44.Opt,44_Uv2.Bak,44.lnp,44.Uv2,44,44.c,44.plg,并行数据转换为...
  • 摘要:串行并行接口模式是A/D转换器诸多分类中的一种,但却是应用中器件选择的一个重要指标。在同样的转换分辨率及转换速度的前提下,不同的接口方式不但影响了电路结构,更重要的是将在高速数据采集的过程中对...
  • 43 串行数据转换并行数据.zip
  • 串行数据转换并行数据.rar,43 串行数据转换并行数据,串行数据转换并行数据.PWI,code,43.M51,43.LST,43.lnp,43.Uv2,43_Uv2.Bak,43.Opt,43.plg,43.c,43,43.OBJ,Keil C,串行数据转换为并行.hex,串行数据转换为...
  • protues串行数据转换并行数据很经典。
  • 并行数据转换串行数据_74ls165 由拨马开关控制并行数据状态,通过74LS165转串口输出 在由8位LED灯的亮灭来显示当前的拨码开关的状态 源程序+Proteus的仿真文件 可以帮助你很好的学习哦
  • 利用单片机的串行口和I/O 端口串行输出,利用74LS164移位转换并行数据,接在LED灯上显示。74LS164置于通用插座上。
  • 模块功能:接收串行数据,转为并行数据。 应用场景:在SPI,Uart等串行协议接收侧均有应用。 二. 模块框图与使用说明 有两种模式(通过参数SDATA_IS_CONTINUOUS进行选择): 1.数据连续模式,此时sdata_valid指示...

    一. 模块功能与应用场景

    模块功能:接收串行数据,转为并行数据。

    应用场景:在SPI,Uart等串行协议接收侧均有应用。

    二. 模块框图与使用说明

    Verilog功能模块-串行数据转并行数据-1

    有两种模式(通过参数SDATA_IS_CONTINUOUS进行选择):

    1.数据连续模式,此时sdata_valid指示有效数据开始,在并行数据接收完成前,后面数据均有效。输入时序如下图。

    Verilog功能模块-串行数据转并行数据-2

    2.数据不连续模式,此时sdata_valid指示当前数据有效。输入时序如下图。

    Verilog功能模块-串行数据转并行数据-3

    注意:

    1.sdata与sdata_valid应同步有效,且因为代码中有同步处理,所以这两者不需要与sclk的某边沿同步

    2.sdata应从最高位开始发

    2.第一组数据和第二组数据之间的间隔可以为0~N个时钟周期,即可以连续发不间隔,也可以有任意间隔。

    三. 模块代码

    /*
     * @Author       : Xu Dakang
     * @Email        : XudaKang_up@qq.com
     * @Date         : 2021-04-24 12:27:11
     * @LastEditors  : Xu Dakang
     * @LastEditTime : 2021-04-25 21:08:14
     * @Filename     : sdata2pdata.sv
     * @Description  : 输入串行数据,输出并行数据,实现串转并
    */
    
    
    
    module sdata2pdata
    #(
      parameter PDATA_WIDTH = 24,
      parameter SDATA_IS_CONTINUOUS = 0
    )(
      output logic [PDATA_WIDTH-1 : 0] pdata,
      output logic                     pdata_valid,
    
      input  logic                     sdata,
      input  logic                     sdata_valid,
    
      input  logic                     sclk,
    
      input  logic rstn
    );
    
    
    
    //< 输入信号同步 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    logic sdata_r1;
    logic sdata_r2;
    logic sdata_r3;
    always_ff @(posedge sclk) begin
      sdata_r1 <= sdata;
      sdata_r2 <= sdata_r1;
      sdata_r3 <= sdata_r2;
    end
    
    
    logic sdata_valid_r1;
    logic sdata_valid_r2;
    always_ff @(posedge sclk) begin
      sdata_valid_r1 <= sdata_valid;
      sdata_valid_r2 <= sdata_valid_r1;
    end
    //< 输入信号同步 ------------------------------------------------------------
    
    
    
    //> 串行数据计数 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    logic [$clog2(PDATA_WIDTH+1)-1 : 0] sdata_cnt;
    
    logic sdata_cnt_en;
    always_ff @(posedge sclk, negedge rstn) begin
      if (~rstn)
        sdata_cnt_en <= '0;
      else if (SDATA_IS_CONTINUOUS)
        if (sdata_valid_r2 && (sdata_cnt == '0 || sdata_cnt == PDATA_WIDTH - 1 || sdata_cnt ==  PDATA_WIDTH))
          sdata_cnt_en <= 1'b1;
        else if (~sdata_valid_r2 && sdata_cnt ==  PDATA_WIDTH - 1)
          sdata_cnt_en <= 1'b0;
        else
          sdata_cnt_en <= sdata_cnt_en;
      else
        sdata_cnt_en <= sdata_valid_r2;
    end
    
    
    always_ff @(posedge sclk, negedge rstn) begin
      if (~rstn)
        sdata_cnt <= '0;
      else if (sdata_cnt_en)
        if (sdata_cnt == PDATA_WIDTH) // 数据有效时,一组数据刚转换完成,下一组的第一个数据来了,计为1
          sdata_cnt <= 'b1;
        else //! 数据有效时,一组数据还未转换完成,计数加1
          sdata_cnt <= sdata_cnt + 1'b1;
      else if (sdata_cnt == PDATA_WIDTH) // 一组数据转换完成,下一组数据没马上来,回到0
        sdata_cnt <= '0;
      else
        sdata_cnt <= sdata_cnt;
    end
    //> 串行数据计数 ------------------------------------------------------------
    
    
    
    //< 生成输出 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    logic [PDATA_WIDTH-1 : 0] pdata_temp; // pdata的计算中间值
    always_ff @(posedge sclk, negedge rstn) begin
      if (~rstn)
        pdata_temp <= '0;
      else if (sdata_cnt_en)
        pdata_temp <= {pdata_temp[PDATA_WIDTH-2 : 0], sdata_r3};
      else
        pdata_temp <= pdata_temp;
    end
    
    
    always_ff @(posedge sclk, negedge rstn) begin
      if (~rstn)
        pdata <= '0;
      else if (sdata_cnt == PDATA_WIDTH)
        pdata <= pdata_temp;
      else
        pdata <= pdata;
    end
    
    
    always_ff @(posedge sclk, negedge rstn) begin
      if (~rstn)
        pdata_valid <= '0;
      else if (sdata_cnt == PDATA_WIDTH)
        pdata_valid <= 1'b1;
      else
        pdata_valid <= '0;
    end
    //< 生成输出 ------------------------------------------------------------
    
    
    
    endmodule
    

    四. testbench

    /*
     * @Author       : Xu Dakang
     * @Email        : XudaKang_up@qq.com
     * @Date         : 2021-04-24 12:27:28
     * @LastEditors  : Xu Dakang
     * @LastEditTime : 2021-04-25 21:05:02
     * @Filename     : sdata2pdata_tb.sv
     * @Description  : testbench of sdata2pdata
    */
    
    
    
    module sdata2pdata_tb ();
    
    timeunit 1ns;
    timeprecision 10ps;
    
    localparam PDATA_WIDTH = 5;
    localparam SDATA_IS_CONTINUOUS = 1;
    
    logic [PDATA_WIDTH-1 : 0] pdata;
    logic                     pdata_valid;
    
    logic                     sdata;
    logic                     sdata_valid;
    logic                     sclk;
    logic                     rstn;
    
    
    
    // 实例化模块
    sdata2pdata #(
      .PDATA_WIDTH (PDATA_WIDTH),
      .SDATA_IS_CONTINUOUS (SDATA_IS_CONTINUOUS)
    ) sdata2pdata_inst(.*);
    
    
    
    // 产生测试数据 最大值 2^PDATA_WIDTH-1
    localparam NUM = 15;
    logic [PDATA_WIDTH-1 : 0] pdata_list [NUM];
    initial begin
      for (int i = 0; i < NUM; i++) begin
        pdata_list[i] = {$random()} % (2**PDATA_WIDTH);
      end
    end
    
    
    
    // 生成时钟
    localparam CLKT = 2;
    initial begin
      sclk = 0;
      forever #(CLKT / 2) sclk = ~sclk;
    end
    
    
    
    // 数据连续模式
    initial begin
      if (SDATA_IS_CONTINUOUS == 1) begin
        rstn = 0;
        sdata_valid = 0;
        #(CLKT * 2)  rstn = 1;
        for (int i = 0; i < NUM; i++) begin
          sdata_valid = 1;
          for (int j = 0; j < PDATA_WIDTH; j++) begin
            sdata = pdata_list[i][PDATA_WIDTH-1-j];
            #(CLKT) sdata_valid = 0;
          end
          #(CLKT * ({$random} % 3)) ; // 数据连续模式时,可在各组数据间插入随机时钟间隔
        end
    
        #(CLKT * 10) $stop;
      end
    end
    
    
    // 数据不连续模式
    initial begin
      if (SDATA_IS_CONTINUOUS == 0) begin
        rstn = 0;
        sdata_valid = 0;
        #(CLKT * 2)  rstn = 1;
        for (int i = 0; i < NUM; i++) begin
          for (int j = 0; j < PDATA_WIDTH; j++) begin
            sdata = pdata_list[i][PDATA_WIDTH-1-j];
            sdata_valid = 1;
            #CLKT ;
            sdata_valid = 0;
            #(CLKT * ({$random} % 3)) ; // 数据不连续模式时,可在同组数据间插入随机时钟间隔
          end
          sdata_valid = 0;
          #(CLKT * ({$random} % 3)) ;
        end
    
        #(CLKT * 10) $stop;
      end
    end
    
    
    
    endmodule
    

    五. 仿真验证

    仿真工具:Vivado 2020.2 Simulator。

    数据连续模式,从结果可以看出,串转并输出正确。

    image-20210425212255013

    数据不连续模式,同样正确。

    image-20210425212515021

    六. 工程分享

    sdata2pdata 串转并模块 vivado 2020.2工程.7z

    链接:https://pan.baidu.com/s/1wBCLjYqcjj0HGm_S9O5iOQ
    提取码:j3z4

    展开全文
  • 单片机C语言程序设计44 并行数据转换串行数据(基于8051 Proteus仿真).rar

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,622
精华内容 20,248
热门标签
关键字:

具有串行并行数据转换功能的是

友情链接: guiyihua.zip