操练十. 经过模块之间的调用完成自顶向下的规划意图:学习状态机的嵌套运用完成层次化、结构化规划。
现代硬件体系的规划进程与软件体系的开发相似,规划一个大规模的集成电路的往往由模块多层次的引证和组合构成。层次化、结构化的规划进程,能使杂乱的体系简略操控和调试。 在Verilog HDL中,上层模块引证基层模块与C言语中程序调用有些相似,被引证的子模块在归纳时作为其父模块的一部分被归纳,构成相应的电路结构。在进行模块实例引证时,有必要留意的是模块之间对应的端口,即子模块的端口与父模块的内部信号有必要明晰无误地一一对应,不然简略发生意想不到的结果。
下面给出的比如是规划中遇到的一个实例,其功用是将并行数据转化为串行数据送交外部电路编码,并将解码后得到的串行数据转化为并行数据交由CPU处理。清楚明了,这实际上是两个独立的逻辑功用,别离规划为独立的模块,然后再兼并为一个模块显得意图明晰、层次明晰。
// —————- p_to_s.v ———————————
module p_to_s(D_in,T0,data,SEND,ESC,ADD_100);
output D_in,T0; // D_in是串行输出,T0是移位时钟并给
// CPU中止,以确认何时给出下个数据。
input [7:0] data; //并行输入的数据。
input SEND,ESC,ADD_100; //SEND、ESC一起决议是否进行并到串
//的数据转化。ADD_100决议何时置数。
wire D_in,T0;
reg [7:0] DATA_Q,DATA_Q_buf;
assign T0 = ! (SEND ESC); //构成移位时钟。.
assign D_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_Q1; //DATA_Q_buf作为中介,以令归纳器
DATA_Q = DATA_Q_buf; //能辨明。
end
end
endmodule
在p_to_s.v中,因为移位运算尽管可归纳,可是不是简略的RTL级描绘,直接用DATA_Q=DATA_Q1的写法在归纳时会令归纳器发生误解。别的,在该规划中,因为时钟T0的频率较低,所以没有象以往那样选用低电平置数,而是选用ADD_100的下降沿置数。
//——————— s_to_p.v —————————
module s_to_p(T1, data, D_out,DSC,TAKE,ADD_101);
output T1; //给CPU中止,以确认CPU何时取转化
//得到的并行数据。
output [7:0] data;
input D_out, DSC, TAKE, ADD_101; //D_out供给输入串行数据。DSC、TAKE
//一起决议何时取数。
wire [7:0] data;
wire T1,clk2;
reg [7:0] data_latch, data_latch_buf;
assign clk2 = DSC TAKE ; //供给移位时钟。
assign T1 = !clk2;
assign data = (!ADD_101) ? data_latch : 8bz;
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);
input D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;
inout [7:0] data;
output D_in,T0,T1;
p_to_s p_to_s(.D_in(D_in),.T0(T0),.data(data),
.SEND(SEND),.ESC(ESC),.ADD_100(ADD_100));
s_to_p s_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;
assign data = (ADD_101) ? data_buf : 8bz;
//data在sys中是inout型变量,ADD_101
//操控data是作为输入仍是进行输出。
assign clk2 =DSC TAKE;
iniTIal
begin
SEND = 0;
ESC = 0;
DSC = 1;
TAKE = 1;
ADD_100 = 1;
ADD_101 = 1;
end
iniTIal
begin
data_buf = 8b10000001;
#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;
sys sys(.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
仿真波形:[[wysiwyg_imageupload:255:]]
操练:规划一个序列发生器。要求依据输入的8位并行数据输出串行数据,假如输入数据在0—127之间则输出一位0,假如输入数据在128—255之间则输出一位1,同步时钟触发;而且和典范8的序列检测器搭接,构成一个封闭体系。编写测验模块,并给出仿真波形。