参考文献1
参考文献2
并行数据流转换为一种特殊串行数据流模块的设计:
设计两个可综合的电路模块,第一个模块(M1)能把4位的并行数据转换为符合以下协议的串行数据流,数据流用scl和sda两条线传输,sclk为输入的时钟信号,data[3:0]为输入数据,ack为M1请求M0发新数据信号。第二个模块(M2)能把串行数据流内的信息接收到,并转换为相应16条信号线的高电平,即若数据为1,则第一条线路为高电平,数据为n,则第N条线路为高电平。M0为测试用信号模块。该模块接收M1发出的ack信号,并产生新的测试数据[3:0].
第一个模块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时钟信号 产生串行输出时钟sclif(!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) beginlink_sda <= 0; // 把 sdabuf 与 sda 串行总线断开state <= ready;sdabuf <= 1; ack <= 0; // 请求新数据置0endelse begincase(state)ready: if(ack) // 并行数据已经到达beginlink_sda <= 1; // 把 sdabuf 与 sda 串行总线连接state <= start; // endelse // 并行数据尚未到达beginlink_sda <= 0; // 把 sda 总线让出,若前面把 sda 定义成双向串行总线,// 则此时 sda 可作为输入state <= ready;ack <= 1; // 请求新数据信号置 1 endstart: if(scl && ack) // 产生 sda 的开始信号beginsdabuf <= 0; // 在 sda 连接的前提下,输出开始信号state <= bit1;endelse state <= start;bit1: if(!scl) // 在 scl 为低电平时送出最高位 databuf[3]beginsdabuf <= databuf[3];state <= bit2;ack <= 0;endelse state <= bit1;bit2: if(!scl) // 在 scl 为低电平时送出次高位 databuf[2]beginsdabuf <= databuf[2];state <= bit3;endelse state <= bit2;bit3: if(!scl) // 在 scl 为低电平时送出次低位 databuf[1]beginsdabuf <= databuf[1];state <= bit4;endelse state <= bit3;bit4: if(!scl) // 在 scl 为低电平时送出最低位 databuf[0]beginsdabuf <= databuf[0];state <= bit5;endelse state <= bit4;bit5: if(!scl) // 为产生结束信号做准备,先把 sda 变为低beginsdabuf <= 0;state <= stop;endelse state <= bit5;stop: if(scl) // 在scl为高时,把 sda 由低变高 产生结束信号beginsdabuf <= 1;state <= idle;endelse state <= stop;idle: beginlink_sda <= 0; // 把 sdabuf 与 sda 串行总线脱开state <= ready;// sdabuf <= 1;end default: beginlink_sda <= 0;sdabuf <= 1;state <= ready; endendcaseendendmodule
模块功能: 按照协议接收串行数据,进行处理并按照数据值在相应位输出高电平;
本模块为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) beginendflag <= 1; // 串行数据 结束标志pdatabuf <= pdata; // 把收到的 4位数据 存入寄存器endelse 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) // 把收到的数据变为相应位的高电平begincase(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;endcaseendalways@(posedge scl) // 在检测到开始标志后, 每次 scl 正跳变 沿 时接收数据,共 4位if(startflag)case(mstate)sbit0: beginmstate <= sbit1;pdata[3] <= sda;$display("I am in sdabit0");endsbit1: beginmstate <= sbit2;pdata[2] <= sda;$display("I am in sdabit1");endsbit2: beginmstate <= sbit3;pdata[1] <= sda;$display("I am in sdabit2");endsbit3: beginmstate <= sbit4;pdata[0] <= sda;$display("I am in sdabit3"); endsbit4: beginmstate <= sbit0;$display("I am in sdastop");enddefault: mstate <= sbit0;endcaseelse mstate <= sbit0;endmodule
模块功能: 本模块产生测试信号对设计中的模块进行测试。
本模块只用于测试,不能通过综合转换为电路。
`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 beginrst = 1;#10 rst = 0;
#(`halfperiod * 2 + 3) rst = 1;endinitial beginsclk = 0;data = 0;
#(`halfperiod * 1000) $stop;endalways #(`halfperiod) sclk = ~sclk; // 产生第一个模块需要的输入时钟
// 每次请求新数据信号的整跳变沿,等一段时间后将输出数据增加1always@(posedge ask_for_data)#(`halfperiod/2 + 3) data = data + 1;
endmodule
模块功能: 对所设计的两个可综合模块
ptosda
和out16hi
进行联合测试。观察ptosda
模块能否正确地把并行数据转换成符合协议要求的串行码流;串行码流能否通过out16hi
模块的处理输出符合设计要求的信号。本模块是为教学需要专门设计的。为了使大家容易理解接口功能,作了许多简化,因此无实用价值。
模块说明: 本模块还可以用于综合或布局布线后的电路网表模块的测试。做后仿真时,把包括的文件改为布局布线后的门级电路文件,即由综合工具生成的
ptosda.vm
和out16hi.vm
文件,或布局布线工具产生的ptosda.vo
和out16hi.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