题解 | #非整数倍数据位宽转换24to128#
非整数倍数据位宽转换24to128
https://www.nowcoder.com/practice/6312169e30a645bba5d832c7313c64cc
//本题需要注意的就是128并不能整除24,所以一次并不是完整的整数个,经过计算分析,可以得知三次输出刚好是整数个24bit,总共需要16次 //这个就可以选择采用状态机,当然也可以直接对计数器进行输出,采用状态机就是三个状态,三个都有不同的输出,对应的时刻分别是5,10和15 //此题重点是理解需要多少次才能完整的输出数据而不需要下一个数据来借位 `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 ); //本题需要注意的就是128并不能整除24,所以一次并不是完整的整数个,经过计算分析,可以得知三次输出刚好是整数个24bit,总共需要16次 //这个就可以选择采用状态机,当然也可以直接对计数器进行输出,采用状态机就是三个状态,三个都有不同的输出,对应的时刻分别是5,10和15 //此题重点是理解需要多少次才能完整的输出数据而不需要下一个数据来借位 localparam One_st = 2'b01; localparam Two_st = 2'b10; localparam Thre_st = 2'b11; reg [1:0] cur_state; reg [1:0] nex_state; reg skip_en; reg [3:0] data_in_cnt; reg [127:0] data_out_temp; always@(posedge clk or negedge rst_n) begin if(!rst_n) data_in_cnt <= 4'd0; else begin if(valid_in) begin if(data_in_cnt == 4'd15) data_in_cnt <= 4'b0; else data_in_cnt <= data_in_cnt + 1'b1; end else data_in_cnt <= data_in_cnt; end end always@(posedge clk or negedge rst_n) begin if(!rst_n) cur_state <= One_st; else cur_state <= nex_state; end always@(*) begin nex_state = One_st; case(cur_state) One_st : begin if(skip_en) nex_state = Two_st; else nex_state = One_st; end Two_st : begin if(skip_en) nex_state = Thre_st; else nex_state = Two_st; end Thre_st : begin if(skip_en) nex_state = One_st; else nex_state = Thre_st; end default : nex_state = One_st; endcase end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin data_out <= 128'b0; valid_out <= 1'b0; skip_en <= 1'b0; end else begin skip_en <= 1'b0; case(nex_state) One_st : begin if(data_in_cnt == 4'd5) begin skip_en <= 1'b1; data_out <= {data_out_temp[119:0] , data_in[23:16]}; valid_out <= 1'b1; end else begin skip_en <= 1'b0; data_out <= data_out; valid_out <= 1'b0; end end Two_st : begin if(data_in_cnt == 4'd10) begin skip_en <= 1'b1; data_out <= {data_out_temp[111:0] , data_in[23:8]}; valid_out <= 1'b1; end else begin skip_en <= 1'b0; data_out <= data_out; valid_out <= 1'b0; end end Thre_st : begin if(data_in_cnt == 4'd15) begin skip_en <= 1'b1; data_out <= {data_out_temp[103:0] , data_in}; valid_out <= 1'b1; end else begin skip_en <= 1'b0; data_out <= data_out; valid_out <= 1'b0; end end default : ; endcase end end always@(posedge clk or negedge rst_n) begin if(!rst_n) data_out_temp <= 128'b0; else if(valid_in) data_out_temp <= {data_out_temp[103:0] , data_in}; else data_out_temp <= data_out_temp; end endmodule