题解 | #整数倍数据位宽转换8to16-解法4有问题#
自己写的时序出错,但是面试手撕的时候也没给时序图啊,可能问题也不大。
题解区copy的代码:
注意点:
1、a0的那个时钟周期valid是没有赶上上升沿的。
2、
`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 [7:0] data_lock; //data buffer reg flag ; //input data buff in data_lock always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_lock <= 'd0; else if(valid_in && !flag) data_lock <= data_in; end //generate flag always @(posedge clk or negedge rst_n ) begin if(!rst_n) flag <= 'd0; else if(valid_in) flag <= ~flag; end //generate valid_out always @(posedge clk or negedge rst_n ) begin if(!rst_n) valid_out <= 'd0; else if(valid_in && flag) valid_out <= 1'd1; else valid_out <= 'd0; end //data stitching always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_out <= 'd0; else if(valid_in && flag) data_out <= {data_lock, data_in}; end endmodule
`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 [1:0] cnt; reg [15:0] data_in_reg; always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin cnt <= 0; end else if(valid_in) begin cnt <= (cnt == 2 ) ? 0 : cnt + 1; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_in_reg <= 0; end else if(valid_in) begin data_in_reg <= {data_in_reg[7:0], data_in}; end end always @ (*) begin if(~rst_n) begin valid_out <= 0; end else if(cnt == 2) begin valid_out <= 1; end else begin valid_out <= 0; end end always @ (*) begin if(~rst_n) begin data_out <= 0; end else if(valid_out) begin data_out <= data_in_reg; end else begin data_out <= data_out; end end endmodule
解法2修改正确:
1、valid_out 是时序模块,cnt到1就可以了。
2、判断valid_out 时还需要cnt == 1 && valid_in,因为只有cnt == 1只能证明缓存了一个数,还需要再一个valid_in才行
`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 [1:0] cnt; reg [15:0] data_in_reg; always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin cnt <= 0; end else if(valid_in) begin cnt <= (cnt == 1 ) ? 0 : cnt + 1; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_in_reg <= 0; end else if(valid_in) begin data_in_reg <= {data_in_reg[7:0], data_in}; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin valid_out <= 0; end else if(cnt == 1 && valid_in) begin valid_out <= 1; end else begin valid_out <= 0; end end always @ (*) begin if(~rst_n) begin data_out <= 0; end else if(valid_out) begin data_out <= data_in_reg; end else begin data_out <= data_out; end end endmodule
cnt == 1 && valid_in
`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 [1:0] cnt; reg [15:0] data_in_reg; always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin cnt <= 0; end else if(valid_in) begin cnt <= (cnt == 1 ) ? 0 : cnt + 1; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_in_reg <= 0; end else if(valid_in) begin data_in_reg <= {data_in_reg[7:0], data_in}; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin valid_out <= 0; end else if(cnt == 1 && valid_in) begin valid_out <= 1; end else begin valid_out <= 0; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_out <= 0; end else if(cnt == 1 && valid_in) begin data_out <= data_in_reg; end else begin data_out <= data_out; end end endmodule
解法3修改:
修改点:data_out 改为时序,则会发现当上升沿到来时最新的{data_in_reg[7:0], data_in}还没到,需要手动加上。
`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 [1:0] cnt; reg [15:0] data_in_reg; always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin cnt <= 0; end else if(valid_in) begin cnt <= (cnt == 1 ) ? 0 : cnt + 1; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_in_reg <= 0; end else if(valid_in) begin data_in_reg <= {data_in_reg[7:0], data_in}; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin valid_out <= 0; end else if(cnt == 1 && valid_in) begin valid_out <= 1; end else begin valid_out <= 0; end end always @ (posedge clk, negedge rst_n) begin if(~rst_n) begin data_out <= 0; end else if(cnt == 1 && valid_in) begin data_out <= {data_in_reg[7:0], data_in}; end else begin data_out <= data_out; end end endmodule