模塊代碼
module parall_interf(
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 [2:0] cs_n_r,rd_n_r,wr_n_r;
reg [47:0] data_r;
reg [23:0] addr_r;
reg [15:0] rdata;
assign data = (cs_n_r[2] == 1'b0 && rd_n_r[2]== 1'b0) ? rdata : 16'hzzzz;
//去降低穩態出現概率把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 <= 16'd0;
data_1 <= 16'd0;
data_2 <= 16'd0;
data_3 <= 16'd0;
data_4 <= 16'd0;
data_5 <= 16'd0;
data_6 <= 16'd0;
data_7 <= 16'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'd1:data_1 <= data_r[47:32];
8'd2:data_2 <= data_r[47:32];
8'd3:data_3 <= data_r[47:32];
8'd4:data_4 <= data_r[47:32];
8'd5:data_5 <= data_r[47:32];
8'd6:data_6 <= data_r[47:32];
8'd7:data_7 <= data_r[47:32];
default: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)
rdata <= 16'hffff;
else if(cs_n_r[2] == 1'b0 && rd_n_r[2] == 1'b1 && wr_n_r[2] == 1'b1) begin
case(addr_r[23:16])
8'd0:rdata <= data_0;
8'd1:rdata <= data_1;
8'd2:rdata <= data_2;
8'd3:rdata <= data_3;
8'd4:rdata <= data_4;
8'd5:rdata <= data_5;
8'd6:rdata <= data_6;
8'd7:rdata <= data_7;
default:rdata <= 16'd0;
endcase
end
endmodule
測試文件
`timescale 1ns/1ns
module parall_interf_tb;
parameter SETUP_TIME = 2;
parameter HOLD_TIME = 2;
parameter DATA_TIME = 4;
parameter READ_WAIT = 5;
reg sclk;
reg rst_n;
reg cs_n;
reg rd_n;
reg wr_n;
reg [15:0] data;
reg [7:0] addr;
tri [15:0] w_data;
initial begin
sclk = 0;
rst_n = 0;
#200
rst_n = 1;
end
always #10 sclk = ~sclk;
initial begin
cs_n = 1;
rd_n = 1;
wr_n = 1;
data = 0;
addr = 0;
//@(posedge rst_n);
#300
write_data(8);
#100;
read_data(8);
end
//測試激勵的三態門
assign w_data = (wr_n==1'b0)?data:16'hzzzz;
parall_interf parall_interf_inst(
.sclk (sclk),//50mhz
.rst_n (rst_n),
.cs_n (cs_n),
.rd_n (rd_n),
.wr_n (wr_n),
.data (w_data),//1Mhz
.addr (addr)
);
//寫數據的任務
task write_data(len);
integer i,len;
begin
for(i=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();
end
cs_n = 1;
end
endtask
//讀數據任務
task read_data(len);
integer i,len;
begin
for(i=0;i<len;i=i+1)
begin
cs_n = 0;
addr = i[7:0];
read_dly();
rd_n = 0;
data_dly();
$display("read data addr is %d = %d ",i,w_data);
rd_n = 1;
end
cs_n = 1;
end
endtask
//基本的延時任務
task setup_dly();
integer i;
begin
for(i=0;i<SETUP_TIME;i=i+1)
begin
@(posedge sclk);
end
end
endtask
task hold_dly();
integer i;
begin
for(i=0;i<HOLD_TIME;i=i+1)
begin
@(posedge sclk);
end
end
endtask
task data_dly();
integer i;
begin
for(i=0;i<DATA_TIME;i=i+1)
begin
@(posedge sclk);
end
end
endtask
task read_dly();
integer i;
begin
for(i=0;i<READ_WAIT;i=i+1)
begin
@(posedge sclk);
end
end
endtask
endmodule