赞
踩
FPGA基础 – 通信协议 — 了解UART以及电脑串口环境准备
FPGA实战 – UART — 实现串口回环(加FIFO)
咱们已经学习了UART协议,并且编写了串口回环的代码。每次一些项目遇到串口的时候都要对 RX 或者 TX 代码进行修改,像本人这种非非非非常懒的人,肯定不愿意经常修改代码,所以制作一个IP核会非常方便,只需要调用一下,在top顶层连一连wire就能使用了。简直就是上天赐予的礼物。
首先创建一个文件夹,记得找一个不会删的地址来创建。因为自己封装的IP核需要Quartus检测这个文档才能使用,所以放在一个不会动的文件夹里比较好。我建议直接放进Quartus的安装文件里。
这个IP核的代码直接贴在这里,这个代码不用看不用理解不用试验,只需要知道日常IP核的底层代码是咱们看不到的,相当于自己做了一个非常简单的软核。目前市面上有一些专门做IP核的公司,这篇文章做的和这些公司出品的根本比不了,但日常自己使用就已经够了,一些简单的工程项目也可以调用。
直接创建一个文件夹,建立几个.v文件把代码复制进去就行。
//例化模板: // uart_tx #( // .CHECK_BIT ("None" ), //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 // .BPS (115200 ), //UART波特率 // .CLK (50000000 ) //工作时钟 // )uart_tx_inst( // /* input */.clk (clk ), // /* input */.rst_n (rst_n ), // /* input [7:0] */.tx_data ( ), // /* input */.tx_data_vld ( ), // /* output */.ready ( ), // /* output reg */.tx ( ) // ); module uart_tx #( parameter CHECK_BIT = "None" , //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 parameter BPS = 115200 , //UART波特率 parameter CLK = 50000000 //工作时钟 )( input clk , input rst_n , input [7:0] tx_data , input tx_data_vld , output ready , output reg tx ); parameter IDLE = 0, START = 1, DATA = 2, CHECK = 3, STOP = 4; reg [2:0] state ; wire idle2start ; wire start2data ; wire data2check ; wire data2stop ; wire check2stop ; wire stop2idle ; reg [12:0] cnt_bps ; wire add_bps_cnt ; wire end_bps_cnt ; parameter BPS_MAX = CLK/BPS; //计算在设定的波特率下,一个bit占用的时钟周期数 reg [3:0] cnt_bit ; wire add_bit_cnt ; wire end_bit_cnt ; reg [3:0] bit_max ; reg [7:0] tx_data_r ; wire check_val ; /************************************************************** 状态机 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) state <= IDLE; else case(state) IDLE : if(idle2start) state <= START; START : if(start2data) state <= DATA; DATA : if(data2stop) //无校验位 state <= STOP; else if(data2check) //有校验位 state <= CHECK; CHECK : if(check2stop) state <= STOP; STOP : if(stop2idle) state <= IDLE; default : state <= IDLE; endcase assign idle2start = state == IDLE && tx_data_vld; assign start2data = state == START && end_bit_cnt; assign data2stop = state == DATA && end_bit_cnt && CHECK_BIT == "None"; assign data2check = state == DATA && end_bit_cnt; assign check2stop = state == CHECK && end_bit_cnt; assign stop2idle = state == STOP && end_bit_cnt; /************************************************************** 波特率计数器 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) cnt_bps <= 'd0; else if(add_bps_cnt) begin if(end_bps_cnt) cnt_bps <= 'd0; else cnt_bps <= cnt_bps + 1'b1; end assign add_bps_cnt = state != IDLE; assign end_bps_cnt = add_bps_cnt && cnt_bps == BPS_MAX - 1; /************************************************************** 比特计数器 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) cnt_bit <= 'd0; else if(add_bit_cnt) begin if(end_bit_cnt) cnt_bit <= 'd0; else cnt_bit <= cnt_bit + 1'b1; end assign add_bit_cnt = end_bps_cnt; assign end_bit_cnt = add_bit_cnt && cnt_bit == bit_max - 1; always@(*) case(state) IDLE : bit_max = 1; START : bit_max = 1; DATA : bit_max = 8; CHECK : bit_max = 1; STOP : bit_max = 1; default : bit_max = 1; endcase /************************************************************** 输入数据寄存 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) tx_data_r <= 0; else if(tx_data_vld) tx_data_r <= tx_data; /************************************************************** 计算校验位 **************************************************************/ //奇校验,缩位同或运算 //assign check_val = ~^tx_data_r; //偶校验,缩位异或运算 //assign check_val = ^tx_data_r; assign check_val = (CHECK_BIT == "Odd")? ~^tx_data_r : ^tx_data_r; /************************************************************** 实现串口时序 **************************************************************/ always@(*) case(state) IDLE : tx = 1; START : tx = 0; DATA : if(tx_data_r[cnt_bit]) //先发低位,再发高位 tx = 1; else tx = 0; CHECK : tx = check_val; STOP : tx = 1; default : tx = 1; endcase assign ready = state == IDLE; endmodule
//例化模板: // uart_rx #( // .CHECK_BIT ("None" ), //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 // .BPS (115200 ), //UART波特率 // .CLK (50000000 ) //工作时钟 // )uart_rx_inst( // /* input */.clk (clk ), // /* input */.rst_n (rst_n ), // /* output [7:0] */.rx_data ( ), // /* output */.rx_data_vld ( ), // /* output */.ready ( ), // /* input */.rx ( ) // ); module uart_rx #( parameter CHECK_BIT = "None" , //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 parameter BPS = 115200 , //UART波特率 parameter CLK = 50000000 //工作时钟 )( input clk , input rst_n , output [7:0] rx_data , output rx_data_vld , output ready , input rx ); parameter IDLE = 0, START = 1, DATA = 2, CHECK = 3; reg [1:0] state ; wire idle2start ; wire start2data ; wire data2idle ; wire data2check ; wire check2idle ; reg [12:0] cnt_bps ; wire add_bps_cnt ; wire end_bps_cnt ; parameter BPS_MAX = CLK/BPS; //计算在设定的波特率下,一个bit占用的时钟周期数 reg [3:0] cnt_bit ; wire add_bit_cnt ; wire end_bit_cnt ; reg [3:0] bit_max ; reg [7:0] rx_temp ; /************************************************************** 下降沿检测 **************************************************************/ reg rx_r1 ; reg rx_r2 ; wire rx_nege ; always@(posedge clk or negedge rst_n) if(!rst_n) begin rx_r1 <= 1; rx_r2 <= 1; end else begin rx_r1 <= rx; //同步 rx_r2 <= rx_r1; //输入打拍,判断下降沿 end assign rx_nege = !rx_r1 && rx_r2; /************************************************************** 状态机 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) state <= IDLE; else case(state) IDLE : if(idle2start) state <= START; START : if(start2data) state <= DATA; DATA : if(data2idle) //无校验位 state <= IDLE; else if(data2check) //有校验位 state <= CHECK; CHECK : if(check2idle) state <= IDLE; default : state <= IDLE; endcase assign idle2start = state == IDLE && rx_nege; assign start2data = state == START && end_bit_cnt; assign data2idle = state == DATA && end_bit_cnt && CHECK_BIT == "None"; assign data2check = state == DATA && end_bit_cnt; assign check2idle = state == CHECK && end_bit_cnt; /************************************************************** 波特率计数器 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) cnt_bps <= 'd0; else if(add_bps_cnt) begin if(end_bps_cnt) cnt_bps <= 'd0; else cnt_bps <= cnt_bps + 1'b1; end assign add_bps_cnt = state != IDLE; assign end_bps_cnt = add_bps_cnt && cnt_bps == BPS_MAX - 1; /************************************************************** 比特计数器 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) cnt_bit <= 'd0; else if(add_bit_cnt) begin if(end_bit_cnt) cnt_bit <= 'd0; else cnt_bit <= cnt_bit + 1'b1; end assign add_bit_cnt = end_bps_cnt; assign end_bit_cnt = add_bit_cnt && cnt_bit == bit_max - 1; always@(*) case(state) IDLE : bit_max = 1; START : bit_max = 1; DATA : bit_max = 8; CHECK : bit_max = 1; default : bit_max = 1; endcase /************************************************************** 校验位处理 **************************************************************/ reg rev_check ; wire check_val ; //接收校验位 always@(posedge clk or negedge rst_n) if(!rst_n) rev_check <= 0; else if(state == CHECK && cnt_bps == BPS_MAX >> 1) rev_check <= rx_r1; //计算校验位 assign check_val = (CHECK_BIT == "Odd")? ~^rx_temp : ^rx_temp; /************************************************************** 实现接收数据 **************************************************************/ always@(posedge clk or negedge rst_n) if(!rst_n) rx_temp <= 0; else if(state == DATA && cnt_bps == BPS_MAX >> 1) rx_temp[cnt_bit] <= rx_r1; assign rx_data = rx_temp; assign rx_data_vld = (CHECK_BIT == "None")? data2idle //无校验方式输出数据有效信号 : (check2idle && (check_val == rev_check))? 1 //有校验方式时,计算的校验值与接收的校验值一致,才能输出有效信号 : 0; assign ready = state == IDLE; endmodule
module ctrl( input uart_clk , //50m input rst_n , //TX通道 input user_tx_clk , //比如80m input [7:0] user_tx_data , input user_tx_data_vld, output user_tx_ready , //RX通道 input user_rx_clk , output user_rx_ready , //表示串口已经收到数据了,可以读出 input user_rx_rd_req , output [7:0] user_rx_data , output user_rx_data_vld, //与UART接口交互 input [7:0] rx_data , input rx_data_vld , output [7:0] tx_data , output tx_data_vld , input tx_ready ); /************************************************************** 实现TX通道的缓存、跨时钟域 **************************************************************/ wire tx_fifo_empty; wire tx_fifo_full; uart_fifo tx_fifo ( .aclr ( ~rst_n ), .data ( user_tx_data ), .wrclk ( user_tx_clk ), .wrreq ( user_tx_data_vld && !tx_fifo_full ), .rdclk ( uart_clk ), .rdreq ( tx_ready && !tx_fifo_empty ), .q ( tx_data ), .rdempty ( tx_fifo_empty ), .wrfull ( tx_fifo_full ) ); assign tx_data_vld = tx_ready && !tx_fifo_empty; assign user_tx_ready = !tx_fifo_full; //只要fifo没有满,就可以继续接收需要发送的数据 /************************************************************** 实现RX通道的缓存、跨时钟域 **************************************************************/ wire rx_fifo_empty; wire rx_fifo_full; wire rx_fifo_rd_req; uart_fifo rx_fifo ( .aclr ( ~rst_n ), .data (rx_data ), .wrclk (uart_clk ), .wrreq (rx_data_vld && !rx_fifo_full), .rdclk (user_rx_clk ), .rdreq (rx_fifo_rd_req ), .q (user_rx_data ), .rdempty ( rx_fifo_empty ), .wrfull ( rx_fifo_full ) ); assign rx_fifo_rd_req = user_rx_rd_req && !rx_fifo_empty; assign user_rx_ready = !rx_fifo_empty; assign user_rx_data_vld = rx_fifo_rd_req; endmodule
这个是这个IP核内部需要用到的FIFO,直接找.v文件,一起加进Quartus中编译就行。
// megafunction wizard: %FIFO% // GENERATION: STANDARD // VERSION: WM1.0 // MODULE: dcfifo // ============================================================ // File Name: uart_fifo.v // Megafunction Name(s): // dcfifo // // Simulation Library Files(s): // altera_mf // ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! // // 18.1.0 Build 625 09/12/2018 SJ Standard Edition // ************************************************************ //Copyright (C) 2018 Intel Corporation. All rights reserved. //Your use of Intel Corporation's design tools, logic functions //and other software and tools, and its AMPP partner logic //functions, and any output files from any of the foregoing //(including device programming or simulation files), and any //associated documentation or information are expressly subject //to the terms and conditions of the Intel Program License //Subscription Agreement, the Intel Quartus Prime License Agreement, //the Intel FPGA IP License Agreement, or other applicable license //agreement, including, without limitation, that your use is for //the sole purpose of programming logic devices manufactured by //Intel and sold by Intel or its authorized distributors. Please //refer to the applicable agreement for further details. // synopsys translate_off `timescale 1 ps / 1 ps // synopsys translate_on module uart_fifo ( aclr, data, rdclk, rdreq, wrclk, wrreq, q, rdempty, wrfull); input aclr; input [7:0] data; input rdclk; input rdreq; input wrclk; input wrreq; output [7:0] q; output rdempty; output wrfull; `ifndef ALTERA_RESERVED_QIS // synopsys translate_off `endif tri0 aclr; `ifndef ALTERA_RESERVED_QIS // synopsys translate_on `endif wire [7:0] sub_wire0; wire sub_wire1; wire sub_wire2; wire [7:0] q = sub_wire0[7:0]; wire rdempty = sub_wire1; wire wrfull = sub_wire2; dcfifo dcfifo_component ( .aclr (aclr), .data (data), .rdclk (rdclk), .rdreq (rdreq), .wrclk (wrclk), .wrreq (wrreq), .q (sub_wire0), .rdempty (sub_wire1), .wrfull (sub_wire2), .eccstatus (), .rdfull (), .rdusedw (), .wrempty (), .wrusedw ()); defparam dcfifo_component.intended_device_family = "Cyclone IV E", dcfifo_component.lpm_numwords = 512, dcfifo_component.lpm_showahead = "ON", dcfifo_component.lpm_type = "dcfifo", dcfifo_component.lpm_width = 8, dcfifo_component.lpm_widthu = 9, dcfifo_component.overflow_checking = "ON", dcfifo_component.rdsync_delaypipe = 4, dcfifo_component.read_aclr_synch = "OFF", dcfifo_component.underflow_checking = "ON", dcfifo_component.use_eab = "ON", dcfifo_component.write_aclr_synch = "OFF", dcfifo_component.wrsync_delaypipe = 4; endmodule // ============================================================ // CNX file retrieval info // ============================================================ // Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" // Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" // Retrieval info: PRIVATE: AlmostFull NUMERIC "0" // Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" // Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0" // Retrieval info: PRIVATE: Clock NUMERIC "4" // Retrieval info: PRIVATE: Depth NUMERIC "512" // Retrieval info: PRIVATE: Empty NUMERIC "1" // Retrieval info: PRIVATE: Full NUMERIC "1" // Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" // Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0" // Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" // Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" // Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0" // Retrieval info: PRIVATE: Optimize NUMERIC "0" // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" // Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0" // Retrieval info: PRIVATE: UsedW NUMERIC "1" // Retrieval info: PRIVATE: Width NUMERIC "8" // Retrieval info: PRIVATE: dc_aclr NUMERIC "1" // Retrieval info: PRIVATE: diff_widths NUMERIC "0" // Retrieval info: PRIVATE: msb_usedw NUMERIC "0" // Retrieval info: PRIVATE: output_width NUMERIC "8" // Retrieval info: PRIVATE: rsEmpty NUMERIC "1" // Retrieval info: PRIVATE: rsFull NUMERIC "0" // Retrieval info: PRIVATE: rsUsedW NUMERIC "0" // Retrieval info: PRIVATE: sc_aclr NUMERIC "0" // Retrieval info: PRIVATE: sc_sclr NUMERIC "0" // Retrieval info: PRIVATE: wsEmpty NUMERIC "0" // Retrieval info: PRIVATE: wsFull NUMERIC "1" // Retrieval info: PRIVATE: wsUsedW NUMERIC "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" // Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "512" // Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" // Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo" // Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8" // Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "9" // Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "4" // Retrieval info: CONSTANT: READ_ACLR_SYNCH STRING "OFF" // Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: USE_EAB STRING "ON" // Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF" // Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "4" // Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr" // Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" // Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" // Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk" // Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL "rdempty" // Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq" // Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk" // Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL "wrfull" // Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq" // Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0 // Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0 // Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0 // Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0 // Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0 // Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0 // Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0 // Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0 // Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0 // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo.v TRUE // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo.inc FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo.cmp FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo.bsf FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo_inst.v TRUE // Retrieval info: GEN_FILE: TYPE_NORMAL uart_fifo_bb.v TRUE // Retrieval info: LIB_FILE: altera_mf
顶层代码
module uart_top#( parameter CHECK_BIT = "None" , //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 parameter BPS = 115200 , //UART波特率 parameter CLK = 50000000 //工作时钟 )( input uart_clk , //50m input rst_n , //TX通道 input user_tx_clk , //比如80m input [7:0] user_tx_data , input user_tx_data_vld, output user_tx_ready , //RX通道 input user_rx_clk , output user_rx_ready , //表示串口已经收到数据了,可以读出 input user_rx_rd_req , output [7:0] user_rx_data , output user_rx_data_vld, input uart_rxd , output uart_txd ); wire [7:0] rx_data ; wire rx_data_vld ; wire [7:0] tx_data ; wire tx_data_vld ; wire tx_ready ; ctrl ctrl( /* input */.uart_clk (uart_clk ), //50m /* input */.rst_n (rst_n ), /* input */.user_tx_clk (user_tx_clk ), //比如80m /* input [7:0] */.user_tx_data (user_tx_data ), /* input */.user_tx_data_vld (user_tx_data_vld ), /* output */.user_tx_ready (user_tx_ready ), /* input */.user_rx_clk (user_rx_clk ), /* output */.user_rx_ready (user_rx_ready ), //表示串口已经收到数据了,可以读出 /* input */.user_rx_rd_req (user_rx_rd_req ), /* output [7:0] */.user_rx_data (user_rx_data ), /* output */.user_rx_data_vld (user_rx_data_vld ), /* input [7:0] */.rx_data (rx_data ), /* input */.rx_data_vld (rx_data_vld ), /* output [7:0] */.tx_data (tx_data ), /* output */.tx_data_vld (tx_data_vld ), /* input */.tx_ready (tx_ready ) ); uart_tx #( .CHECK_BIT (CHECK_BIT ), //"None" 偶校验,"Odd" 奇校验,"Even" 偶校验 .BPS (BPS ), //UART波特率 .CLK (CLK ) //工作时钟 )uart_tx_inst( /* input */.clk (uart_clk ), /* input */.rst_n (rst_n ), /* input [7:0] */.tx_data (tx_data ), /* input */.tx_data_vld (tx_data_vld ), /* output */.ready (tx_ready ), /* output reg */.tx (uart_txd ) ); uart_rx #( .CHECK_BIT (CHECK_BIT ), //"None" 无校验,"Odd" 奇校验,"Even" 偶校验 .BPS (BPS ), //UART波特率 .CLK (CLK ) //工作时钟 )uart_rx_inst( /* input */.clk (uart_clk ), /* input */.rst_n (rst_n ), /* output [7:0] */.rx_data (rx_data ), /* output */.rx_data_vld (rx_data_vld ), /* output */.ready ( ), /* input */.rx (uart_rxd ) ); endmodule
首先创建一个工程,命名随意,不过尽量言简意赅。
空工程创建完毕,接下来打开 Platform Designer。图中圈起来的那个图标。
双击New Component ,进入创建新IP的界面。
可以自己设定IP核的名字。还是那句话,言简意赅。然后点击上边的files。
点击Add Files ,将上边的代码文件加进去。
将文件加入以后,点击top文件的“Attributes”一列,将其设置为顶层。
点击编译一下这些代码文件。等待编译完成。
编译完成后,不用管下面的错误,点击close,进入下一步。
点击上边框的最后一个,进入对引脚的配置。
添加接口的同时更改名字和类型
完成后一共有四个接口:
1、时钟类型的接口,名字改成clk ,添加时选择类型为clk input,并且将“uart_clk”拖动到里边。
2、复位接口,名字改成rst_n,添加时选择类型为reset input,并且将“rst_n”拖到里边。
3、管道类型接口有两个,(1)名字改为uart,添加时选择类型为conduit,并且将“uart_txd”“uart_rxd”拖进里边(2)名字改为conduitend(接口名字随意,只要类型和包含的信号对就行),类型也是conduit,剩余的信号全都在里边。
还有一个重要的就是将管道接口的时钟和复位改一下,就在图中画星星的旁边,不要是“none”,连接时钟接口和复位接口。
然后将管道信号中的每个信号后边的字符改变一下。直接将name复制进去就行。记住,只用改管道接口里的信号。
最后就是像下图这样,接口就算配置完成了。
在改动接口的过程中就能注意到,下面的报错在减少。等配置完报错就没了。就说明已经配置完成了,仔细检查一遍没有错误了就点击Finish完成,返回quartus的主页面。
回到主页面后点击“Tool”–>“Options”–>“IP setting”–>“IP catalog”。
点击右边的三个点,然后选择存放此工程的文件夹,且点击add。
这一步是为了让quartus检测到我们创建的IP核,不然就只能在这个工程里用。如下图,随便打开一个工程就能看到自己封装的IP核。
完成了IP核的封装,接下来就是调用了。
随便打开一个工程,然后点击“Platfrom Designer”,或者点击右边的IP核。
就会弹出下图一样的画面。修改IP的名字以及ip存放的地址。
然后就是可以修改我们需要的校验方式,波特率和时钟频率。
然后按照图中的顺序点击按钮。如果第三步没有报错就说明之前配置IP核的步骤没问题。点击完后等待一会。
这里同样,只要没有报错就没有问题,关闭就行,最后点击Finish。
然后就可以在代码里找到例化的模版。这里例化进顶层进行连线就行,之后我会发一个文章仔细讲解,现在先弄好IP核就行。
IP核的封装完成了,接下来就是调用,等几天我发出来具体的方法。
代码放进了baidu网盘里,去找就行。
链接:https://pan.baidu.com/s/107QVaN3du91LhQbFuL3IRQ?pwd=yang
提取码:yang
如果有错误的话就加qq问我,号码在上一篇写了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。