使用iverilog+gtkwave 仿真or1200

为了学习雷思磊的,步步惊心 软核处理器内部设计和分析,又不想在linux下使用庞大的modelsim,只能摸索开源verilog仿真软件。

1.首先准备or1200源码,在opencores.org上下载吧。

2.在你的linux系统上安装iverilog和gtkwave,安装方法很简单,fedora:sudo yum install iverilog gtkwave. ubuntu:sudo apt-get install iverilog gtkwave

3.安装or1200的交叉编译器,编译器下载也在opencores.org,具体怎么安装,在网上搜一把,"交叉编译器安装“,虽然是arm的,但是or1200也一样。

4.接下来编写第一个测试程序test.S,第一个程序是or1200汇编程序,内容如下:

.section .text ,"ax"

.org 0x100

.global _start

_start:
	l.andi r0,r0,0
	l.extwz r1,r0
	l.extwz r2,r0
	l.addi r1,r1,0x0a
	l.add r2,r2,r1
	l.nop 0x0001
5.编写程序链接脚本,ram.ld,注意原书中"Entry(_start)"无法编译通过,我把它改为ENTRY(_start)

MEMORY 
	{
		ram : ORIGIN = 0x00000000, LENGTH = 0x00005000
	}
SECTIONS
	{
		.text :
			{
			*(.text)
			} > ram

		.data :
			{
			*(.data)
			} > ram

		.bss :
			{
			*(.bss)
			} > ram
	}

ENTRY (_start)
6.编译程序

or32-elf-as -o test.o test.S
or32-elf-ld -T ram.ld test.o -o test.or32
7.这个test.or32可以放入or1200模拟器中允许,为了装入qmem我们还需要进行处理,先把test.or32转为bin文件,再把bin转为存储器初始化文件。

or32-elf-objcopy -O binary test.or32 test.bin
8.应为我没有bin转hex的工具,只好自己写一个,代码如下:

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc,char **argv)
{
	FILE *fd_src,*fd_dst;
	char buf[64];
	int ret,i;

	if (argc != 2)
	{
		printf("usage: %s binfile\n",argv[0]);
		return 0;
	}
	fd_src = fopen(argv[1],"rb");
	if(!fd_src)
	{
		perror("src fopen:");
		return 0;
	}
	memset(buf,0,64);
	sprintf(buf,"%s.hex",argv[1]);

	fd_dst = fopen(buf,"w+");
        if(!fd_dst)
        {
                perror("dst fopen:");
		fclose(fd_src);
                return 0;
        }

	i = 0;
	while ((ret=fread(buf,1,4,fd_src))!=0)
	{
		if(ret != 4)
		{
			printf("read file error\n");
			fclose(fd_src);
			fclose(fd_dst);
			return 0;
		}
		ret = htonl(*((int *)buf));
		fprintf(fd_dst,"%08x\r\n",ret);
		i++;
	}

	while (i!=2048)
	{
		fprintf(fd_dst,"00000000\r\n");
		i++;
	}

	fclose(fd_src);
	fclose(fd_dst);



}
9.编写testbench文件,注意我在源文件中加了,initial那一节,这很重要。

`timescale 1ns/100ps

module or1200_tb1();

	reg CLOCK_50;
	reg rst;

	initial begin 
		CLOCK_50 = 1'b0;
		forever #10 CLOCK_50 = ~CLOCK_50;
	end

	initial begin 
		rst = 1'b1;
		#200 rst = 1'b0;
		#1000 $stop;
	end

	or1200_top or1200_top_inst
	(
		.clk_i(CLOCK_50),
		.rst_i(rst),
		.pic_ints_i(20'b0),
		.clmode_i(2'b00),
	//指令总线
		.iwb_clk_i(clk_i), .iwb_rst_i(rst), .iwb_dat_i(32'b0), .iwb_ack_i(1'b0), .iwb_err_i(1'b0), 
		.iwb_rty_i(1'b0), .iwb_cyc_o(), .iwb_adr_o(), .iwb_dat_o(), .iwb_stb_o(), .iwb_we_o(), 
		.iwb_sel_o(),

		`ifdef OR1200_WB_CAB
		.iwb_cab_o(),
		`endif

	//数据总线
		.dwb_clk_i(clk_i), .dwb_rst_i(rst), .dwb_dat_i(32'b0), .dwb_ack_i(1'b0), .dwb_err_i(1'b0),
		.dwb_rty_i(1'b0), .dwb_cyc_o(), .dwb_adr_o(), .dwb_dat_o(), .dwb_stb_o(), .dwb_we_o(),
		.dwb_sel_o(),
	
		`ifdef OR1200_WB_CAB
		.dwb_cab_o(),
		`endif

	//外部调试接口
		.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(),

	//电源接口
		.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()
	);

	initial
        begin            
            $dumpfile("or1200_tb1.vcd");
            $dumpvars(0,or1200_top_inst);
        end
endmodule
10.根据书上要求,更改or1200_qmem.v文件,并在or1200_spram_2048x32.v的611行添加

initial $readmemh("test.in.hex",mem)
11.编译所以verilog文件:

iverilog -o or1200_tb1 or1200_tb1.v $(SRC) //SRC代表所有verilog源文件
vvp -n or1200_tb1 -lxt2
cp or1200_tb1.vcd or1200_tb.lxt2
12.使用gtkwave打开or1200_tb.lxt2,就可以看波形如下图,和modelsim显示的一样

使用iverilog+gtkwave 仿真or1200_第1张图片

13.注意iverilog好像不能观察形如reg [aa:bb]  cccc[dd:ee];这类的变量,所以寄存器文件or1200_rf/rb_b/mem[1],无法查看,所以你只能修改源码,修改or1200_dpram.v,我在100行添加如下:

wire [dw-1:0] 		mem_r0;
	wire [dw-1:0] 		mem_r1;
	wire [dw-1:0] 		mem_r2;
	wire [dw-1:0] 		mem_r3;
	wire [dw-1:0] 		mem_r4;
	wire [dw-1:0] 		mem_r5;
	wire [dw-1:0] 		mem_r6;
	wire [dw-1:0] 		mem_r7;
	wire [dw-1:0] 		mem_r8;
	wire [dw-1:0] 		mem_r9;
	wire [dw-1:0] 		mem_r10;
	wire [dw-1:0] 		mem_r11;
	wire [dw-1:0] 		mem_r12;
	wire [dw-1:0] 		mem_r13;
	wire [dw-1:0] 		mem_r14;
	wire [dw-1:0] 		mem_r15;
	wire [dw-1:0] 		mem_r16;
	wire [dw-1:0] 		mem_r17;
	wire [dw-1:0] 		mem_r18;
	wire [dw-1:0] 		mem_r19;
	wire [dw-1:0] 		mem_r20;
	wire [dw-1:0] 		mem_r21;
	wire [dw-1:0] 		mem_r22;
	wire [dw-1:0] 		mem_r23;
	wire [dw-1:0] 		mem_r24;
	wire [dw-1:0] 		mem_r25;
	wire [dw-1:0] 		mem_r26;
	wire [dw-1:0] 		mem_r27;
	wire [dw-1:0] 		mem_r28;
	wire [dw-1:0] 		mem_r29;
	wire [dw-1:0] 		mem_r30;
	wire [dw-1:0] 		mem_r31;
	assign mem_r0 = mem[0];
	assign mem_r1 = mem[1];
	assign mem_r2 = mem[2];
	assign mem_r3 = mem[3];
	assign mem_r4 = mem[4];
	assign mem_r5 = mem[5];
	assign mem_r6 = mem[6];
	assign mem_r7 = mem[7];
	assign mem_r8 = mem[8];
	assign mem_r9 = mem[9];
	assign mem_r10 = mem[10];
	assign mem_r11 = mem[11];
	assign mem_r12 = mem[12];
	assign mem_r13 = mem[13];
	assign mem_r14 = mem[14];
	assign mem_r15 = mem[15];
	assign mem_r16 = mem[16];
	assign mem_r17 = mem[17];
	assign mem_r18 = mem[18];
	assign mem_r19 = mem[19];
	assign mem_r20 = mem[20];
	assign mem_r21 = mem[21];
	assign mem_r22 = mem[22];
	assign mem_r23 = mem[23];
	assign mem_r24 = mem[24];
	assign mem_r25 = mem[25];
	assign mem_r26 = mem[26];
	assign mem_r27 = mem[27];
	assign mem_r28 = mem[28];
	assign mem_r29 = mem[29];
	assign mem_r30 = mem[30];
	assign mem_r31 = mem[31];



14.想观察mem[1],就直接观察mem_r1,就成

你可能感兴趣的:(linux,iverilog,or1200)