【FPGA项目】System Generator算法板级验证-快速搭建外围测试电路

🎉欢迎来到FPGA专栏~System Generator算法板级验证-快速搭建外围测试电路


  • ☆* o(≧▽≦)o *☆~我是小夏与酒🍹
  • 博客主页:小夏与酒的博客
  • 🎈该系列文章专栏:FPGA学习之旅
  • 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
  • 📜 欢迎大家关注! ❤️
    FPGQ2

CSDN

🎉 目录-System Generator算法板级验证-快速搭建外围测试电路

  • 一、效果演示
    • 🔸项目介绍
    • 🔸项目演示效果
    • 🔸操作过程演示
  • 二、说明
  • 三、Matlab数据存为bin文件
  • 四、串口收发模块
  • 五、系统各模块详细说明

遇见未来

一、效果演示

🔸项目介绍

使用System Generator搭建算法时,为了快速进行算法正确性的板级验证,只需要将算法的算法时钟端口数据输入端口结果输出端口保留,如下图所示:
sysgen
为了控制算法模块,需要实现数据输入的控制算法启动数据输出的控制等。本篇文章搭建简单的外围电路实现对sysgen算法的控制和执行。

🔸项目演示效果

在本项目中,使用Verilog HDL编写了一个和使用System Generator搭建的算法模块类似的模块,该模块实现的功能是对输入的两个32位的非负整型数据进行相加。该模块有时钟端口复位端口两个数据输入端口一个数据输出端口,如下图所示:
算法模块
使用matlab生成两组1-100随机非负整数,每组数据的个数为100个两组数据以及两组数据对应数据之和的波形绘图如下所示:
matlab
将两组数据存为bin文件并输入到FPGA中执行求和算法,将算法执行结果导出进行数据进制转换并使用matlab画图得到的结果如下所示:
FPGA结果
将FPGA运算得到的结果与matlab运算得到的结果进行对比,算法执行结果一致,如下图所示:
最终结果
本项目的完整系统包括时钟模块、vio控制、串口收发模块、计数器模块、ram控制模块、算法使能模块和算法模块。FPGA系统的RTL视图如下所示:
RTL

🔸操作过程演示

FPGA开发板与电脑连接:
实际连接图
系统串口波特率为115200

项目主要使用到vio控制串口助手收发数据,串口将bin文件数据发送给FPGA并存入到ram1ram2中,运行算法之后的结果存储到ram3中,通过控制从串口将结果数据读出。vio使用4个输出信号控制系统:信号1置为高电平时,存入第一组bin文件数据到ram1中;信号2置为高电平时,存入第二组bin文件数据到ram2中;信号3置为高电平时,执行sysgen算法模块信号4置为高电平时,将ram3中的结果数据通过串口读取出来。操作过程视频如下所示:

【FPGA项目】System Generator算法板级验证

二、说明

本项目基于《【FPGA项目】bin文件ram存取回环测试》来搭建完整的板级验证系统,建议小伙伴们可以先学习该篇文章的知识点。

需要该项目中的串口助手软件或者项目工程文件的小伙伴,直接加入QQ群,在群文件中搜索下载即可QQ群862135231
matlab版本:R2020b
vivado版本:2020.2
开发板型号:AXKU040
接口连接如下所示:
接口
工程文件目录结构如下所示:
目录结构

三、Matlab数据存为bin文件

关于bin文件的介绍和使用bin文件存储数据的原因,在该篇文章中已经做了讲解:《【FPGA项目】bin文件ram存取回环测试》。

通过串口将sysgen算法模块的运行结果导出时,串口助手可以将数据保存为hex格式,需要对数据进行简单的处理,再通过matlab将十六进制的结果数据转换成十进制即可。

本项目中的matlab代码如下,根据需要运行相关代码片段即可:

%% bin文件生成代码:生成两个随机波形数据的bin文件
%----------------------------------------------------
% 首先生成1-100的double类型随机整数;
% 将double类型随机整数转换为32位数据;
% 将转换后的数据保存为bin文件。
%----------------------------------------------------
clear;
clc;
close all;
% 生成1-100的double类型随机整数
random_data1 = randi([1 100], 1, 100);
random_data2 = randi([1 100], 1, 100);% 将double类型数据转换为uint32类型
random_data1_uint32 = uint32(random_data1);
random_data2_uint32 = uint32(random_data2);% 画图
figure;
x = 0:1:100-1;
subplot(3,1,1);
plot(x,random_data1_uint32,'b');
title('random data1');
grid on;subplot(3,1,2);
plot(x,random_data2_uint32,'g');
title('random data2');
grid on;subplot(3,1,3);
plot(x,random_data1_uint32+random_data2_uint32,'r');
title('random data1 + random data2');
grid on;% 将数据保存为bin文件
fid = fopen('random_data1.bin', 'wb');
fwrite(fid, random_data1_uint32, 'uint32');
fclose(fid);
fid = fopen('random_data2.bin', 'wb');
fwrite(fid, random_data2_uint32, 'uint32');
fclose(fid);disp('波形数据已生成并保存为random_data1.bin和random_data2.bin');%% 读取txt文档中的数据,并转换成十进制
file_path = 'Rec240626210210.txt'; % 替换为实际文件路径
fileId = fopen(file_path, 'r');hex_values = cell(100, 1);
for i = 1:100hex_values{i} = fgetl(fileId);
endfclose(fileId);
dec_values = hex2dec(hex_values);figure;
x = 0:1:100-1;
plot(x,dec_values);
title('FPGA');
grid on;% 画图
figure;
x = 0:1:100-1;
subplot(4,1,1);
plot(x,random_data1_uint32,'b');
title('random data1');
grid on;subplot(4,1,2);
plot(x,random_data2_uint32,'g');
title('random data2');
grid on;subplot(4,1,3);
plot(x,random_data1_uint32+random_data2_uint32,'r');
title('random data1 + random data2');
grid on;subplot(4,1,4);
plot(x,dec_values);
title('FPGA');
grid on;

四、串口收发模块

整个sysgen算法的验证都是通过vio和串口来实现的。

关于串口收发模块的详细讲解,请点击如下两篇文章进行学习:
串口发送模块:【FPGA零基础学习之旅#13】串口发送模块设计与验证;
串口接收模块:【FPGA零基础学习之旅#15】串口接收模块设计与验证(工业环境)。

在此附上模块代码:

串口发送模块:

//
//模块名称:串口发送模块
//
module uart_byte_tx(input 		Clk,input 		Rst_n,input [7:0]	data_byte,input 		send_en,input [2:0]	baud_set,output reg uart_tx,output reg Tx_Done,output reg uart_state
);reg bps_clk;//波特率时钟reg [15:0]div_cnt;//分频计数器reg [15:0]bps_DR;//分频计数最大值reg [3:0]bps_cnt;//波特率计数时钟//定义数据的起始位和停止位localparam START_BIT = 1'b0;localparam STOP_BIT  = 1'b1;reg [7:0]r_data_byte;//数据寄存器//--------<uart状态模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)uart_state <= 1'b0;else if(send_en)uart_state <= 1'b1;else if(bps_cnt == 4'd11)//bps_cnt计数达到11次,即发送结束uart_state <= 1'b0;elseuart_state <= uart_state;end//--------<使能分频计数模块>-------	
//	assign en_cnt = uart_state;//--------<寄存待发送的数据,使数据保持稳定>--------always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)r_data_byte <= 8'd0;else if(send_en)r_data_byte <= data_byte;elser_data_byte <= r_data_byte;end//--------<波特率查找表>--------		always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_DR <= 16'd5207;else begincase(baud_set)0:bps_DR <= 16'd5207;1:bps_DR <= 16'd2603;2:bps_DR <= 16'd1301;3:bps_DR <= 16'd867;4:bps_DR <= 16'd433;default:bps_DR <= 16'd5207;endcaseend	end//--------<Div_Cnt模块>--------	
//得到不同计数周期的计数器always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)div_cnt <= 16'd0;else if(uart_state)begin	//	assign en_cnt = uart_state;if(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;end
//--------<bps_clk信号的产生>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;end//--------<bps_cnt计数模块>--------		always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_cnt <= 4'd0;else if(bps_cnt == 4'd11)//clr信号bps_cnt <= 4'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;end//--------<Tx_Done模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Tx_Done <= 1'b0;else if(bps_cnt == 4'd11)Tx_Done <= 1'b1;elseTx_Done <= 1'b0;end//--------<数据位输出模块-10选1多路器>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)uart_tx <= 1'b1;else begincase(bps_cnt)0:uart_tx <= 1'b1;1:uart_tx <= START_BIT;2:uart_tx <= r_data_byte[0];3:uart_tx <= r_data_byte[1];4:uart_tx <= r_data_byte[2];5:uart_tx <= r_data_byte[3];6:uart_tx <= r_data_byte[4];7:uart_tx <= r_data_byte[5];8:uart_tx <= r_data_byte[6];9:uart_tx <= r_data_byte[7];10:uart_tx <= STOP_BIT;default:uart_tx <= 1'b1;endcaseendendendmodule

串口接收模块:

//
//模块名称:串口接收模块(工业环境)
//
module uart_byte_rx(input 					Clk,//50Minput 					Rst_n,input 			[2:0]	baud_set,input 					data_rx,output 	reg 	[7:0]	data_byte,output 	reg			Rx_Done
);reg s0_Rx,s1_Rx;//同步寄存器reg tmp0_Rx,tmp1_Rx;//数据寄存器reg [15:0]bps_DR;//分频计数器计数最大值reg [15:0]div_cnt;//分频计数器reg bps_clk;//波特率时钟reg [7:0]bps_cnt;reg uart_state;reg [2:0] r_data_byte [7:0];reg [2:0]START_BIT;reg [2:0]STOP_BIT;wire nedge;//--------<同步寄存器处理>--------		
//用于消除亚稳态always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)begins0_Rx <= 1'b0;s1_Rx <= 1'b0;endelse begins0_Rx <= data_rx;s1_Rx <= s0_Rx;endend//--------<数据寄存器处理>--------		always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)begintmp0_Rx <= 1'b0;tmp1_Rx <= 1'b0;endelse begintmp0_Rx <= s1_Rx;tmp1_Rx <= tmp0_Rx;endend//--------<下降沿检测>--------	assign nedge = !tmp0_Rx & tmp1_Rx;//--------<div_cnt模块>--------	
//得到不同计数周期的计数器always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;end
//--------<bps_clk信号的产生>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;end//--------<bps_clk计数模块>--------		always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_cnt <= 8'd0;else if(bps_cnt == 8'd159 || (bps_cnt == 8'd12 && (START_BIT > 2)))bps_cnt <= 8'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;end//--------<Rx_Done模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)Rx_Done <= 1'b0;else if(bps_cnt == 8'd159)Rx_Done <= 1'b1;elseRx_Done <= 1'b0;end	//--------<波特率查找表>--------		always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)bps_DR <= 16'd324;else begincase(baud_set)0:bps_DR <= 16'd324;1:bps_DR <= 16'd162;2:bps_DR <= 16'd80;3:bps_DR <= 16'd53;4:bps_DR <= 16'd26;default:bps_DR <= 16'd324;endcaseend	end//--------<采样数据接收模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)beginSTART_BIT <= 3'd0;r_data_byte[0] <= 3'd0; r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0; r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0; r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0; r_data_byte[7] <= 3'd0;STOP_BIT <= 3'd0;endelse if(bps_clk)begincase(bps_cnt)0:beginSTART_BIT <= 3'd0;r_data_byte[0] <= 3'd0;r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0;r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0;r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0;r_data_byte[7] <= 3'd0;STOP_BIT <= 3'd0; end6,7,8,9,10,11:START_BIT <= START_BIT + s1_Rx;22,23,24,25,26,27:r_data_byte[0] <= r_data_byte[0] + s1_Rx;38,39,40,41,42,43:r_data_byte[1] <= r_data_byte[1] + s1_Rx;54,55,56,57,58,59:r_data_byte[2] <= r_data_byte[2] + s1_Rx;70,71,72,73,74,75:r_data_byte[3] <= r_data_byte[3] + s1_Rx;86,87,88,89,90,91:r_data_byte[4] <= r_data_byte[4] + s1_Rx;102,103,104,105,106,107:r_data_byte[5] <= r_data_byte[5] + s1_Rx;118,119,120,121,122,123:r_data_byte[6] <= r_data_byte[6] + s1_Rx;134,135,136,137,138,139:r_data_byte[7] <= r_data_byte[7] + s1_Rx;150,151,152,153,154,155:STOP_BIT <= STOP_BIT + s1_Rx;default:beginSTART_BIT <= START_BIT;r_data_byte[0] <= r_data_byte[0];r_data_byte[1] <= r_data_byte[1];r_data_byte[2] <= r_data_byte[2];r_data_byte[3] <= r_data_byte[3];r_data_byte[4] <= r_data_byte[4];r_data_byte[5] <= r_data_byte[5];r_data_byte[6] <= r_data_byte[6];r_data_byte[7] <= r_data_byte[7];STOP_BIT <= STOP_BIT;endendcaseendend//--------<数据状态判定模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)data_byte <= 8'd0;else if(bps_cnt == 8'd159)begindata_byte[0] <= r_data_byte[0][2];data_byte[1] <= r_data_byte[1][2];data_byte[2] <= r_data_byte[2][2];data_byte[3] <= r_data_byte[3][2];data_byte[4] <= r_data_byte[4][2];data_byte[5] <= r_data_byte[5][2];data_byte[6] <= r_data_byte[6][2];data_byte[7] <= r_data_byte[7][2];endelse;end//--------<uart_state模块>--------	always@(posedge Clk or negedge Rst_n)beginif(!Rst_n)uart_state <= 1'b0;else if(nedge)uart_state <= 1'b1;else if(Rx_Done || (bps_cnt == 8'd12 && (START_BIT > 2)))uart_state <= 1'b0;elseuart_state <= uart_state;endendmodule

五、系统各模块详细说明

本项目的完整系统包括时钟模块、vio控制、串口收发模块、计数器模块、ram控制模块、算法使能模块和算法模块。FPGA系统的RTL视图如下所示:
RTL
🔸时钟模块:
时钟模块

信号端口功能
rst_n复位
sys_clk_n200MHz差分时钟输入
sys_clk_p200MHz差分时钟输入
clk_50MHz输出50MHz时钟信号
clk_200MHz输出200MHz时钟信号

时钟模块的核心是pll ip核,为了使系统时钟更加稳定,将pll和外围电路封装为一个时钟模块,代码如下:

clk_200MHz_50MHz.v:

`timescale 1ns / 1psmodule clk_200MHz_50MHz(input 	sys_clk_p,input 	sys_clk_n,input	    rst_n,output 	clk_200MHz,output 	clk_50MHz
);wire clk_200MHz_r;wire clk_50MHz_r;wire locked;pll_200MHz_50MHz pll_200MHz_50MHz(// Clock out ports.clk_out1(clk_200MHz_r), //200MHz.clk_out2(clk_50MHz_r),  //50MHz// Status and control signals.resetn(rst_n),.locked(locked),// Clock in ports.clk_in1_p(sys_clk_p),.clk_in1_n(sys_clk_n) );assign clk_200MHz = (locked)?clk_200MHz_r:1'b0;assign clk_50MHz  = (locked)?clk_50MHz_r :1'b0;endmodule

🔸vio控制:
vio
vio ip核四个输出端口的信号作用如上文中所述:

vio使用4个输出信号控制系统:信号1置为高电平时,存入第一组bin文件数据到ram1中;信号2置为高电平时,存入第二组bin文件数据到ram2中;信号3置为高电平时,执行sysgen算法模块信号4置为高电平时,将ram3中的结果数据通过串口读取出来。

🔸串口收发模块:
串口收发模块在本文的第四节(“四、串口收发模块”)中已提及,收发模块端口如下图所示:
r'x
t'x

🔸计数器模块:
计数器模块

信号端口功能
rst_n复位
clk_200MHz输入200MHz时钟信号
all_cnt_times输入计数器的计数总数
probe_out3计数器使能控制信号(来自vio)
all_cnt输出计数器当前的计数值

计数器模块的作用: 用来控制sysgen算法模块运行的时钟周期数。如输入计数总数为32’d100,则sysgen模块执行100个时钟周期。当计数器计数到输入的计数总数时,计数器的值保持不变,该模块代码如下:

cnt.v:

`timescale 1ns / 1psmodule cnt(input                   clk_200MHz,input                   rst_n,input                   probe_out3,input       [32-1:0]    all_cnt_times,output reg  [32-1:0]    all_cnt
);always@(posedge clk_200MHz or negedge rst_n)beginif(!rst_n)all_cnt <= 32'd0;else if(probe_out3 && all_cnt < all_cnt_times)all_cnt <= all_cnt + 1'b1;else if(probe_out3 && all_cnt == all_cnt_times)all_cnt <= all_cnt_times;elseall_cnt <= all_cnt;endendmodule

🔸ram控制模块:
ram控制模块主要包括两个输入bin文件存储模块一个运算结果保存模块
输入bin文件存储模块——re:
re

ram_re_ctrl.v:

`timescale 1ns / 1psmodule ram_re_ctrl(input               clk_50MHz,input               clk_200MHz,input               rst_n,input               probe_out1,input   [7:0]       data_byte_rx,input               Rx_Done,input   [32-1:0]    all_cnt,input               probe_out3,output  [32-1:0]    doutb_re
);reg     [17-1:0]    addra_re;wire    [8-1:0]     dina_re;always@(posedge clk_50MHz or negedge rst_n)beginif(!rst_n)addra_re <= 17'd0;else if(probe_out1 && Rx_Done)addra_re <= addra_re + 1'b1;elseaddra_re <= addra_re;endassign dina_re = (probe_out1)?data_byte_rx:8'b0;ram_re ram_re(.clka(clk_50MHz),    // input wire clka.ena(probe_out1),      // input wire ena.wea(Rx_Done),      // input wire [0 : 0] wea.addra(addra_re),  // input wire [16 : 0] addra.dina(dina_re),    // input wire [7 : 0] dina.clkb(clk_200MHz),    // input wire clkb.enb(probe_out3),      // input wire enb.addrb(all_cnt),  // input wire [14 : 0] addrb.doutb(doutb_re)  // output wire [31 : 0] doutb);endmodule

输入bin文件存储模块——im:
im

ram_im_ctrl.v:

`timescale 1ns / 1psmodule ram_im_ctrl(input               clk_50MHz,input               clk_200MHz,input               rst_n,input               probe_out2,input   [7:0]       data_byte_rx,input               Rx_Done,input   [32-1:0]    all_cnt,input               probe_out3,output  [32-1:0]    doutb_im
);reg     [17-1:0]    addra_im;wire    [8-1:0]     dina_im;always@(posedge clk_50MHz or negedge rst_n)beginif(!rst_n)addra_im <= 17'd0;else if(probe_out2 && Rx_Done)addra_im <= addra_im + 1'b1;elseaddra_im <= addra_im;endassign dina_im = (probe_out2)?data_byte_rx:8'b0;ram_im ram_im(.clka(clk_50MHz),    // input wire clka.ena(probe_out2),      // input wire ena.wea(Rx_Done),      // input wire [0 : 0] wea.addra(addra_im),  // input wire [16 : 0] addra.dina(dina_im),    // input wire [7 : 0] dina.clkb(clk_200MHz),    // input wire clkb.enb(probe_out3),      // input wire enb.addrb(all_cnt),  // input wire [14 : 0] addrb.doutb(doutb_im)  // output wire [31 : 0] doutb);endmodule

运算结果保存模块:
result
该模块端口中有一个信号端口为:delay_cnt_times,该信号的作用是延迟存储数据。如输入32‘d10给该信号端口,则会在sysgen模块运行10个时钟周期后才存储sysgen模块的运算结果到ram3中。

ram_result_ctrl.v:

`timescale 1ns / 1psmodule ram_result_ctrl(input               clk_50MHz,input               clk_200MHz,input               rst_n,input               probe_out3,input               probe_out4,input   [32-1:0]    delay_cnt_times,input   [32-1:0]    all_cnt_times,input   [32-1:0]    all_cnt,input               Tx_Done,input   [32-1:0]    dina_ot,output              send_en,output  [7:0]       data_byte_tx
);reg          wea_result;reg          rea_result;reg [32-1:0] delay_cnt;reg [9:0]   addra_ot;reg [11:0]  addrb_ot;reg [7:0]   doutb_ot;always@(posedge clk_200MHz or negedge rst_n)beginif(!rst_n)delay_cnt <= 32'd0;else if(probe_out3 && delay_cnt < delay_cnt_times)delay_cnt <= delay_cnt + 1'b1;else if(probe_out3 && delay_cnt == delay_cnt_times)delay_cnt <= delay_cnt_times;elsedelay_cnt <= delay_cnt;endalways@(posedge clk_200MHz or negedge rst_n)beginif(!rst_n)wea_result <= 1'b0;else if(probe_out3 && delay_cnt == delay_cnt_times && all_cnt != all_cnt_times)wea_result <= 1'b1;elsewea_result <= 1'b0;endalways@(posedge clk_200MHz or negedge rst_n)beginif(!rst_n)addra_ot <= 10'd0;else if(wea_result)addra_ot <= addra_ot + 1'b1;elseaddra_ot <= addra_ot;endram_result ram_result(.clka(clk_200MHz),    // input wire clka.ena(probe_out3),      // input wire ena.wea(wea_result),      // input wire [0 : 0] wea.addra(addra_ot),  // input wire [7 : 0] addra.dina(dina_ot),    // input wire [31 : 0] dina.clkb(clk_50MHz),    // input wire clkb.enb(rea_result),      // input wire enb.addrb(addrb_ot),  // input wire [9 : 0] addrb.doutb(data_byte_tx)  // output wire [7 : 0] doutb);always@(posedge clk_50MHz or negedge rst_n)beginif(!rst_n)rea_result <= 1'b0;else if(probe_out4 && addrb_ot < 11'd2000)rea_result <= 1'b1;else if(addrb_ot == 11'd2000)rea_result <= 1'b0;elserea_result <= rea_result;endassign send_en = rea_result;always@(posedge clk_50MHz or negedge rst_n)beginif(!rst_n)addrb_ot <= 10'd0;else if(rea_result && Tx_Done)addrb_ot <= addrb_ot + 1'b1;elseaddrb_ot <= addrb_ot;endendmodule

🔸算法模块:
算法模块

信号端口功能
rst_n复位
sys_clk输入算法模块时钟信号
input_data1输入算法数据1
input_data2输入算法数据2
output_data输出算法执行结果

算法模块只实现简单的32位无符号整型数据相加,代码如下:

sysgen.v:

`timescale 1ns / 1psmodule sysgen(input 					sys_clk,//200MHzinput 					rst_n,input 		[32-1:0] 	input_data1,input 		[32-1:0] 	input_data2,output 	reg [32-1:0] 	output_data
);always@(posedge sys_clk or negedge rst_n)beginif(!rst_n)output_data <= 32'd0;elseoutput_data <= input_data1 + input_data2;endendmodule

🔸算法使能模块:
算法使能模块

信号端口功能
rst_n复位
sys_clk输入算法模块时钟信号
input_data1输入算法数据1

为了快速对sysgen算法进行板级验证,在搭建sysgen的时候只需保留数据端口时钟端口即可。因此,要控制算法的启动、暂停或停止,只能通过控制sysgen模块的时钟端口来实现,算法使能模块代码如下:

sysgen_clk_en.v:

`timescale 1ns / 1psmodule sysgen_clk_en(input 	clk_200MHz,input 	probe_out3,output 	sysgen_clk
);assign sysgen_clk = (probe_out3)?clk_200MHz:1'b0;endmodule

🔸顶层模块:

uart_io.v:

`timescale 1ns / 1psmodule uart_io(input 	sys_clk_p,input 	sys_clk_n,input 	rst_n,input 	uart_rx,output 	uart_tx
);localparam baud_bps = 3'b100;//115200localparam delay_cnt_times = 32'd1;localparam all_cnt_times   = 32'd102;wire clk_200MHz;wire clk_50MHz;wire [7:0] data_byte_rx;wire [7:0] data_byte_tx;wire Tx_Done;wire Rx_Done;wire probe_out1;wire probe_out2;wire probe_out3;wire probe_out4;wire [32-1:0] all_cnt;wire [32-1:0] doutb_re;wire [32-1:0] doutb_im;wire [32-1:0] dina_ot;wire send_en;//---------------------------------------sysgen inst_sysgen(.sys_clk     (sysgen_clk),.rst_n       (rst_n),.input_data1 (doutb_re),.input_data2 (doutb_im),.output_data (dina_ot));//---------------------------------------sysgen_clk_en inst_sysgen_clk_en(.clk_200MHz(clk_200MHz), .probe_out3(probe_out3), .sysgen_clk(sysgen_clk));clk_200MHz_50MHz inst_clk_200MHz_50MHz(.sys_clk_p  (sys_clk_p),.sys_clk_n  (sys_clk_n),.rst_n      (rst_n),.clk_200MHz (clk_200MHz),.clk_50MHz  (clk_50MHz));vio_0 vio(.clk        (clk_50MHz),                // input wire clk.probe_out0 (),  // output wire [0 : 0] probe_out0.probe_out1 (probe_out1),  // output wire [0 : 0] probe_out1.probe_out2 (probe_out2),  // output wire [0 : 0] probe_out2.probe_out3 (probe_out3),  // output wire [0 : 0] probe_out3.probe_out4 (probe_out4)  // output wire [0 : 0] probe_out4);cnt inst_cnt(.clk_200MHz    (clk_200MHz),.rst_n         (rst_n),.probe_out3    (probe_out3),.all_cnt_times (all_cnt_times),.all_cnt       (all_cnt));uart_byte_rx inst_uart_byte_rx(.Clk       (clk_50MHz),.Rst_n     (rst_n),.baud_set  (baud_bps),.data_rx   (uart_rx),.data_byte (data_byte_rx),.Rx_Done   (Rx_Done));ram_re_ctrl inst_ram_re_ctrl(.clk_50MHz    (clk_50MHz),.clk_200MHz   (clk_200MHz),.rst_n        (rst_n),.probe_out1   (probe_out1),.data_byte_rx (data_byte_rx),.Rx_Done      (Rx_Done),.all_cnt      (all_cnt),.probe_out3   (probe_out3),.doutb_re     (doutb_re));ram_im_ctrl inst_ram_im_ctrl(.clk_50MHz    (clk_50MHz),.clk_200MHz   (clk_200MHz),.rst_n        (rst_n),.probe_out2   (probe_out2),.data_byte_rx (data_byte_rx),.Rx_Done      (Rx_Done),.all_cnt      (all_cnt),.probe_out3   (probe_out3),.doutb_im     (doutb_im));ram_result_ctrl inst_ram_result_ctrl(.clk_50MHz       (clk_50MHz),.clk_200MHz      (clk_200MHz),.rst_n           (rst_n),.probe_out3      (probe_out3),.probe_out4      (probe_out4),.delay_cnt_times (delay_cnt_times),.all_cnt_times   (all_cnt_times),.all_cnt         (all_cnt),.Tx_Done         (Tx_Done),.dina_ot         (dina_ot),.send_en         (send_en),.data_byte_tx    (data_byte_tx));uart_byte_tx inst_uart_byte_tx(.Clk        (clk_50MHz),.Rst_n      (rst_n),.data_byte  (data_byte_tx),.send_en    (send_en),.baud_set   (baud_bps),.uart_tx    (uart_tx),.Tx_Done    (Tx_Done),.uart_state ());endmodule

csdn

🧸结尾


  • ❤️ 感谢您的支持和鼓励! 😊🙏
  • 📜您可能感兴趣的内容:
  • 【FPGA零基础学习之旅#17】搭建串口收发与储存双口RAM系统
  • 【Python】串口通信-与FPGA、蓝牙模块实现串口通信(Python+FPGA)
  • 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
  • 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制
    遇见未来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/35274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【微服务网关——中间件实现】

1.中间件的意义 避免成为if狂魔提高复用、隔离业务调用清晰、组合随意 2.实现原理 中间件一般都封装在路由上&#xff0c;路由是URL请求分发的管理器中间件选型 基于链表构建中间件 基于责任链的实现缺点&#xff1a;实现复杂&#xff0c;调用方式不灵活 使用数组构建中间件 控…

大模型笔记1: Longformer环境配置

论文: https://arxiv.org/abs/2004.05150 首先保证电脑上配置了git. git环境配置: https://blog.csdn.net/Andone_hsx/article/details/87937329 3.1、找到git安装路径中bin的位置&#xff0c;如&#xff1a;D:\Program Files\Git\bin 找到git安装路径中git-core的…

PostgreSQL 连接器:在 SeaTunnel 中的应用与优势

在现代企业中&#xff0c;数据已经成为核心资产&#xff0c;基于开源数据集成平台SeaTunnel&#xff0c;工程师如何高效地连接和管理这些数据源&#xff0c;直接关系到企业的竞争力和运营效率。 本文将给大家介绍如何通过 JDBC PostgreSQL 数据源连接器&#xff0c;在 SeaTunne…

第15周:RNN心脏病预测

目录 前言 二、前期准备 2.1 设置GPU 2.2 导入数据 2.2.1 数据介绍 2.2.2 导入代码 2.2.3 检查数据 三、数据预处理 3.1 划分训练集与测试集 3.2 标准化 四、构建RNN模型 4.1 基本概念 4.2 搭建代码 五、编译模型 六、训练模型 七、模型评估 总结 前言 &#…

直播怎么录制视频?直播视频,3种录制方法

“今晚我最喜欢的游戏博主要进行直播&#xff0c;但我可能还要加班。怎么办&#xff0c;不想错过直播的内容&#xff01;电脑怎么才能进行直播录制视频啊&#xff1f;谁能教教我&#xff1f;” 在数字化的今天&#xff0c;直播已经成为人们获取信息和娱乐的重要途径。有时&…

执行yum命令报错Could not resolve host: mirrors.cloud.aliyuncs.com; Unknown error

执行yum命令报错 [Errno 14] curl#6 - "Could not resolve host: mirrors.cloud.aliyuncs.com; Unknown error 修改图中所示两个文件&#xff1a; vim epel.repo vim CentOS-Base.repo 将所有的http://mirrors.cloud.aliyuncs.com 修改为http://mirrors.aliyun.com。 修改…

趣测系统搭建APP源码开发,娱乐丰富生活的选择!

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 趣测系统提供了一个集合多种有趣测试的平台&#xff0c;如心理测试和星座测试等&#xff0c;这些测试内容富有趣味性和娱乐性&#xff0c;能够帮助大众在忙碌的生活中找到放松和娱乐的时刻…

yolov5驾驶员不规范行为检测

1 项目介绍 1.1 摘要 随着汽车工业的迅速发展和交通拥堵的加剧&#xff0c;驾驶员在行车过程中的不规范行为成为了导致交通事故频发的重要因素之一。为了减少交通事故的发生&#xff0c;保障道路安全&#xff0c;提高驾驶员的行车安全意识&#xff0c;本研究致力于实现驾驶员…

5. PyTorch+NCCL源码编译

系列文章 第1章 多机多卡运行nccl-tests 和channel获取第2章 多机多卡nccl-tests 对比分析第3章 使用tcpdump抓取rdma数据包第5章 PyTorchNCCL源码编译 目录 系列文章前言一、本地环境二、安装cudnn三、使用pytorch自带NCCL库进行编译安装1. 源码编译2. 查看版本和all_reduce测…

【机器学习】机器学习重要方法——迁移学习:理论、方法与实践

文章目录 迁移学习&#xff1a;理论、方法与实践引言第一章 迁移学习的基本概念1.1 什么是迁移学习1.2 迁移学习的类型1.3 迁移学习的优势 第二章 迁移学习的核心方法2.1 特征重用&#xff08;Feature Reuse&#xff09;2.2 微调&#xff08;Fine-Tuning&#xff09;2.3 领域适…

【启明智显分享】典型的HMI应用实现方案:帮你更好地主控选型!

HMI是操作者与机器/系统间资讯传递和交换的主要桥梁。HMI系统通常能提供丰富的资讯&#xff0c;例如温度、压力、制造流程步骤以及材料的计量数据。还能显示设备中物料的确切位置或储存槽内的液位数据等讯息。无论是在工业自动化还是医疗、商业等重要行业领域&#xff0c;HMI都…

【前端项目笔记】6 参数管理

参数管理 效果展示&#xff1a; 在开发功能之前先创建分支goods_params cls 清空终端 git branch 查看所有分支 git checkout -b goods_params 新建分支goods_params git push -u origin goods_params 把本地的新分支推送到云端origin并命名为goods_params 参数管理需要维…

一个易于使用、与Android系统良好整合的多合一游戏模拟器

大家好&#xff0c;今天给大家分享的是一个易于使用、与Android系统良好整合的多合一游戏模拟器 Lemuroid。 Lemuroid 是一个专为Android平台设计的开源游戏模拟器项目&#xff0c;它基于强大的Libretro框架&#xff0c;旨在提供广泛的兼容性和卓越的用户体验。 项目介绍 Lem…

如何安装多版本CUDA?

首先聊一个题外话&#xff1a;前几天在csdn上看到的一个话题”安装pytorch一定要去nvidia官网下载安装cuda和cudnn吗&#xff1f;“ 我相信任何一个刚开始接触或者从事深度学习的炼丹者都会从安装cuda开始&#xff0c;现在网上随便一搜如何安装pytorch&#xff0c;蹦出来教程提…

pd虚拟机 Parallels Desktop 19 for Mac 破解版小白安装使用指南

Parallels Desktop 19 for Mac 乃是一款适配于 Mac 的虚拟化软件。它能让您在 Mac 计算机上同时运行多个操作系统。您可借此创建虚拟机&#xff0c;并于其中装设不同的操作系统&#xff0c;如 Windows、Linux 或 macOS。使用 Parallels Desktop 19 mac 版时&#xff0c;您可在 …

无线麦克风推荐哪些品牌,一文揭秘无线麦克风领夹哪个牌子好!

​究竟该如何选择麦克风呢&#xff1f;又该如何挑选无线麦克呢&#xff1f;询问我关于麦克风选择问题的人着实不少。对于那些仅仅是想要简单地自我娱乐的朋友而言&#xff0c;着实没必要去折腾&#xff0c;直接使用手机自带的麦克风便可以了。 但若是处于想要直播、拍摄短视频…

【Termius】详细说明MacOS中的SSH的客户端利器Termius

希望文章能给到你启发和灵感~ 如果觉得有帮助的话,点赞+关注+收藏支持一下博主哦~ 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境二、软件的安装2.1 Termius界面介绍2.1.1 Hosts 主机列表2.1.2 SFTP 文件传输2.1.3 Port ForWarding 端口转发2.1.4 Snippets 片…

为什么带货主播,他突然就不吃香了?

为什么带货主播他突然就不吃香了&#xff1f;工资骤降50%。 相比 2023 年初主播的平均薪资降了50%&#xff0c;那不管你是头部主播还是腰部主播&#xff0c;全部都降薪了。那尾部主播就更不用说了&#xff0c;有的主播他的时薪已经低到 20 块钱一个小时&#xff0c;还不如大学…

U-boot相关基础知识

U-boot和Bootloader之间的关系 U-Boot是Bootloader的一种实现&#xff0c;它专门用于嵌入式系统&#xff0c;特别是那些基于ARM、MIPS等处理器的系统。U-Boot提供了丰富的硬件支持和功能&#xff0c;使得开发者能够轻松地初始化硬件、加载操作系统内核&#xff0c;并进行一些基…

【漏洞复现】安美数字酒店宽带运营系统——命令执行漏洞(CNVD-2021-37784)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 安美数字酒店宽带运营系统 server_ping.php 存在远程命令执行漏洞&#…