vivado确实很好用,之前一直使用zynq,但是部分场景成本过高,索性直接准备用开源软核or1200 sopc,最早了解or1200还是在大学的时候,大约2010年左右,准备电赛的时候在实验室曾经简单接触过,印象里应该是S3的fpga,后来由于专业原因,主要研究雷达电磁算法与进化算法,后来被航天科工淘汰之后,因为工作需要,感觉可以重温旧事,这个还是可以搞一下的,但是有些旧事就比较难了,比如科工的江f,我至今也不知道到底是生她的人牛逼还是睡她的人牛逼,本次利用vivado进行soc设计,相关资源最后上传百度云,这里主要是首先添加两个外设作为例子,展示整个流程
一、代码准备:
首先建立目录OR1200_soc_wyz_ram_gpio
1.openRISC 官网https://openrisc.io/下载OR1200的代码,如下图所示:
解压之后,将or1200-master\rtl\verilog下的代码拷贝到指定目录,由此得到本次实验的CPU软核部分。
- 下载wishbone总线IP核,将代码拷贝到指定目录
- Ram采用数组编写代码实现(此处直接采用步步惊心里面ram文件),编码编写完成之后,在OR1200_soc_wyz_ram_gpio下面建立目录ram
- 下载GPIO的IP核,解压之后将代码存放到OR1200_soc_wyz_ram_gpio/gpio
二、建立vovado工程
1.打开vivado2019.1
2.建立新的工程,OR1200_soc_wyz_1
3.选择RTL工程之后,一直选next 到finish,其他的设置都是默认,后期如果综合需要再进行修改
- 添加IP核代码,点击add souces
然后选择添加ADD Drections
将CPU、wishbone总线、ram以及gpio的路径添加,然后结束。界面如下图所示,表示各个模块的代码已经添加到了工程当中。
目前工程默认的顶层文件是,没有关系。
三、建立顶层文件,例化连接各个IP核,形成SOC系统
首先点击add source 按钮,选择创建文件,的名字命名为Or1200_soc_wyz,然后在这个文件当中定义输入与输出,代码如下:
module Or1200_soc_wyz(
input clk_i,
input rst_i,
// GPIO输入
input [15:0] SW,
// GPIO输出
output [31:0] LEDR
);
//1.定义各个IP核之间的连线
// **************************************************
// Wires from OR1200 Inst Master to Conmax m0 定义总线和OR1200指令接口之间的连接线
// **************************************************
wire wire_iwb_ack_i;
wire wire_iwb_cyc_o;
wire wire_iwb_stb_o;
wire [31:0] wire_iwb_data_i;
wire [31:0] wire_iwb_data_o;
wire [31:0] wire_iwb_addr_o;
wire [3:0] wire_iwb_sel_o;
wire wire_iwb_we_o;
wire wire_iwb_err_i;
wire wire_iwb_rty_i;
// **************************************************
// Wires from OR1200 Data Master to Conmax m1
// **************************************************
wire wire_dwb_ack_i;
wire wire_dwb_cyc_o;
wire wire_dwb_stb_o;
wire [31:0] wire_dwb_data_i;
wire [31:0] wire_dwb_data_o;
wire [31:0] wire_dwb_addr_o;
wire [3:0] wire_dwb_sel_o;
wire wire_dwb_we_o;
wire wire_dwb_err_i;
wire wire_dwb_rty_i;
// **************************************************
// Wires from Conmax s0 to onchip_ram0
// **************************************************
wire wire_ram0_ack_o;
wire wire_ram0_cyc_i;
wire wire_ram0_stb_i;
wire [31:0] wire_ram0_data_i;
wire [31:0] wire_ram0_data_o;
wire [31:0] wire_ram0_addr_i;
wire [3:0] wire_ram0_sel_i;
wire wire_ram0_we_i;
// **************************************************
// Wires from Conmax s1 to GPIO 信号数量来源于wb总线的规定 王一哲
// **************************************************
wire wire_gpio1_ack_o;
wire wire_gpio1_cyc_i;
wire wire_gpio1_stb_i;
wire [31:0] wire_gpio1_data_i;
wire [31:0] wire_gpio1_data_o;
wire [31:0] wire_gpio1_addr_i;
wire [3:0] wire_gpio1_sel_i;
wire wire_gpio1_we_i;
wire wire_gpio1_err_o;
wire wire_gpio_interrupt;
例化连接各个模块
//例化or1200 CPU,各个连线的定义参考官方文档
or1200_top u_or1200(
// System
.clk_i(clk_i),
.rst_i(rst_i),
.pic_ints_i({18'b0,wire_uart_interrupt,wire_gpio_interrupt}),
.clmode_i(2'b00),
// Instruction WISHBONE INTERFACE
.iwb_clk_i(clk_i),
.iwb_rst_i(rst_i),
.iwb_ack_i(wire_iwb_ack_i),
.iwb_err_i(wire_iwb_err_i),
.iwb_rty_i(wire_iwb_rty_i),
.iwb_dat_i(wire_iwb_data_i),
.iwb_cyc_o(wire_iwb_cyc_o),
.iwb_adr_o(wire_iwb_addr_o),
.iwb_stb_o(wire_iwb_stb_o),
.iwb_we_o(wire_iwb_we_o),
.iwb_sel_o(wire_iwb_sel_o),
.iwb_dat_o(wire_iwb_data_o),
`ifdef OR1200_WB_CAB
.iwb_cab_o(),
`endif
//`ifdef OR1200_WB_B3
// iwb_cti_o(),
// iwb_bte_o(),
//`endif
// Data WISHBONE INTERFACE
.dwb_clk_i(clk_i),
.dwb_rst_i(rst_i),
.dwb_ack_i(wire_dwb_ack_i),
.dwb_err_i(wire_dwb_err_i),
.dwb_rty_i(wire_dwb_rty_i),
.dwb_dat_i(wire_dwb_data_i),
.dwb_cyc_o(wire_dwb_cyc_o),
.dwb_adr_o(wire_dwb_addr_o),
.dwb_stb_o(wire_dwb_stb_o),
.dwb_we_o(wire_dwb_we_o),
.dwb_sel_o(wire_dwb_sel_o),
.dwb_dat_o(wire_dwb_data_o),
`ifdef OR1200_WB_CAB
.dwb_cab_o(),
`endif
//`ifdef OR1200_WB_B3
// dwb_cti_o(),
// dwb_bte_o(),
//`endif
// External Debug Interface
.dbg_stall_i(1'b0),
.dbg_ewt_i(1'b0),
.dbg_lss_o(),
.dbg_is_o(),
.dbg_wp_o(),
.dbg_bp_o(),
.dbg_stb_i(1'b0),
.dbg_we_i(1'b0),
.dbg_adr_i(0),
.dbg_dat_i(0),
.dbg_dat_o(),
.dbg_ack_o(),
//`ifdef OR1200_BIST
// // RAM BIST
// mbist_si_i(),
// mbist_so_o(),
// mbist_ctrl_i(),
//`endif
// Power Management
.pm_cpustall_i(0),
.pm_clksd_o(),
.pm_dc_gate_o(),
.pm_ic_gate_o(),
.pm_dmmu_gate_o(),
.pm_immu_gate_o(),
.pm_tt_gate_o(),
.pm_cpu_gate_o(),
.pm_wakeup_o(),
.pm_lvolt_o()
);
//例化总线控制器,连接各个接口
wb_conmax_top u_wb(
.clk_i(clk_i),
.rst_i(rst_i),
// Master 0 Interface
.m0_data_i(wire_iwb_data_o),
.m0_data_o(wire_iwb_data_i),
.m0_addr_i(wire_iwb_addr_o),
.m0_sel_i(wire_iwb_sel_o),
.m0_we_i(wire_iwb_we_o),
.m0_cyc_i(wire_iwb_cyc_o),
.m0_stb_i(wire_iwb_stb_o),
.m0_ack_o(wire_iwb_ack_i),
.m0_err_o(wire_iwb_err_i),
.m0_rty_o(wire_iwb_rty_i),
// .m0_cab_i(),
// Master 1 Interface
.m1_data_i(wire_dwb_data_o),
.m1_data_o(wire_dwb_data_i),
.m1_addr_i(wire_dwb_addr_o),
.m1_sel_i(wire_dwb_sel_o),
.m1_we_i(wire_dwb_we_o),
.m1_cyc_i(wire_dwb_cyc_o),
.m1_stb_i(wire_dwb_stb_o),
.m1_ack_o(wire_dwb_ack_i),
.m1_err_o(wire_dwb_err_i),
.m1_rty_o(wire_dwb_rty_i),
// .m0_cab_i(),
// Slave 0 Interface
.s0_data_i(wire_ram0_data_o),
.s0_data_o(wire_ram0_data_i),
.s0_addr_o(wire_ram0_addr_i),
.s0_sel_o(wire_ram0_sel_i),
.s0_we_o(wire_ram0_we_i),
.s0_cyc_o(wire_ram0_cyc_i),
.s0_stb_o(wire_ram0_stb_i),
.s0_ack_i(wire_ram0_ack_o),
.s0_err_i(0),
.s0_rty_i(0),
//.s0_cab_o(),
// Slave 1 Interface
.s1_data_i(wire_gpio1_data_o),
.s1_data_o(wire_gpio1_data_i),
.s1_addr_o(wire_gpio1_addr_i),
.s1_sel_o(wire_gpio1_sel_i),
.s1_we_o(wire_gpio1_we_i),
.s1_cyc_o(wire_gpio1_cyc_i),
.s1_stb_o(wire_gpio1_stb_i),
.s1_ack_i(wire_gpio1_ack_o),
.s1_err_i(wire_gpio1_err_o),
.s1_rty_i(0),
//.s1_cab_o(),
);
例化连接ram和
ram_top u_ram0(
.clk_i(clk_i),
.rst_i(rst_i),
.wb_stb_i(wire_ram0_stb_i),
.wb_cyc_i(wire_ram0_cyc_i),
.wb_ack_o(wire_ram0_ack_o),
.wb_addr_i(wire_ram0_addr_i),
.wb_sel_i(wire_ram0_sel_i),
.wb_we_i(wire_ram0_we_i),
.wb_data_i(wire_ram0_data_i),
.wb_data_o(wire_ram0_data_o)
);
gpio_top u_gpio1(
.wb_clk_i(clk_i),
.wb_rst_i(rst_i),
.wb_stb_i(wire_gpio1_stb_i),
.wb_cyc_i(wire_gpio1_cyc_i),
.wb_ack_o(wire_gpio1_ack_o),
.wb_adr_i(wire_gpio1_addr_i),
.wb_sel_i(wire_gpio1_sel_i),
.wb_we_i(wire_gpio1_we_i),
.wb_dat_i(wire_gpio1_data_i),
.wb_err_o(wire_gpio1_err_o),
.wb_dat_o(wire_gpio1_data_o),
.wb_inta_o(wire_gpio_interrupt),
// External GPIO Interface
.ext_pad_i({16'b0,SW}),
.ext_pad_o(LEDR),
.ext_padoe_o()//,
);
然后将这个文件设置为顶层文件
至此,工程建立完毕,下面建立仿真文件,在Simulation sources下面添加仿真文件,命名为sim_soc_wyz
在sim_soc_wyz文件当中输入一下代码,然后将其在仿真目录中设为顶层文件
module sim_soc_wyz( );
reg CLOCK_50;
reg rst;
initial begin
CLOCK_50 = 1'b0;
forever #10 CLOCK_50 = ~CLOCK_50;
end
initial begin
rst = 1'b0;
#200 rst= 1'b1;
#100 rst= 1'b0;
#10000 $stop;
end
soc_top or1200_sopc_inst
(
.clk_i(CLOCK_50),
.rst_i(rst)
);
Endmodule
开始仿真,没有错误,出现下图
说明工程建立结束,连接正确。
四、编写程序,测试ram 和 gpio
-
- ram 测试
直接编写程序,将ram从地址0开始处,一次设置为0000,0001,0002
建立汇编文件如下:
-
- gpio测试
gpio的使用,首先使能32个PIO端口,向使能寄存器写入0xFFFF