Verilog——数据转换器:1)由宽到窄(32bit到16bit)的数据转换模块

Verilog——数据转换器:1)由宽到窄(32bit到16bit)的数据转换模块

转换目标及基本原理

  • 转换目标

使用FPGA的不同频率和相位的时钟,将低频32bit位宽的数据流转换为倍频16bit位宽的数据流。

  • 时钟
  1. 时钟频率:输入时钟频率CLK1X,输出时钟频率CLK2X,f_CLK2X = 2*f_CLK1X。
  2. 相位:CLK2X的相位略超前于CLK1X。CLK1X和CLK2X的相位关系如下图所示:
    疑问:对相位是否没有要求?
  • 基本原理:
  1. data_in_r是在clk2x时钟驱动下读入data_in数据;
  2. data_out是16bit数据输出。在clk2x时钟驱动下,当clk1x为0时输出data_in_r的低16位,当clk1x为1时输出data_in_r的高16位,

代码实现

//convert_32to16.v
//数据转换器:32bit数据到16bit数据转换
//目标:1X时钟的32bit数据输入,转换为2X时钟的16bit数据输出
//要求:
//  1) clk_2X的频率为clk_1X的2倍;
//  2) clk_2X的相位超前clk_1X的相位。

`timescale 1ns/1ps

module convert_32to16(
    input               clk_1X          ,
    input               clk_2X          ,
    input               flag_in         ,//输入有效标志
    input       [31:0]  data_in         ,//输入数据
    output  reg         flag_out        ,//输出有效标志
    output  reg [15:0]  data_out         //输出数据
);

reg [31:0]  data_in_r;
reg         flag_in_r;

//data_in_r
always @(posedge clk_2X) begin
    data_in_r <= data_in;
end

//flag_out
always  @(posedge clk_2X) begin
    flag_in_r <= flag_in;
    flag_out <= flag_in_r;
end

//data_out
always @(posedge clk_2X) begin
    if(flag_in_r & ~clk_1X)
        data_out <= data_in_r[15:0];
    else if(flag_in_r & clk_1X)
        data_out <= data_in_r[31:16];
    else
        data_out <= 16'hffff;
end

endmodule

仿真

//tb_convert_32to16.v
`timescale 1ns/1ps
module tb_convert_32to16();

reg         clk_1X      ;
reg         clk_2X      ;
reg         flag_in     ;
reg [31:0]  data_in     ;
wire        flag_out    ;
wire[15:0]  data_out    ;

convert_32to16 convert_32to16_inst(
    .clk_1X         (clk_1X     ),
    .clk_2X         (clk_2X     ),
    .flag_in        (flag_in    ),//输入有效标志
    .data_in        (data_in    ),//输入数据
    .flag_out       (flag_out   ),//输出有效标志
    .data_out       (data_out   ) //输出数据
);

//clk_1X,50MHz
initial begin
    clk_1X = 1'b1;
    forever begin
        #10;
        clk_1X = ~clk_1X;
    end
end

//clk_2X,100MHz
initial begin
    clk_2X = 1'b1;
    #2;
    forever begin
        #5;
        clk_2X = ~clk_2X;
    end
end

//Main
initial begin
    flag_in = 0;
    data_in = 32'hffff_ffff;
    #55;

    flag_in = 1;
    data_in = 32'ha000_1000;
    repeat(5) begin
        data_in = data_in + 32'h0001_0001;
        #20;
    end
    flag_in = 0;
    data_in = 32'ha000_1000;

end


endmodule

仿真结果

posted @ 2022-04-24 10:21  fxz_abc  阅读(2811)  评论(0编辑  收藏  举报