Verilog HDL设计练习进阶(十)
2012-12-20
标签:

练习十. 通过模块之间的调用实现自顶向下的设计

目的:学习状态机的嵌套使用实现层次化、结构化设计。

现代硬件系统的设计过程与软件系统的开发相似,设计一个大规模的集成电路的往往由模块多层次的引用和组合构成。层次化、结构化的设计过程,能使复杂的系统容易控制和调试。 在Verilog HDL中,上层模块引用下层模块与C语言中程序调用有些类似,被引用的子模块在综合时作为其父模块的一部分被综合,形成相应的电路结构。在进行模块实例引用时,必须注意的是模块之间对应的端口,即子模块的端口与父模块的内部信号必须明确无误地一一对应,否则容易产生意想不到的后果。

下面给出的例子是设计中遇到的一个实例,其功能是将并行数据转化为串行数据送交外部电路编码,并将解码后得到的串行数据转化为并行数据交由CPU处理。显而易见,这实际上是两个独立的逻辑功能,分别设计为独立的模块,然后再合并为一个模块显得目的明确、层次清晰。

// ----------------p_to_s.v ---------------------------------

modulep_to_s(D_in,T0,data,SEND,ESC,ADD_100);

outputD_in,T0;// D_in是串行输出,T0是移位时钟并给

// CPU中断,以确定何时给出下个数据。

input[7:0] data;//并行输入的数据。

inputSEND,ESC,ADD_100;//SEND、ESC共同决定是否进行并到串

//的数据转化。ADD_100决定何时置数。

wireD_in,T0;

reg [7:0] DATA_Q,DATA_Q_buf;

assignT0 = ! (SEND & ESC);//形成移位时钟。.

assignD_in = DATA_Q[7];//给出串行数据。

always @(posedge T0 or negedge ADD_100)//ADD_100下沿置数,T0上沿移位。

begin

if(!ADD_100)

DATA_Q = data;

else

begin

DATA_Q_buf = DATA_Q<<1;//DATA_Q_buf作为中介,以令综合器

DATA_Q= DATA_Q_buf;//能辨明。

end

end

endmodule

在p_to_s.v中,由于移位运算虽然可综合,但是不是简单的RTL级描述,直接用DATA_Q<=DATA_Q<<1的写法在综合时会令综合器产生误解。另外,在该设计中,由于时钟T0的频率较低,所以没有象以往那样采用低电平置数,而是采用ADD_100的下降沿置数。

//--------------------- s_to_p.v ---------------------------

module s_to_p(T1, data, D_out,DSC,TAKE,ADD_101);

outputT1;//给CPU中断,以确定CPU何时取转化

//得到的并行数据。

output [7:0] data;

inputD_out, DSC, TAKE, ADD_101;//D_out提供输入串行数据。DSC、TAKE

//共同决定何时取数。

wire[7:0] data;

wireT1,clk2;

reg[7:0] data_latch, data_latch_buf;

assignclk2 = DSC& TAKE ;//提供移位时钟。

assignT1 = !clk2;

assigndata =(!ADD_101) ? data_latch : 8'bz;

always@(posedge clk2)

begin

data_latch_buf = data_latch << 1;//data_latch_buf作缓冲

data_latch= data_latch_buf;//,以令综合器能辩明。

data_latch[0] = D_out;

end

endmodule

将上面的两个模块合并起来的sys.v的源代码:

//------------------- sys.v ---------------------------

`include "./p_to_s.v"

`include "./s_to_p.v"

module sys(D_in,T0,T1, data, D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101);

inputD_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;

inout[7:0]data;

outputD_in,T0,T1;

p_to_sp_to_s(.D_in(D_in),.T0(T0),.data(data),

.SEND(SEND),.ESC(ESC),.ADD_100(ADD_100));

s_to_ps_to_p(.T1(T1),.data(data),.D_out(D_out),

.DSC(DSC),.TAKE(TAKE),.ADD_101(ADD_101));

endmodule

测试模块源代码:

//-------------Top test file for sys.v ------------------

`timescale 1ns/100ps

`include "./sys.v"

module Top;

reg D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;

reg[7:0] data_buf;

wire [7:0] data;

wire clk2;

assigndata = (ADD_101) ? data_buf : 8'bz;

//data在sys中是inout型变量,ADD_101

//控制data是作为输入还是进行输出。

assignclk2 =DSC && TAKE;

initial

begin

SEND = 0;

ESC = 0;

DSC = 1;

TAKE = 1;

ADD_100 = 1;

ADD_101 = 1;

end

initial

begin

data_buf = 8'b10000001;

#90 ADD_100 = 0;

#100 ADD_100 = 1;

end

always

begin

#50;

SEND = ~SEND;

ESC = ~ESC;

end

initial

begin

#1500 ;

SEND = 0;

ESC= 0;

DSC= 1;

TAKE = 1;

ADD_100 = 1;

ADD_101 = 1;

D_out = 0;

#1150 ADD_101 = 0;

#100 ADD_101 =1;

#100 $stop;

end

always

begin

#50 ;

DSC = ~DSC;

TAKE = ~TAKE;

end

always @(negedge clk2) D_out = ~D_out;

syssys(.D_in(D_in),.T0(T0),.T1(T1),.data(data),.D_out(D_out),

.ADD_101(ADD_101), .SEND(SEND),.ESC(ESC),.DSC(DSC),

.TAKE(TAKE),.ADD_100(ADD_100));

endmodule

仿真波形:

练习:设计一个序列发生器。要求根据输入的8位并行数据输出串行数据,如果输入数据在0—127之间则输出一位0,如果输入数据在128—255之间则输出一位1,同步时钟触发;并且和范例8的序列检测器搭接,形成一个封闭系统。编写测试模块,并给出仿真波形。

可能会用到的工具/仪表
相关文章
推荐文章
热门文章
章节目录
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号