tag 标签: CrosslinkNX

相关博文
  • 热度 4
    2021-2-18 10:18
    2559 次阅读|
    1 个评论
    lattice CrosslinkNx LIFCL-40应用连载4-RISC-V处理器访问I2CFIFO
    作者:Hello,Panda 熊猫君这次分享的是如何通过 CrosslinkNX 的 RISC-V 软核来访问 I2CFIFO 软核。 IIC 是最常用的外设总线,通常一块板子上要挂好些个 IIC 器件,如果完全使用 RTL 状态机来实现总线控制的话,无疑非常的繁琐且非常的不友好,调试和使用起来也很不方便。熊猫君的这次分享就是为了解决这个问题,将 Lattice 的 I2CFIFO 模块挂到 RISC-V 软核的 APB 总线上,通过软件来实现 IIC 总线, I2CFIFO 模块就相当于是 RISC-V 处理器的一个外设,按地址访问就行了。 在阅读这个例子之前,读者需要了解以下基本知识: (1) lattice 基于 RISC-V 处理器的 SOC 基本开发流程; (2) Arm 的 APB 总线协议《 AMBA 3 APB Protocol Specification 》; (3) Lattice 的 lmmi 总线协议《 Lattice Memory Mapped Interface and Lattice Interrupt Interface 》, lattice 内部文档编码 UG-02039 ; (4) I2CFIFO 模块使用手册《 I2CFIFO Module - Lattice Radiant Software 》, lattice 内部文档编码 IPUG-02064 ; 一、电路板硬件 熊猫君用的公司自制的评估板,板上集成了若干个 IIC 从设备,硬件原理图见下图 1 。 图 1 评估板硬件原理图 由图中可以看出, IIC 设备有扩展 IO 芯片、 MIPI 接口的图像传感器、时钟芯片、触摸屏等,通过一个 IIC Switch 芯片来进行通道选择,这样的硬件结构如果直接用 RTL 状态机实现,那无疑是非常复杂,因此通过挂到 APB 总线上作为一个 RISC-V 外设使用就相对简单多了。 二、软件设计 本案软件至少需要包括 RISC-V 处理器、程序运行 RAM 、总线仲裁器、 I2CFIFO 模块等,系统结构见图 2 所示。 图 2 软件系统结构框图 (1) SoC 方框内所有模块是在 Propel 中搭建的,其中 APB IF 是一个自定义的接口 IP ,目的是将 APB 总线引出并给其在 RISC-V 处理器中分配访问地址,自定义的 IP 的封装方法在本文中不再赘述; (2) APB REG: 这个模块是熊猫君自己写的,目的是解析 APB 总线数据并将其分发到工程中的各个模块,图 2 中只画了一个 I2CFIFO ,实际上挂了很多 IP 的; (3) LMMI Master :这个模块是熊猫君自己写的,目的是为了实现 LMMI 总线访问逻辑,用于配置 I2CFIFO 。 其实,在本案中最关键的一步是如何将 I2CFIFO 模块挂载到 APB 总线上去,让 RISC-V 处理器可以访问它。 2.1 第一步:搭建 Propel 工程 软件设计的第一步是在 Propel 下搭建一个 RISC-V 软核工程,搭建的流程可以参考本系列分享 3 ,搭建好的工程见下图 3 所示。 图 3 搭建好的 Propel 工程图 如图 3 所示,标记红色方框的就是自定义封装的一个 APB 接口 IP ,里面没有什么逻辑,就是将 APB 总线的若干信号引出 SOC 工程供顶层的 Radiant 模块调用,并且定义了地址空间范围,如下图 4 所示。 图 4 给 APB 总线接口分配地址空间 如果做到这图 4 这一步,那么恭喜你, RISC-V 处理器核已经可以正常访问该段地址对应的外设寄存器了,这个应用也就成功了一多半。 2.2 第二步:例化 I2CFIFO 模组 Lattice I2CFIFO 模组是无需额外的 License 授权的,在 Radiant 开发环境下可以免费使用,我们把这个模组例化成为 FIFO 模式,总线速率 400KHz ,例化配置见下图 5 所示,其他图中不所见的配置按默认即可。 图 5 I2CFIFO 例化配置界面 关于这个 IP 模块的使用请参见官方 User Guide 文档,配置成为 FIFO 模式的操作比较简单,软件编程时只需按照下图 6 所示的步骤配置寄存器即可完成 I2C 的读写访问。 图 6 FIFO 模式下 I2C 读写访问流程表 这里需要特别提醒注意的是: fifo 模式下的寄存器是 10bit 位宽,需要分两次访问,如写 fifo 操作, bit 写入到偏移地址为 0x12 的寄存器中, bit 控制命令写入到偏移地址为 0x13 的寄存器中。 2.3 第三步:搭建 APB 到 LMMI 总线的转换逻辑 这一步在 APB_REG 模块和 LMMI_Master 模块中实现,当然也可以直接使用一个总线桥来做,但是这样做的话,这个 APB 总线接口就是专有的了,不利于系统的扩展使用。 这两个模块的代码如下: //------------------------------------------------------------ //File Name: apb_reg_v1 //Project : mipi dphy //Module :apb_reg //Content : //Description : apb reg mapping //Spec. : //Author : Hello,Panda //------------------------------------------------------------ //History : //20210205: V1.0 -Initial Creation //------------------------------------------------------------ `timescale 1ns / 1ps module apb_reg_v1 #( parameter P_MAJOR_VERSION = 4'd1 ,parameter P_MINOR_VERSION = 4'd0 ,parameter P_BUILD_YEAR = 12'd2021 ,parameter P_BUILD_MON = 4'd2 ,parameter P_BUILD_DAY = 8'd6 )( input wire i_clk ,input wire i_rst /**************apb bus****************/ ,input wire i_apb_penable ,input wire i_apb_psel ,input wire i_apb_pwrite ,input wire i_apb_paddr ,input wire i_apb_pwdata ,output wire o_apb_pready ,output wire o_apb_pslverr ,output wire o_apb_prdata ,output wire o_iicfifo_lmmi_start ,output wire o_iicfifo_lmmi_mode ,output wire o_iicfifo_lmmi_offset ,output wire o_iicfifo_lmmi_wdata ,input wire i_iicfifo_lmmi_busy ,input wire i_iicfifo_lmmi_done ,input wire i_iicfifo_lmmi_rdata ,output wire o_iicfifo_reset ); reg r_apb_addr ; reg r_apb_pwdata ; reg r_apb_reg_wren ; reg r_apb_reg_rden ; reg r_p1_apb_reg_wren; reg r_p1_apb_reg_rden; reg r_app_reg_rdout ; reg r_apb_prdata ; reg r_iicfifo_reset ; reg r_apb_slv_reg1 ; reg r_apb_slv_reg2 ; reg r_apb_pready ; reg r_iicfifo_lmmi_start; reg r_iicfifo_lmmi_rready; reg r_iicfifo_lmmi_rflag ; reg r_iicfifo_lmmi_rdata ; reg r_iicfifo_lmmi_clean ; wire w_major_ver ; wire w_minor_ver ; wire w_build_year ; wire w_build_mon ; wire w_build_day ; wire w_apb_reg_wren ; wire w_apb_reg_rden ; wire w_apb_slv_reg0 ; wire w_apb_slv_reg1 ; assign o_apb_pready = r_apb_pready ; assign o_apb_pslverr = 1'b0 ; assign o_apb_prdata = r_apb_prdata ; assign w_major_ver = P_MAJOR_VERSION; assign w_minor_ver = P_MINOR_VERSION; assign w_build_year = P_BUILD_YEAR ; assign w_build_mon = P_BUILD_MON ; assign w_build_day = P_BUILD_DAY ; assign w_apb_slv_reg0 = {w_build_year ,w_build_mon , w_build_day ,w_major_ver ,w_minor_ver }; assign w_apb_reg_wren = ((~r_p1_apb_reg_wren) & r_apb_reg_wren); assign w_apb_reg_rden = ((~r_p1_apb_reg_rden) & r_apb_reg_rden); assign o_iicfifo_lmmi_start = (r_apb_slv_reg1 & (~r_iicfifo_lmmi_start)); assign o_iicfifo_lmmi_mode = r_apb_slv_reg1 ; assign o_iicfifo_lmmi_offset = r_apb_slv_reg1 ; assign o_iicfifo_lmmi_wdata = r_apb_slv_reg2 ; assign o_iicfifo_reset = (r_iicfifo_reset|r_apb_slv_reg1 ); assign w_apb_slv_reg1 = {i_iicfifo_lmmi_busy,r_iicfifo_lmmi_rready,r_apb_slv_reg1 }; always @ (posedge i_clk) begin if(i_rst) begin r_apb_addr <= 10'd0; r_apb_reg_wren <= 1'b0 ; r_apb_reg_rden <= 1'b0 ; r_p1_apb_reg_wren <= 1'b0; r_p1_apb_reg_rden <= 1'b0; r_apb_pwdata <= 32'd0; r_app_reg_rdout <= 1'b0 ; end else begin r_apb_reg_wren <= (i_apb_psel & i_apb_penable & i_apb_pwrite) ? 1'b1 : 1'b0 ; r_apb_addr <= (i_apb_psel & (~i_apb_penable)) ? i_apb_paddr : r_apb_addr ; //latch addr r_apb_reg_rden <= (i_apb_psel & (~i_apb_penable) & (~i_apb_pwrite)) ? 1'b1 : 1'b0 ; //begin read with wait r_p1_apb_reg_wren <= r_apb_reg_wren ; r_p1_apb_reg_rden <= r_apb_reg_rden ; r_apb_pwdata <= (i_apb_psel & i_apb_penable & i_apb_pwrite & r_apb_pready) ? i_apb_pwdata : r_apb_pwdata; r_app_reg_rdout <= w_apb_reg_rden ? 1'b1 : 1'b0; end end always @ (posedge i_clk) begin if(i_rst) begin r_apb_pready <= 1'b0; end else begin if(i_apb_psel & (~i_apb_pwrite)) begin if(~i_apb_penable) begin r_apb_pready <= 1'b0; end else if(r_app_reg_rdout) begin r_apb_pready <= 1'b1; end end else begin r_apb_pready <= 1'b1; end end end always @ (posedge i_clk) begin if(i_rst) begin r_apb_slv_reg1 <= 32'h00000000; r_apb_slv_reg2 <= 32'h00000000; end else begin if(w_apb_reg_wren) begin case (r_apb_addr ) 8'd1 : begin r_apb_slv_reg1 <= r_apb_pwdata; end 8'd2 : begin r_apb_slv_reg2 <= r_apb_pwdata; end default : begin r_apb_slv_reg1 <= r_apb_slv_reg1; r_apb_slv_reg2 <= r_apb_slv_reg2; end endcase end else begin r_apb_slv_reg1 <= 2'b00; end end end always @ (posedge i_clk) begin if(i_rst) begin r_apb_prdata <= 32'd0; r_iicfifo_lmmi_clean <= 1'b0 ; end else begin if(r_app_reg_rdout) begin case (r_apb_addr ) 8'd0 : begin r_apb_prdata <= w_apb_slv_reg0; end 8'd1 : begin r_apb_prdata <= w_apb_slv_reg1; end 8'd2 : begin r_apb_prdata <= r_apb_slv_reg2; end 8'd3 : begin r_apb_prdata <= r_iicfifo_lmmi_rdata ; r_iicfifo_lmmi_clean <= 1'b1 ; end default : begin r_apb_prdata <= 32'd0; end endcase end else begin r_iicfifo_lmmi_clean <= 1'b0; end end end always @ (posedge i_clk) begin if(i_rst) begin r_iicfifo_lmmi_start <= 1'b0; r_iicfifo_lmmi_rready <= 1'b0; r_iicfifo_lmmi_rflag <= 1'b0; r_iicfifo_lmmi_rdata <= 32'd0; r_iicfifo_reset <= 1'b0; end else begin r_iicfifo_lmmi_start <= r_apb_slv_reg1 ; r_iicfifo_reset <= r_apb_slv_reg1 ; if(r_apb_slv_reg1 & (~r_apb_slv_reg1 )) begin r_iicfifo_lmmi_rflag <= 1'b1; end else if(i_iicfifo_lmmi_done) begin r_iicfifo_lmmi_rflag <= 1'b0; end if(r_iicfifo_lmmi_rflag & i_iicfifo_lmmi_done) begin r_iicfifo_lmmi_rdata <= i_iicfifo_lmmi_rdata; end if(r_iicfifo_lmmi_rflag & i_iicfifo_lmmi_done) begin r_iicfifo_lmmi_rready <= 1'b1; end else if(r_iicfifo_lmmi_clean) begin r_iicfifo_lmmi_rready <= 1'b0; end end end endmodule //------------------------------------------------------------ //file name: lmmi_master_v1 //project : mipi dphy //module : //content : //description : generate lmmi acess logic //spec. : //author : hello,panda //------------------------------------------------------------ //history : //20210205: v1.0 -initial creation //------------------------------------------------------------ `timescale 1ns / 1ps module lmmi_master_v1( input wire i_clk ,input wire i_rst ,input wire i_addr_offset ,input wire i_reg_wdata ,output wire o_reg_rdata ,input wire i_access_start ,input wire i_access_mode //1-write mode; 0-read mode ,output wire o_access_done ,output wire o_access_busy ,output wire o_lmmi_request ,output wire o_lmmi_wr_rdn ,output wire o_lmmi_offset ,output wire o_lmmi_wdata ,input wire i_lmmi_rdata ,input wire i_lmmi_rdata_valid ,input wire i_lmmi_ready ); reg r_access_start; reg r_addr_offset ; reg r_reg_wdata ; reg r_reg_rdata ; reg r_access_mode ; reg r_access_busy ; reg r_access_done ; reg r_lmmi_request; reg r_lmmi_state ; reg r_lmmi_wr_rdn ; localparam st_idel = 4'b0000; localparam st_wr = 4'b0001; localparam st_rd = 4'b0010; localparam st_wait = 4'b0100; localparam st_done = 4'b1000; assign o_reg_rdata = r_reg_rdata ; assign o_access_done = r_access_done ; assign o_access_busy = (r_access_start|r_access_busy); assign o_lmmi_request = r_lmmi_request ; assign o_lmmi_wr_rdn = r_lmmi_wr_rdn ; assign o_lmmi_offset = r_addr_offset ; assign o_lmmi_wdata = r_reg_wdata ; always @ (posedge i_clk) begin if(i_rst) begin r_access_start <= 1'b0 ; r_addr_offset <= 8'd0 ; r_reg_wdata <= 32'd0; r_access_mode <= 1'b0 ; end else begin if(i_access_start & (~r_access_busy)) begin r_addr_offset <= i_addr_offset ; r_reg_wdata <= i_reg_wdata ; r_access_mode <= i_access_mode ; end r_access_start <= i_access_start; end end always @ (posedge i_clk) begin if(i_rst) begin r_lmmi_state <= st_idel ; r_lmmi_request <= 1'b0 ; r_reg_rdata <= 32'd0 ; r_access_done <= 1'b0 ; r_lmmi_wr_rdn <= 1'b0 ; end else begin case (r_lmmi_state) st_idel : begin if(r_access_start) begin r_lmmi_state <= st_wr ; end r_lmmi_request <= 1'b0; r_access_done <= 1'b0; r_lmmi_wr_rdn <= 1'b0; end ST_WR : begin if(i_lmmi_ready) begin r_lmmi_state <= r_access_mode ? ST_WAIT : ST_RD; r_lmmi_request <= 1'b1 ; r_lmmi_wr_rdn <= r_access_mode; end end ST_RD : begin r_lmmi_request <= 1'b0; r_lmmi_wr_rdn <= 1'b0; if(i_lmmi_rdata_valid) begin r_reg_rdata <= i_lmmi_rdata; r_lmmi_state <= ST_WAIT ; end end ST_WAIT : begin r_lmmi_request <= 1'b0; r_lmmi_wr_rdn <= 1'b0; if(i_lmmi_ready) begin r_lmmi_state <= ST_DONE; r_access_done<= 1'b1 ; end end ST_DONE : begin r_lmmi_request <= 1'b0; r_lmmi_wr_rdn <= 1'b0; r_lmmi_state <= ST_IDEL; r_access_done <= 1'b0; end default : begin r_lmmi_request <= 1'b0; r_lmmi_wr_rdn <= 1'b0; r_lmmi_state <= ST_IDEL; r_access_done <= 1'b0; end endcase end end always @ (posedge i_clk) begin if(i_rst) begin r_access_busy <= 1'b0; end else begin if(r_access_start) begin r_access_busy <= 1'b1; end else if(r_lmmi_state == ST_DONE) begin r_access_busy <= 1'b0; end end end endmodule 好了,这两个模块的代码已经贴出来了,这里就不再多作解释。 2.4 第四步:在 Propel SDK 下编写 C 代码 这一步就是在软件访问 I2CFIFO 模块寄存,根据 2.3 第三步描述的逻辑,写好读写寄存器的底层函数即可,比如写 I2CFIFO 模块寄存器的语句如下: void iiclmmiwrite ( uint8_t offset, uint32_t wdata) { uint32_t reg_val; //check lmii bus idle IIC_LMII_CTRL & IIC_LMII_CTRL_BUSY_MASK); while (reg_val){ IIC_LMII_CTRL & IIC_LMII_CTRL_BUSY_MASK); } //write wdata to register IIC_LMII_WDATA = wdata; //write ctrl to start reg_val = offset; reg_val |= IIC_LMII_CTRL_PWRITE_MASK; reg_val |= IIC_LMII_CTRL_START_MASK ; IIC_LMII_CTRL = reg_val; } 至于后面的逻辑代码怎么写,调用底层的寄存器读写函数就可以了。 好了,今天的分享到此结束,欢迎大家加入 QQ 群或微信公众号交流讨论,同时也祝朋友们在新的一年里更上一层楼,牛得牛气冲天!
  • 热度 5
    2021-1-15 11:47
    3868 次阅读|
    1 个评论
    Lattice CrossLinkNx LIFCL-40应用连载2-使用Reveal Inserter逻辑分析工具
    作者:Hello,Panda 3. 使用在线调试器( ILA ) Lattice 系列工具使用在线调试器的方法比 Xilinx 要复杂,和 Altera 的类似,但还是要稍微复杂一些。本例在上一个产生 50Hz 方波的工程基础上进行说明。 3.1 添加 Logic Analyzer 核 首先,需要将工程布局布线通过生成网表。 Step1 :点击 Reveal Inserter 按钮或点击快捷按钮,选择 Add Logic Analyzer 。 图 1 选择逻辑分析仪 Step2 :添加采样时钟、采样深度、待观测信号等。如下图所示,将左边的时钟信号拖到 sample clock 位置,将需要观测的信号拖到 Trace 下的空白处。配置采样深度为 1024 和实现的资源为 EBR 。 图 2 配置 Trace Signal Step3 :配置触发信号、触发条件等 如下图所示,将触发信号添加到 Tigger Unit 单元下并设置触发条件,然后进行“规则检查”,规则检查无误后点击“添加到工程”按钮并保持工程。 图 3 配置触发信号、触发条件等界面 Step3 :生成新的 bit 文件。 Step4 :将新生成的 bit 文件下载到 FPGA 。 1.2 在线调试 将包含 Logic Analyzer 的 bit 文件下载到 FPGA 以后,选择 Reveal Analyzer/Controller 或者点击快捷按钮,按下图红框处所列找到 USB Port 和 Debug Device ,点击 OK 确认。 图 4 启用 Analyzer/Controller 如下图所示,点击运行按钮,点击“ run ”运行按钮,等待触发完成即可看到如图所示的波形,可以根据自己的需要鼠标右击波形根据选项调整波形的显示格式属性。 图 5 触发显示波形 欢迎大家扫描下面的二维码加入QQ讨论群或微信公众号共同讨论,共同进步。
  • 热度 3
    2021-1-15 11:26
    3728 次阅读|
    1 个评论
    Lattice CrossLinkNx LIFCL-40应用连载1:新建一个工程
    作者:Hello,Panda 1 1.目的 本入门分享一共三篇,目的是为了帮助新手利用 Lattice Radiant Software 创建第一个新工程、使用在线调试器和使用 RSIC-V 软核。基本的软硬件配置如下: (1) 软件开发平台: Lattice Radiant Software 2.0.1.281.2 和 Lattice Propel1.1 。 (2) 评估板: CrossLinkNx Base (编号 YSPL0010A ,公司自制) (3) 器件 : LIFC-40-7MG121C ( ES 器件) (4) 调试器: Lattice HW-USBN-2B 2 创建第一个工程 本章介绍如何创建第一个 CrosslinkNX 工程。 2.1 创建新工程 目标:创建一个新工程,使用内部的 osc 产生 50MHz 的时钟作为系统的工作时钟,利用计数器产生 50Hz 的方波,生成 bit 文件并将 bit 文件烧写到 SPI Flash 中。 Step1 :打开 Radiant 软件,选择 Project 。 图 1 创建新工程界面 Step2 :选择工程路径和工程名,这里命名为 wave_50hz 。 图 2 选择新工程路径和命名 Step3: 一路下一步,根据自己用的芯片选择器件,我的板子上是 LIFCL-40-7M121C ,如下图 图 3 选择器件 Step4 :一路下一步,直到工程创建完毕。 2.2 添加和编译文件 一个完整的工程,至少具备顶层文件、约束文件和若干 IP ,本例生成一个简单的 50Hz 方波,因此需要一个 OSC IP 来产生时钟、一个约束文件来指定 IO 、一个顶层 vhd 文件。 2.2.1 生成 OSC IP Lattice CrossLink NX FPGA 内部有一个 450MHz 时钟单元,通过 IP 来例化调用。 Step1 :选择 IP Catalog ,双击 OSC IP 核,并将之命名为 sys_osc 。 图 4 生成 OSC IP Step2 :选择 Next ,配置 HFCLK Divider 参数为 9 ,点击 Generate 。 图 5 配置 OSC IP 2.2.2 编写顶层文件 Step1 :在 File List 下,选择 New File 建立一个新文件,选择类型为 Verilog Files ,命名为 wave­_50hz_top, 点击 new 完成创建。 图 6 创建 HDL 文件 图 7 选择新创建文件属性 Step2 :编写文件 为形成良好的编码习惯,一个 verilog 文件里面需要包含注释、仿真精度和实体模块等信息,本文件例化之前生成的 sys_osc ,并编写产生方波的文件,示例如下: //------------------------------------------------------------ //File Name: wave_50hz_top // //Project : top moudle of generate 50Hz sqrt wave // //Module : top // //Content : none // //Description : 50MHz clock generate by intel OSC // //Spec. : none // //Author : Hello,Panda //------------------------------------------------------------ //History : //20200804: V1.0 -Initial Creation //------------------------------------------------------------ `timescale 1ns / 1ps module wave_50hz_top( output wire o_wave_50hz //output port ); reg r_chip_cnt = 16'd0 ; reg r_chip_rstn = 1'b0 ; reg r_low_cnt ; reg r_high_cnt ; reg r_wave ; wire w_chip_clk_50m; /***************************************************************/ //part1:osc genrate clock /***************************************************************/ sys_osc u_sys_clk_inst( .hf_out_en_i (1'b1 ) ,.hf_clk_out_o (w_chip_clk_50m ) ); always @ (posedge w_chip_clk_50m) begin r_chip_cnt <= (&r_chip_cnt) ? r_chip_cnt : (r_chip_cnt + 1'b1); r_chip_rstn = 16'd32768) ? 1'b1 : 1'b0; end /***************************************************************/ //part2:generate wave /***************************************************************/ always @ (posedge w_chip_clk_50m) begin if(~r_chip_rstn) begin r_low_cnt <= 10'd0; r_high_cnt <= 10'd0; r_wave <= 1'b0 ; end else begin = 10'd999) begin r_low_cnt <= 10'd0; r_high_cnt = 10'd999) ? 10'd0 : (r_high_cnt + 1'b1); end else begin r_low_cnt <= r_low_cnt + 1'b1; r_high_cnt <= r_high_cnt ; end r_wave = 10'd499) ? 1'b1 : 1'b0; end end assign o_wave_50hz = r_wave; endmodule 备注: 50Hz 频率的周期为 20ms , 50MHz 的周期为 20ns ,即需要计数器计满 1000*1000 个节拍为 20ms 。 Step3 :添加 wave_50hz_top 为顶层文件 右键 inpl_1 选择 Set Top level Unit, 将 wave_50hz_top 指定为顶层文件。 图 8 设置顶层文件 2.2.3 编写约束文件 本例中约束文件包括 IO 、使能 JTAG 和使能 MASTER_SPI_PORT 原语。约束文件既可以先行写好添加,也可以通过综合以后在 Device Constraint Editor 、 Timing Constraint Editor 等图形界面添加,本例选择第一种,约束文件的语法请参考 Lattice 的官方文件,也可在软件 Source Templates 里看到一部分。 Step1 :新建一个 Post-Systhesis 约束文件,命名为 wave_50hz.pdc, 点击 new 。 图 9 创建约束文件 Step2 :编写约束 (1) 指定 IO :指定 IO 引脚号为 G1 ,电平标准 1.8V LVCMOS 和其他属性; (2) 使能 JTAG :使能 JTAG ; (3) 使能 MASTER_SPI_PORT ,并指定其工作时钟频率为 3.5MHz 。 ldc_set_location -site {G1} ldc_set_port -iobuf {IO_TYPE=LVCMOS18H SLEWRATE=SLOW} ldc_set_sysconfig {MASTER_SPI_PORT=SERIAL BOOTMODE=SINGLE CONFIGIO_VOLTAGE_BANK0=1.8 CONFIGIO_VOLTAGE_BANK1=1.8 MCCLK_FREQ=3.5 CONFIG_IOSLEW=FAST} ldc_set_sysconfig {JTAG_PORT=ENABLE} 2.3 布局布线和导出文件 点击 Export Files 按钮,软件可以一键完成综合、布局布线、生成 bit 文件等工作。 2.4 Bit 文件下载 有两种类型,一种是下载到 FPGA 的配置 SRAM ,掉电即丢失,适合调试时使用。一种是烧写到 SPI Flash 进行程序固化,上电加载到 FPGA 运行。 首先,点击 Programer 按钮,进入烧写工具界面。 2.4.1 下载到 FPGA SRAM 如下图所示,双击 Target Memory 或 Operation 下面的复习项弹出配置菜单,根据实际硬件情况选择 JTAG 的类型、选择 Target Memory 为 SRAM 是, File Name 选项指定到 bit 文件所在位置, Port Interface 选择为 JTAG , Acess Mode 选择为 Direct Programing , Operation 为 Fast Configuration 。 图 10 下载到 FPGA SRAM 配置界面 点击绿色的下载按钮,等待下载完成,完成后下方的 output 栏会提示 successful 。 2.4.2 固化到 SPI Flash 将 bit 文件固化到 spi flash ,首先应将其下载到 fpga 的 sram 使能 MASTER_SPI_PORT 使 JTAG2SPI 命令可以正常工作。烧写到 SPI Flash 的文件既可以是 bit 文件,也可以是 mcs 文件,本例选择直接烧写 bit 文件。 如下图所示,选项如下: (1) Target Memory : Extern SPI Flash Memory ; (2) Port Interface : JTAG2SPI ; (3) Operation : Erase , Program , Verify ; (4) Programming File 路径指向 bit 文件所在位置; (5) 选择 SPI Flash 的型号; (6) 根据 bit 文件的大小设置烧写到 Flash 的起始地址。 设置完成后点击绿色的下载按钮,等待下载到 SPI Flash 完成, output 栏会提示进度和完成状态。 图 11 固化到 SPI Flash 配置界面 2.5 功能确认 用示波器测量输出引脚,可以看到频率为 50Hz ,幅度为 1.8V 的方波。 图 12 功能确认 欢迎大家扫描下面的二维码加入QQ讨论群或微信公众号共同讨论,共同进步。