题解 | #非整数倍数据位宽转换24to128#
非整数倍数据位宽转换24to128
https://www.nowcoder.com/practice/6312169e30a645bba5d832c7313c64cc
`timescale 1ns/1ns
//串转并的方式有很多种:
//(1)单比特转多比特。这个比较容易,只需使用移位寄存器寄存,然后计数,在相同同的计数值输出结果即可。
//(2)多比特转多比特有两种可能,一种可能输出是输入的倍数,另一种可能是输出不是输入的倍数。
//(3)输出是输入的倍数,只需使用移位寄存器寄存,然后计数,在相同的计数值输出结果。
//(4)输出不是输入的倍数,使用移位寄存器寄存,找到输入和输出的最小公倍数,然后计数,在不同的计数值输出结果。
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
);
//24bit---128bit: 最小公倍数为 24*16=128*3
reg [3:0] cnt;//计数器16
reg [127:0] data_reg;//数据缓存器
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(valid_in) begin
if(cnt==15)
cnt <= 0;
else
cnt <= cnt+1'b1;
end
else
cnt <= cnt;
end
always@(posedge clk or negedge rst_n)begin //数据缓存器,当输入valid_in有效时,将数据data_in从低位移入
if(!rst_n)
data_reg <= 128'd0;
else if(valid_in)
data_reg <= {data_reg[103:0],data_in};
else
data_reg <= data_reg;
end
// 当计数器cnt计数到5、10、15时,data_out要进行更新,并拉高valid_out
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
valid_out <= 0;
else if ((cnt==5 || cnt==10 || cnt==15)&&valid_in)
valid_out <= 1;
else
valid_out <= 0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
data_out <= 4'd0;
else if(valid_in&&cnt==5)
data_out <= {data_reg[119:0], data_in[23:16]};
else if(valid_in&&cnt==10)
data_out <= {data_reg[111:0], data_in[23:8]};
else if(valid_in&&cnt==15)
data_out <= {data_reg[103:0], data_in[23:0]};
else
data_out <= data_out;
end
endmodule
