设计要求:上游模块产生的数据是8位宽, FIFO输入输出而是16位宽的,那么就需要将上游产生的两个8bit数据进行拼接,凑成一个完整的16bit数据,然后再一次写入fifo
上游模块产生两个信号 datat_in[7:0] 和 data_in_vld 给FIFO,在控制FIFO模块中,将利用这两个信号通过一定方式转换成写入FIFO,思路步骤如下:
(1)、将两个8bit数据拼接一个16bit的,那么就需要一个计数器 (cnt0),对数据进行数数,数两个,所以位宽1bit就够 ,定义
reg [0:0] cnt0;
(2)、计数器启动条件 (add_cnt0), 启动条件无非就是利用data_in_vld ,当data_in_vld 有效时,立刻启动计数器,可以画出data_in_vld 和 add_cnt0的波形对应关系了
add_cnt0 = data_in_vld == 1;
(3)、计数器结束条件(end_cnt0),当计数器cnt0 == 2-1 时(也就是数到了2个数),就停止计数。 根据cnt0 数数情况,可以画出end_cnt0的波形了
end_cnt0 = add_cnt0 && cnt0 == 2-1;
(4)、该考虑处理怎么处理data_in的数据了,肯定要结合 cnt0 将 数据 进行 拼接,在cnt0 == 1-1 时,就得将第一个data_in[7:0]的数据保存到data_temp[15:8]中的高八位,
在cnt0 == 2-1 时,就得将 data_in[7:0]的数据保存到data_temp[7:0]中的低八位。如下写法
1 always @(posedge clk_in or negedge rst_n)begin 2 if(!rst_n)begin 3 data_temp <= 0; 4 end 5 else if(add_cnt0 && cnt0 == 1)begin 6 data_temp[7:0] <= data_in; 7 end 8 else if(add_cnt0 && cnt0 == 0)begin 9 data_temp[15:8] <= data_in; 10 end 11 end
可以将上面的形式转换另外一种高级方式:
always @(posedge clk_in or negedge rst_n)begin if(!rst_n)begin data_temp <= 0; end else if(add_cnt0 && cnt0 >= 0 && cnt0 < 2)begin data_temp[DOUT_W-1 - cnt0*DIN_W -:DIN_W] = data_in; end end
data_temp[DOUT_W-1 - cnt0*DIN_W -:DIN_W] = data_temp[16-1 - cnt0*8 -:8]:
当cnt0 = 0 时,data_temp[16-1 - 0*8 -:8] = data_temp[15 -:8] 表示data_temp第15位开始,往下数8个,相当于就是datat_temp[15:8]
当cnt0 = 1 时,data_temp[16-1 - 1*8 -:8] = data_temp[7 -:8] 表示data_temp第7位开始,往下数8个,相当于就是datat_temp[7:0]
是不是立马觉得很高级了,一行表示完,看起来代码少了,但理解起来有点费劲,就让人产生高级感了!!!!
根据cnt0,就可以画出data_temp 和cnt0的对应关系了。
(4)、拼接完了,那就得考虑如何产生wrreq信号了,首先记住一个关键点,wrreq 和待写入fifo的数据(data_temp[15:0])要保持在同一拍,既然要保持在同一拍,说明数据拼接好了,
就可以画出 wrreq 和 data_temp[15:0] 的波形,如下图,
wrreq 和 data_temp = 16'h1011 保持在同一拍,且wrreq只能保持一个时钟周期,画出这两个相对应的波形。
现在波形画的差不多了,可以看出在哪个节点 将 wrreq 拉高,也就是end_cnt0 == 1 时,将wrreq拉高,因为还要考虑一个usedw条件,所以将两个条件一同写上,如下代码:
always @(posedge clk_in or negedge rst_n)begin if(!rst_n)begin wrreq <= 0; end else if(end_cnt0 && wrusedw < 61 )begin wrreq <= 1; //只保留一个时钟周期 end else begin wrreq <= 0; end end
大概轮廓波形:
modelsim仿真波形: 在wrreq = 1 期间, data_temp = 16'h1011, 保持在同一拍,且只保留一个时钟周期,当第一个写完之后,可以看到q 上面已经显示 16'h1011,说明已成功写入fifo中