并行是指多比特数据同时通过并行线进行传送,这样数据传送速度大大提高,但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。
异步并口应用:CPU类的芯片与FPGA的数据交互,数据速率一般在100Mbps以内。数据总线不大于16bit。
非CPU类的功能芯片与FPGA通过并口进行数据交互,例如配置寄存器等等。
并行由于数据传输的相位差之间的正确窗口大小限制其传输速度。
这里提出亚稳态的概念,从事多时钟设计的第一步是要理解信号稳定性问题。当一个信号跨越某个时钟域时,对新时钟域的电路来说它就是一个异步信号。接收该信号的电路需要对其进行同步,同步可以防止第一级存储单元(触发器)的亚稳态在新的时钟域传播蔓延。
亚稳态是指触发器无法在某个规定时间段内达到一个可确认的状态。当一个触发器进入亚稳态时,既无法预测单元的输出电平也无法预测何时输出才能稳定在某个正确的电平上。在这个稳定期间,触发器输出一些中间级电平或者处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。
代码实现:
module parall_inerf(
input wire sclk,
input wire rst_n,
input wire cs_n,
input wire rd_n,
input wire wr_n,
inout tri [15:0] data,
input wire [7:0] addr
);
reg [15:0] data_0,data_1,data_2,data_3,
data_4,data_5,data_6,data_7;
reg [1:0] cs_n_r,rd_n_r,wr_n_r;
reg [47:0] data_r;
reg [23:0] addr_r;
reg [15:0] rdata;
//降低亚稳态出现概率,把CS_n,rd_n,wr_n,单比特信号打两拍
always @(posedge sclk or negedge rst_n)
if(rst_n==1'b0)
{cs_n_r,rd_n_r,wr_n_r}<=9'h1ff;
else
{cs_n_r,rd_n_r,wr_n_r}<={{cs_n_r[1:0],cs_n},{rd_n_r[1:0],rd_n},{wr_n_r[1:0],wr_n}};
//降低亚稳态出现概率,
always @(posedge sclk or negedge rst_n)
if(rst_n==1'b0) begin
data_r<=48'd0;
addr_r<=24'd0;
end
else begin
data_r<={data_r[31:0],data};
addr_r<={addr_r[15:0],addr};
end
//写
always @(posedge sclk or negedge rst_n)
if(rst_n==1'b0) begin
data_0<=8'd0;
data_1<=8'd0;
data_2<=8'd0;
data_3<=8'd0;
data_4<=8'd0;
data_5<=8'd0;
data_6<=8'd0;
data_7<=8'd0;
end
else if{cs_n_r[2] == 1'b0 && rd_n_r[2] == 1'b1 && wr_n_r[2] == 1'b0} begin
case(addr_r[23:16])
8'd0:data_0<=data_r[47:32];
8'd0:data_1<=data_r[47:32];
8'd0:data_2<=data_r[47:32];
8'd0:data_3<=data_r[47:32];
8'd0:data_4<=data_r[47:32];
8'd0:data_5<=data_r[47:32];
8'd0:data_6<=data_r[47:32];
8'd0:data_7<=data_r[47:32];
dafaulet:begin
data_0<=data_0;
data_1<=data_1;
data_2<=data_2;
data_3<=data_3;
data_4<=data_4;
data_5<=data_5;
data_6<=data_6;
data_7<=data_7;
end
endcase
end
always @(posedge sclk or negedge rst_n)
if(rst_n==1'b0) begin
r_data<='d0;
else if(cs_n_r[2] == 1'b0 && wr_n_r[2] == 1'b1)begin
case(addr[23:16])
8'd0:rdata=data_0;
8'd0:rdata<=data_1;
8'd0:rdata<=data_2;
8'd0:rdata<=data_3;
8'd0:rdata<=data_4;
8'd0:rdata<=data_5;
8'd0:rdata<=data_6;
8'd0:rdata<=data_7;
default:rdata<=16'd0;
endcase
//三态门
assign data=(cs_n_r[2] == 1'b0 && rd_n_r[2]==1'b0)?rdata:16'hzzz;
endmodule
代码测试:
1ns/1ns
module tb_parall_interf();
reg sclk,rst_n;
reg cs_n,rd_n,wr_n;
reg [15:0] data;
reg [7:0] addr;
reg [15:0] w_date;
parameter setup_time=2;
parameter hold_time=2;
parameter data_time=4;
2; =
initial begin
sclk=0;
rst_n=0;
#200
rst_n=1;
end
~sclk; =
//例化
parall_interf parall_interf_inst(
(sclk),
(rst_n),
(cs_n),
(rd_n),
(wr_n),
(w_data),
.addr (addr)
);
initial begin
cs_n=1;
rd_n=1;
wr_n=1;
data=0;
addr=0;
rst_n);
#100
write_data(8);
#100
read_data(8);
end
//写数据任务
task write_data(len);
integer i,len;
begin
0;i<len;i=i+1) =
begin
cs_n=0;
data=i[15:0];
addr=i[7:0];
setup_dly();
wr_n=0;
data_dly();
wr_n=1;
hold_dly();
1; =
end
cs_n=1;
end
endtask
//读数据任务
task read_data(len);
integer i,len;
begin
0;i<len;i=i+1) =
begin
cs_n=0;
addr=i[7:0];
read_dly();
rd_n=0;
data_dly();
addr=%d data=%d",i,w_data);
rd_n=1;
end
cs_n=1;
end
endtask
//测试激励的三态门
assign w_data=(wr_n==1'b0)?data:16'hzzzz;
//延时
task setup_dly();
integer i;
begin
for (i=0;i<setup_time;i=i+1)
begin
sclk);
end
end
endtask
task hold_dly();
integer i;
begin
0;i<hold_time;i=i+1) =
begin
sclk);
end
end
endtask
task data_dly();
integer i;
begin
0;i<data_time;i=i+1) =
begin
sclk);
end
end
endtask
task read_dly();
integer i;
begin
0;i<read_time;i=i+1) =
begin
sclk);
end
end
endtask
endmodule