题解 | #非整数倍数据位宽转换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
