题解 | #整数倍数据位宽转换8to16#
整数倍数据位宽转换8to16
https://www.nowcoder.com/practice/f1fb03cb0baf46ada2969806114bce5e
思路
本道题思路很简单。
在valid_in为1的情况下,得到第一个数据放在data_out的高8位,得到第二个数据放在data_out的低8位。
但是仔细观察波形图发现,valid_in为0后并没有把data_out之前装载的数据清空,而是下一次valid_in为1时继续使用。
data_out装载完成后,让valid_out为1,并输出data_out。
重复以上步骤!由此可以找一个标志的符号flag,若flag为0,则data_in的数据装载到data_out的高位;若flag为1,则data_in的数据装载到data_out的低位。每次装载完数据就让flag=flag+1,这样flag就能在0和1之间来回变换。
代码
`timescale 1ns/1ns module width_8to16( input clk , input rst_n , input valid_in , input [7:0] data_in , output reg valid_out, output reg [15:0] data_out ); reg flag=1'b0;//flag为0把data_in放在data_out_tmp高8位,为1放低位 reg [15:0]data_out_tmp; always @(posedge clk or posedge rst_n) begin if (!rst_n)begin data_out_tmp<=0; data_out<=0; flag<=0; valid_out<=0; end else begin if (valid_in)begin if (flag==0)begin data_out_tmp[15:8]<=data_in; flag=flag+1; valid_out<=0; end else begin data_out_tmp[7:0]=data_in;//注意这里是=不是<= flag=flag+1; valid_out<=1; data_out<=data_out_tmp; end end else begin valid_out=0; // data_out<=0; 这句不要 要了就通不过测试用例 end end end always @(posedge clk or negedge rst_n) begin if (!rst_n)begin data_out<=0; valid_out<=0; end end endmodule
注意点
接下来说一说代码中有几个需要注意的地方:
1.代码第29行,为什么用=而不用<=
- 观察题目的波形图,可以发现当装载完数据,valid_out为1恰好是在如下图的“1”处。所以装载完数据要马上能让valid_in为1。所以用阻塞赋值,让data_in的数据完整装到data_out_tmp里面才可以赋值给data_out.
2.第37行代码,为什么那句代码不要?
- 因为要了的话就通不过测试。在valid_in为0期间,data_out还要保持valid_in为1时的值。所以这句代码不能要。
3.第41行到第46行是不是多余?
- 其实我也觉得多余,因为在第15~19行已经给它赋值过了。但是如果不要第41~46行,就会报错。咱也不知道为啥呢【
】
4.这想提一个题外话,笔者发现牛客的仿真和在vivado上的仿真不一样唉。同样的代码逻辑,在牛客上仿真时valid_out为1时要落后于valid_in一拍,但是在vivado上仿真两个可以同时为1,咱也不知道为啥呢【】