设计要求:
①
包含一个
FIFO
,数据位宽
16bit
,深度是
64
。
②输入数据
data_in
和
data_in_vld
都是在属于
clk_in
时钟域的,模块首先将数据写到内部
FIFO
中。
③如果内部
FIFO
快满时(
wrusedw
>=61
)时,仍然有数据要写入,为了防止
FIFO
溢出,丢弃该数据,不再写入
FIFO
。
④data_out
、
data_out_vld
和
b_rdy
都是属于
clk_out
时钟域的。
⑤当
b_rdy
为
1
,且
FIFO
内有数据
(
rdempty
==0)
时,将数据送给模块
B
注意:这个题的不同点与第一题的不同点在于输出和输入的位宽不一致,data_out和data_in的位宽不一致,这就导致了,输入的一个数据,需要输出两次。
解决方案:用计数器来进行计数,分第一次和第二次,第一次取高八位,第二次取低八位。
module mdy_fifo_1_2(
clk_in ,
clk_out ,
rst_n ,
b_rdy ,
data_in ,
data_in_vld ,
data_out_vld,
data_out
);
parameter DOUT_W = 8;
parameter DIN_W = 16;
input clk_in ;
input clk_out ;
input rst_n ;
input b_rdy ;
input [DIN_W-1:0] data_in ;
input data_in_vld ;
output data_out_vld ;
output[DOUT_W-1:0] data_out ;
reg wrreq ;
wire [5:0] wrusedw ;
wire rdreq ;
wire [15:0] q ;
reg [7:0] data_out ;
reg data_out_vld ;
reg [1:0] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
//我们找到需要设计的信号:包含wrreq,rdreq,data_out,和data_out_vld
always @(*)begin
if(wrusedw>=61)
wrreq = 0;
else
wrreq =data_in_vld;
end
//例化信号
fifo_ahead#(.DATA_W(16),.DEPT_W(64)) u_fifo(
.aclr (~rst_n ),
.data (data_in ),
.rdclk (clk_out ),
.rdreq (rdreq ),
.wrclk (clk_in ),
.wrreq (wrreq ),
.q (q ),
.rdempty (rdempty ),
.wrusedw (wrusedw )
);
always @(posedge clk_out or negedge rst_n) begin
if (rst_n==0) begin
cnt0 <= 0;
end
else if(add_cnt0) begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0+1 ;
end
end
assign add_cnt0 = b_rdy && rdempty ==0;
assign end_cnt0 = add_cnt0 && cnt0 == 2-1 ;
assign rdreq = end_cnt0 ;
always @(posedge clk_out or negedge rst_n)begin
if(rst_n==1'b0)begin
data_out <= 0;
end
else begin
data_out <= q[DIN_W-1-DOUT_W*cnt0 -:DOUT_W];
end
end
always @(posedge clk_out or negedge rst_n)begin
if(rst_n==1'b0)begin
data_out_vld <= 0;
end
else begin
data_out_vld <= add_cnt0;
end
end
endmodule
我们可以看到有数据输入,data_in有数据,但是data_out并有数据输出,这主要是由于下游模块没有准备好,b_rdy==0;且可以看出,第一个数据是16'h03e8,最后一组数据是16'h0424;
我们可以看出下游模块开始准备好,b_rdy==1的情况开始出现;
FIFO中的存储的数据q是16'h03e8,而输出data_out输出是8'h03,第二个是8'he8,与输入的数据是一致的。这就说明已经达到了设计要求。