Verilog 代码题练手 (2-2)




引言

本篇博客做一个异步FIFO的设计。给出设计代码、TEST_BENCH、仿真结果,以及板级验证。

验证平台:A-7系列开发板(FPGA:xc7a35tfgg484-2)

开发环境:Vivado 2018.3

本篇博文接上篇,利用已设计的FIFO进行板级调试。

上篇:Verilog 代码题练手 (2-1)


应用说明 

将 100MHz 采样得到的 1MHz 正弦信号 内插一倍;

内插规则:内插当前采样值;

如:100M 采样 12,13,14,21,……;

内插后,序列1 :12 ,12 ,14 ,14 ,……;序列2:13,13,21,21,……

设计源码

`timescale 1ns / 1ps

// 声明:
// 1、利用 FIFO 对 100M采样 的DDS正弦信号作时域内插(即内插当前值) 
// 
// Author : 在路上,正出发

module TOP_ASYNC_FIFO_VERIFY(
// -------------------- 输入输出端口 ----------------------
input  								I_SYS_CLK_50M,
input 								I_SYS_RST,       //板上开关控制
input 								I_OPR_CTRL        //板上开关控制



    );

// --------------------  模块重载参数 -----------------------
// 数据位宽
localparam 							P_WR_DATA_WIDTH 	= 		8  ;
localparam 							P_RD_DATA_WIDTH 	= 		16 ;
// 地址位宽
localparam 							P_WR_ADDR_WIDTH 	= 		9  ;
localparam 							P_RD_ADDR_WIDTH 	= 		8  ;
// 几乎满、空阈值
localparam      					P_ALMOST_FULL_THRESHOLD =   50  ;//还剩 50 个空间时   几乎满信号拉高
localparam      					P_ALMOST_EMPTY_THRESHOLD =  50  ;//还剩 50 个数未读时 几乎空信号拉高

// ------------------- 内部信号 -------------------------
// 时钟
wire 								W_CLK_WR_100M  ;
wire 								W_CLK_RD_50M   ;
// 复位
wire 								W_OPR_RSTN     ;
// FIFO 写
(*MARK_DEBUG = "TRUE"*)reg								R_WR_EN 	   ;
(*MARK_DEBUG = "TRUE"*)reg 	[P_WR_DATA_WIDTH-1:0]		R_WR_DATA	   ;
(*MARK_DEBUG = "TRUE"*)wire								W_FIFO_FULL    ;
(*MARK_DEBUG = "TRUE"*)wire 							W_FIFO_ALMOST_FULL  ;

// FIFO 读
(*MARK_DEBUG = "TRUE"*)reg 								R_RD_EN		   ;
(*MARK_DEBUG = "TRUE"*)wire								W_RD_DATA_VAL  ;
(*MARK_DEBUG = "TRUE"*)wire 	[P_RD_DATA_WIDTH-1:0]	W_RD_DATA      ;
(*MARK_DEBUG = "TRUE"*)wire 							W_FIFO_EMPTY   ;
(*MARK_DEBUG = "TRUE"*)wire 							W_FIFO_ALMOST_EMPTY ;
// DDS
(*MARK_DEBUG = "TRUE"*)wire 							W_DDS_VAL;
(*MARK_DEBUG = "TRUE"*)wire [P_WR_DATA_WIDTH-1:0]		W_DDS_DATA;

// 2倍内插结果
(*MARK_DEBUG = "TRUE"*)(*KEEP = "TRUE"*)wire [P_WR_DATA_WIDTH-1:0] W_I_1;
(*MARK_DEBUG = "TRUE"*)(*KEEP = "TRUE"*)wire [P_WR_DATA_WIDTH-1:0] W_I_2;

assign W_I_1 = W_RD_DATA[15:8];
assign W_I_2 = W_RD_DATA[7:0];

// -------------------- 内部逻辑 ----------------------------
// 写
always @ (posedge W_CLK_WR_100M)
begin
	if(~W_OPR_RSTN)
	begin
		R_WR_EN    <= 0;
		R_WR_DATA  <= 0; 
	end
	else if(W_DDS_VAL & I_OPR_CTRL)
	begin
		R_WR_EN    <= W_DDS_VAL;
		R_WR_DATA  <= W_DDS_DATA; 
	end
	else
	begin
		R_WR_EN    <= 0;
		R_WR_DATA  <= 0; 
	end
end

// 读
always @(posedge W_CLK_RD_50M) 
begin 
	if(~W_OPR_RSTN) 
	begin
		 R_RD_EN<= 0;
	end 
	else 
	begin
		if(~W_FIFO_ALMOST_EMPTY)
		begin
			R_RD_EN<= 1;
		end
		else
		begin
			R_RD_EN <= 0;
		end
	end
end

// ------------------- 模块例化 -------------------------
ASYNC_FIFO #(
		.P_WR_DATA_WIDTH		     (P_WR_DATA_WIDTH),
		.P_RD_DATA_WIDTH		     (P_RD_DATA_WIDTH),
		.P_WR_ADDR_WIDTH		     (P_WR_ADDR_WIDTH),
		.P_RD_ADDR_WIDTH		     (P_RD_ADDR_WIDTH),
		.P_ALMOST_FULL_THRESHOLD     (P_ALMOST_FULL_THRESHOLD),
		.P_ALMOST_EMPTY_THRESHOLD    (P_ALMOST_EMPTY_THRESHOLD)
	) ASYNC_FIFO_INST (
		.I_WR_CLK_100M               (W_CLK_WR_100M),
		.I_WR_RSTN                   (W_OPR_RSTN),
		.I_WR_EN                     (R_WR_EN),
		.I_WR_DATA                   (R_WR_DATA),
		.O_FIFO_FULL                 (W_FIFO_FULL       ),
		.O_FIFO_ALMOST_FULL          (W_FIFO_ALMOST_FULL),

		.I_RD_CLK_50M                (W_CLK_RD_50M),
		.I_RD_RSTN                   (W_OPR_RSTN),
		.I_RD_EN                     (R_RD_EN),
		.O_RD_DATA_VAL               (W_RD_DATA_VAL),
		.O_RD_DATA                   (W_RD_DATA),
		.O_FIFO_EMPTY                (W_FIFO_EMPTY),
		.O_FIFO_ALMOST_EMPTY         (W_FIFO_ALMOST_EMPTY)
	);

// ------------------- IP例化 -------------------------

SYS_MMCM SYS_MMCM_INST
 (
  // Clock out ports
  .CLK_WR_100M(W_CLK_WR_100M),     // output CLK_WR_100M
  .CLK_RD_50M (W_CLK_RD_50M ) ,     // output CLK_RD_50M
  // Status and control signals
  .reset(I_SYS_RST), // input reset
  .locked(W_OPR_RSTN),       // output locked
 // Clock in ports
  .clk_in1(I_SYS_CLK_50M));      // input clk_in1

// DDS 输出位宽 8 采样率 100M 输出频率 1M 输出波形 正弦波
DDS_100_8 DDS_100_8_INST (
  .aclk(W_CLK_WR_100M),            // input wire aclk
  .m_axis_data_tvalid(W_DDS_VAL),    // output wire m_axis_data_tvalid
  .m_axis_data_tdata(W_DDS_DATA),   // output wire [7 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid(),  		   // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata()    		   // output wire [31 : 0] m_axis_phase_tdata
);

endmodule

IP CORE 配置

DDS:

Verilog 代码题练手 (2-2)_第1张图片

Verilog 代码题练手 (2-2)_第2张图片

Verilog 代码题练手 (2-2)_第3张图片

Verilog 代码题练手 (2-2)_第4张图片

Verilog 代码题练手 (2-2)_第5张图片

 时钟 IP:

50M单端输入,输出100M、50M两个时钟

仿真

TESTBENCH:

`timescale 1ns / 1ps



module TB_TOP_ASYNC_FIFO();
reg  								I_SYS_CLK_50M;
reg 								I_SYS_RST;     //板上开关控制
reg									I_OPR_CTRL;



initial I_SYS_CLK_50M = 0;
always #10 I_SYS_CLK_50M = ~I_SYS_CLK_50M;
initial 
begin
	I_SYS_RST = 1;
	I_OPR_CTRL = 0;
	#100;
	I_SYS_RST = 0;
	#100;
	I_OPR_CTRL = 1;


end

TOP_ASYNC_FIFO_VERIFY inst_TOP_ASYNC_FIFO_VERIFY
	(
		.I_SYS_CLK_50M       (I_SYS_CLK_50M),
		.I_SYS_RST           (I_SYS_RST),
		.I_OPR_CTRL			 (I_OPR_CTRL)
	);

endmodule

波形:

Verilog 代码题练手 (2-2)_第6张图片

Verilog 代码题练手 (2-2)_第7张图片

Verilog 代码题练手 (2-2)_第8张图片

板级调试

引脚约束、综合、实现、产生比特流。

按键SW0控制系统复位;SW1控制写入FIFO使能;只要FIFO不是将空状态一直读取FIFO数据。

抓取的DEBUG信号波形如下:

Verilog 代码题练手 (2-2)_第9张图片

Verilog 代码题练手 (2-2)_第10张图片

 



 

你可能感兴趣的:(Verilog,编程题,刷题,异步FIFO,内插,DDS)