题解 | #非整数倍数据位宽转换24to128#
非整数倍数据位宽转换24to128
https://www.nowcoder.com/practice/6312169e30a645bba5d832c7313c64cc
`timescale 1ns/1ns module width_24to128( input clk , input rst_n , input valid_in , input [23:0] data_in , output reg valid_out , output reg [127:0] data_out ); reg [1 :0] data_lock_cnt ; reg [15 :0] data_lock ; reg [4 :0] shf_cnt ; reg [127:0] data_save ; //data_lock_cnt /* 当valid_in = 1时: (1)若shf_cnt ≤ 3: data_lock_cnt = 3 - shf_cnt; (2)若shf_cnt= 16: data_lock_cnt = 0; */ always@(posedge clk or negedge rst_n) begin if(!rst_n) data_lock_cnt <= 2'b0 ; else begin if(valid_in) begin if(shf_cnt <= 5'd3) data_lock_cnt <= 2'd3 - shf_cnt[1:0] ; else if(shf_cnt == 5'd16) data_lock_cnt <= 2'b0 ; end end end //data_lock /* 当valid_in = 1时: (1)若shf_cnt ≤ 3: data_lock = data_in的低(3-shf_cnt)个字节 (2)若shf_cnt= 16: data_lock = 0; */ always@(posedge clk or negedge rst_n) begin if(!rst_n) data_lock <= 16'b0 ; else begin if(valid_in) begin if(shf_cnt <= 5'd3) begin case(shf_cnt) 5'd2:data_lock <= {8'b0,data_in[15:8]} ; 5'd1:data_lock <= data_in[15:0] ; endcase end else if(shf_cnt == 5'd16) data_lock <= 16'b0 ; end end end //shf_cnt /* 状态指示位shf_cnt初始值为16,当valid_in = 1时: (1)若shf_cnt =16 shf_cnt 减去(data_lock_cnt + 3); (2)若shf_cnt ≠ 16: <1>若shcnt > 3 : shf_cnt 自减 3 ; <2>若shf_cnt ≤ 3: shf_cnt 归 16; */ always@(posedge clk or negedge rst_n) begin if(!rst_n) shf_cnt <= 5'd16 ; else begin if(valid_in) begin if(shf_cnt == 5'd16) shf_cnt <= shf_cnt - (data_lock_cnt + 5'd3) ; else begin if(shf_cnt > 5'd3) shf_cnt <= shf_cnt - 5'd3 ; else shf_cnt <= 5'd16 ; end end end end //data_save /* 当valid_in = 1时: (1)若shf_cnt =16 data_save将{data_lock,data_in}放入低6个字节; (2)若shf_cnt ≠ 16: <1>若shf_cnt > 3 : data_save移位3个字节并存入data_in的数据; <2>若shf_cnt ≤ 3: data_save根据shf_cnt的当前值位移并存入相应的数据; */ always@(posedge clk or negedge rst_n) begin if(!rst_n) data_save <= 128'b0 ; else begin if(valid_in) begin if(shf_cnt == 5'd16) data_save <= {88'b0,data_lock,data_in} ; else begin if(shf_cnt > 5'd3) data_save <= { data_save[103:0],data_in } ; end end end end //data_out /* 当valid_in = 1 且 shf_cnt ≤ 3: data_out 根据shf_cnt的当前值位移并存入相应的数据; */ always@(posedge clk or negedge rst_n) begin if(!rst_n) data_out <= 128'b0 ; else begin if(valid_in & (shf_cnt <= 5'd3)) begin case(shf_cnt) 5'd3: data_out <= { data_save[103:0],data_in[23: 0]} ; 5'd2: data_out <= { data_save[111:0],data_in[23: 8]} ; 5'd1: data_out <= { data_save[119:0],data_in[23:16]} ; endcase end end end // valid_out /* 当valid_in = 1 且 shf_cnt<=3时,那么此次装填会使fifo装满,则valid_out拉高 其余情况,valid_out 拉低 */ always@(posedge clk or negedge rst_n) begin if(!rst_n) valid_out <= 1'b0 ; else begin if(valid_in & (shf_cnt <= 5'd3)) valid_out <= 1'b1 ; else valid_out <= 1'b0 ; end end endmodule