牛客网整数位宽转换

发布时间 2023-08-08 17:42:24作者: super_sweet

1、veilog进阶篇 VL32 非整数倍数据位宽转换24to48

描述:

实现数据位宽转换电路,实现24bit数据输入转换为128bit数据输出。其中,先到的数据应置于输出的高bit位。

valid_in用来指示数据输入data_in的有效性,valid_out用来指示数据输出data_out的有效性;clk是时钟信号;rst_n是异步复位信号。
 
观察时序图:

1、valid_out和data_out是在已存入5个数据且第6个数据到来后产生输出,且每个输入的数据中,低位数据会优先输出,图中第6个输入数据中的高8bit数据f2优先输出;

2、当数据缓存不满足128bit时,不会产生输出valid_out和data_out。

 

分析:

1、要实现24bit数据至128bit数据的位宽转换,必须要用寄存器将先到达的数据进行缓存。

2、24bit数据至128bit数据,相当于5个输入数据+第6个输入数据的拼接成一个输出数据,出于对资源的节省以及时序要求,采用120bit的寄存器进行数据缓存。

3、根据时序推演,数据是在第6个、第11个、第16个数据到来之后输出,所以内部设计一个计数器,用来指示数据接收状态。(24*16=128*3)

  a、当检测到valid_in拉高时,valid_cnt加1,valid_cnt在0-15之间循环,valid_cnt复位值是0。

  b、当valid_cnt是5或10或15,且valid_in为高时,输出数据,valid_out拉高。

 

 

`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 [119:0] data_reg;
reg [4:0] cnt;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        cnt <= 5'd0;
    else if(valid_in)
        cnt <= (cnt==5'd15)? 5'd0 : cnt+1'b1;
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        data_reg <= 120'd0;
        data_out <= 128'd0;
    end
    else if(valid_in) begin
        if(cnt==5'd5) begin
            data_reg <= {data_reg[119:16],data_in[15:0]};
            data_out <= {data_reg,data_in[23:16]};
        end
        else if(cnt==5'd10) begin
            data_reg <= {data_reg[119:8],data_in[7:0]};
            data_out <= {data_reg[111:0],data_in[23:8]};
        end
        else if(cnt==5'd15) begin
            data_reg <= {data_reg[119:24],data_in};
            data_out <= {data_reg[103:0],data_in};
        end
        else
            data_reg <= {data_reg[95:0],data_in};
    end
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        valid_out <= 1'b0;
    else if((cnt==5'd5 || cnt==5'd10 || cnt==5'd15) && valid_in)
        valid_out <= 1'b1;
    else
        valid_out <= 1'b0;
end


endmodule

 

2、veilog进阶篇 VL33 非整数倍数据位宽转换8to12

描述:

实现数据位宽转换电路,实现8bit数据输入转换为12bit数据输出。其中,先到的数据应置于输出的高bit位。

alid_in用来指示数据输入data_in的有效性,valid_out用来指示数据输出data_out的有效性;clk是时钟信号;rst_n是异步复位信号。
 
观察时序图:

1、valid_out和data_out是在两个数据输入之后的下一个时钟周期产生输出;

2、当仅有一个数据输入后,不会产生输出valid_out和data_out,而是会等待下一个数据到来之后完成两个数据的拼接,才产生输出valid_out和data_out。

 
 分析:
1、要实现8bit数据至12bit数据的位宽转换,必须要用寄存器将先到达的数据进行缓存。8bit数据至12bit数据,相当于1.5个输入数据拼接成一个输出数据,出于对资源的节省以及时序要求,采用1个8bit的寄存器(data_lock)进行数据缓存。
2、根据时序图,数据是在第二个数据到来之后输出,当仅有一个数据到来时,不产生输出,所以内部设计一个计数器(valid_cnt),用来指示数据接收状态。
  当检测到valid_in拉高时,valid_cnt加1,valid_cnt在0-2之间循环,valid_cnt复位值是0。
  当valid_cnt是1或2,且valid_in为高时,输出数据,valid_out拉高。
    当valid_cnt==1且valid_in为高时,data_out <= {data_lock, data_in[7:4]};
    当valid_cnt==2且valid_in为高时,data_out <= {data_lock[3:0], data_in}。
 

 

`timescale 1ns/1ns

module width_8to12(
    input                    clk         ,   
    input                   rst_n        ,
    input                      valid_in    ,
    input    [7:0]               data_in    ,
 
     output  reg               valid_out,
    output  reg [11:0]   data_out
);

reg [1:0] cnt;
reg [7:0] data_lock;

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        cnt <= 'b0;
    else if(valid_in)
        cnt <= (cnt==2'b10) ? 'b0 : cnt+1'b1;
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        data_lock <= 'b0;
    else if(valid_in)
        data_lock <= data_in;
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        data_out <= 'b0;
        valid_out <= 'b0;
    end
    else if(valid_in && cnt==2'b01) begin
        data_out <= {data_lock,data_in[7:4]};
        valid_out <= 1'b1;
    end
    else if(valid_in && cnt==2'b010) begin
        data_out <= {data_lock[3:0],data_in};
        valid_out <= 1'b1;
    end
    else
        valid_out <= 1'b0;
end

endmodule