Signed-off-by: Michael Walle <mich...@walle.cc> --- cores/lm32/test/Makefile | 21 +++ cores/lm32/test/crt.S | 28 +++ cores/lm32/test/hello_world.c | 15 ++ cores/lm32/test/linker.ld | 56 ++++++ cores/lm32/test/lm32_include.v | 377 ++++++++++++++++++++++++++++++++++++++++ cores/lm32/test/tb_lm32.v | 172 ++++++++++++++++++ 6 files changed, 669 insertions(+), 0 deletions(-) create mode 100644 cores/lm32/test/Makefile create mode 100644 cores/lm32/test/crt.S create mode 100644 cores/lm32/test/hello_world.c create mode 100644 cores/lm32/test/linker.ld create mode 100644 cores/lm32/test/lm32_include.v create mode 100644 cores/lm32/test/tb_lm32.v
diff --git a/cores/lm32/test/Makefile b/cores/lm32/test/Makefile new file mode 100644 index 0000000..7be362b --- /dev/null +++ b/cores/lm32/test/Makefile @@ -0,0 +1,21 @@ +SOURCES=tb_lm32.v lm32_include.v +SOURCES+=../rtl/lm32_adder.v ../rtl/lm32_addsub.v ../rtl/lm32_cpu.v ../rtl/lm32_dcache.v ../rtl/lm32_debug.v ../rtl/lm32_decoder.v ../rtl/lm32_dp_ram.v ../rtl/lm32_icache.v ../rtl/lm32_instruction_unit.v ../rtl/lm32_interrupt.v ../rtl/lm32_jtag.v ../rtl/lm32_load_store_unit.v ../rtl/lm32_logic_op.v ../rtl/lm32_mc_arithmetic.v ../rtl/lm32_multiplier.v ../rtl/lm32_ram.v ../rtl/lm32_shifter.v ../rtl/lm32_top.v + +all: tb_lm32 + +sim_%: %.vh tb_lm32 + @vvp tb_lm32 +prog=$< + +hello_world.elf: crt.S hello_world.c + lm32-elf-gcc -Tlinker.ld -fno-builtin -o $@ $^ + +%.vh: %.elf + lm32-elf-objcopy -O verilog $< $@ + +clean: + rm -f tb_lm32 *.vcd *.elf *.vh + +tb_lm32: $(SOURCES) + iverilog -o tb_lm32 $(SOURCES) + +.PHONY: clean sim diff --git a/cores/lm32/test/crt.S b/cores/lm32/test/crt.S new file mode 100644 index 0000000..326e5d7 --- /dev/null +++ b/cores/lm32/test/crt.S @@ -0,0 +1,28 @@ +.globl _start + +.text +_start: +xor r0, r0, r0 + +mvhi sp, hi(_fstack) +ori sp, sp, lo(_fstack) + +mv fp,r0 + +mvhi r1, hi(_fbss) +ori r1, r1, lo(_fbss) +mvhi r2, hi(_ebss) +ori r2, r2, lo(_ebss) + +1: +bge r1, r2, 2f +sw (r1+0), r0 +addi r1, r1, 4 +bi 1b +2: + +calli main + +mvhi r1, 0xdead +ori r2, r0, 0xbeef +sw (r1+0), r2 diff --git a/cores/lm32/test/hello_world.c b/cores/lm32/test/hello_world.c new file mode 100644 index 0000000..bdcdcbc --- /dev/null +++ b/cores/lm32/test/hello_world.c @@ -0,0 +1,15 @@ +void putc(char c) +{ + char *tx = (char*)0xff000000; + *tx = c; +} + +void puts(char *s) +{ + while (*s) putc(*s++); +} + +void main(void) +{ + puts("Hello World\n"); +} diff --git a/cores/lm32/test/linker.ld b/cores/lm32/test/linker.ld new file mode 100644 index 0000000..51ca00f --- /dev/null +++ b/cores/lm32/test/linker.ld @@ -0,0 +1,56 @@ +OUTPUT_FORMAT("elf32-lm32") +ENTRY(_start) + +__DYNAMIC = 0; + +MEMORY { + pmem : ORIGIN = 0x00000000, LENGTH = 0x8000 + dmem : ORIGIN = 0x00008000, LENGTH = 0x8000 +} + +SECTIONS +{ + .text : + { + _ftext = .; + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > pmem + + .rodata : + { + . = ALIGN(4); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + _erodata = .; + } > dmem + + .data : + { + . = ALIGN(4); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + _gp = ALIGN(16); + *(.sdata .sdata.* .gnu.linkonce.s.*) + _edata = .; + } > dmem + + .bss : + { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + } > dmem +} + +PROVIDE(_fstack = ORIGIN(dmem) + LENGTH(dmem) - 4); diff --git a/cores/lm32/test/lm32_include.v b/cores/lm32/test/lm32_include.v new file mode 100644 index 0000000..ffa95bf --- /dev/null +++ b/cores/lm32/test/lm32_include.v @@ -0,0 +1,377 @@ +// ================================================================== +// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< +// ------------------------------------------------------------------ +// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation +// ALL RIGHTS RESERVED +// ------------------------------------------------------------------ +// +// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM. +// +// Permission: +// +// Lattice Semiconductor grants permission to use this code +// pursuant to the terms of the Lattice Semiconductor Corporation +// Open Source License Agreement. +// +// Disclaimer: +// +// Lattice Semiconductor provides no warranty regarding the use or +// functionality of this code. It is the user's responsibility to +// verify the user's design for consistency and functionality through +// the use of formal verification methods. +// +// -------------------------------------------------------------------- +// +// Lattice Semiconductor Corporation +// 5555 NE Moore Court +// Hillsboro, OR 97214 +// U.S.A +// +// TEL: 1-800-Lattice (USA and Canada) +// 503-286-8001 (other locations) +// +// web: http://www.latticesemi.com/ +// email: techsupp...@latticesemi.com +// +// -------------------------------------------------------------------- +// FILE DETAILS +// Project : LatticeMico32 +// File : lm32_include.v +// Title : CPU global macros +// Version : 6.1.17 +// : Initial Release +// Version : 7.0SP2, 3.0 +// : No Change +// Version : 3.1 +// : No Change +// Version : 3.2 +// : No Change +// Version : 3.3 +// : Support for extended configuration register +// ============================================================================= + +`ifdef LM32_INCLUDE_V +`else +`define LM32_INCLUDE_V + +// +// Common configuration options +// + +`define CFG_EBA_RESET 32'h0 +`define CFG_DEBA_RESET 32'h0 + +`define CFG_PL_MULTIPLY_ENABLED +`define CFG_PL_BARREL_SHIFT_ENABLED +`define CFG_SIGN_EXTEND_ENABLED +`define CFG_MC_DIVIDE_ENABLED +`define CFG_EBR_POSEDGE_REGISTER_FILE + +`define CFG_ICACHE_ENABLED +`define CFG_ICACHE_ASSOCIATIVITY 1 +`define CFG_ICACHE_SETS 256 +`define CFG_ICACHE_BYTES_PER_LINE 16 +`define CFG_ICACHE_BASE_ADDRESS 32'h0 +`define CFG_ICACHE_LIMIT 32'h7fffffff + +`define CFG_DCACHE_ENABLED +`define CFG_DCACHE_ASSOCIATIVITY 1 +`define CFG_DCACHE_SETS 256 +`define CFG_DCACHE_BYTES_PER_LINE 16 +`define CFG_DCACHE_BASE_ADDRESS 32'h0 +`define CFG_DCACHE_LIMIT 32'h7fffffff + +// Enable Debugging +//`define CFG_JTAG_ENABLED +//`define CFG_JTAG_UART_ENABLED +`define CFG_DEBUG_ENABLED +//`define CFG_HW_DEBUG_ENABLED +`define CFG_ROM_DEBUG_ENABLED +`define CFG_BREAKPOINTS 32'h4 +`define CFG_WATCHPOINTS 32'h4 +`define CFG_EXTERNAL_BREAK_ENABLED +`define CFG_GDBSTUB_ENABLED + +// +// End of common configuration options +// + +`ifdef TRUE +`else +`define TRUE 1'b1 +`define FALSE 1'b0 +`define TRUE_N 1'b0 +`define FALSE_N 1'b1 +`endif + +// Wishbone configuration +`define CFG_IWB_ENABLED +`define CFG_DWB_ENABLED + +// Data-path width +`define LM32_WORD_WIDTH 32 +`define LM32_WORD_RNG (`LM32_WORD_WIDTH-1):0 +`define LM32_SHIFT_WIDTH 5 +`define LM32_SHIFT_RNG (`LM32_SHIFT_WIDTH-1):0 +`define LM32_BYTE_SELECT_WIDTH 4 +`define LM32_BYTE_SELECT_RNG (`LM32_BYTE_SELECT_WIDTH-1):0 + +// Register file size +`define LM32_REGISTERS 32 +`define LM32_REG_IDX_WIDTH 5 +`define LM32_REG_IDX_RNG (`LM32_REG_IDX_WIDTH-1):0 + +// Standard register numbers +`define LM32_RA_REG `LM32_REG_IDX_WIDTH'd29 +`define LM32_EA_REG `LM32_REG_IDX_WIDTH'd30 +`define LM32_BA_REG `LM32_REG_IDX_WIDTH'd31 + +// Range of Program Counter. Two LSBs are always 0. +`define LM32_PC_WIDTH (`LM32_WORD_WIDTH-2) +`define LM32_PC_RNG (`LM32_PC_WIDTH+2-1):2 + +// Range of an instruction +`define LM32_INSTRUCTION_WIDTH 32 +`define LM32_INSTRUCTION_RNG (`LM32_INSTRUCTION_WIDTH-1):0 + +// Adder operation +`define LM32_ADDER_OP_ADD 1'b0 +`define LM32_ADDER_OP_SUBTRACT 1'b1 + +// Shift direction +`define LM32_SHIFT_OP_RIGHT 1'b0 +`define LM32_SHIFT_OP_LEFT 1'b1 + +// Bus errors +`define CFG_BUS_ERRORS_ENABLED + +// Derive macro that indicates whether we have single-stepping or not +`ifdef CFG_ROM_DEBUG_ENABLED +`define LM32_SINGLE_STEP_ENABLED +`else +`ifdef CFG_HW_DEBUG_ENABLED +`define LM32_SINGLE_STEP_ENABLED +`endif +`endif + +// Derive macro that indicates whether JTAG interface is required +`ifdef CFG_JTAG_UART_ENABLED +`define LM32_JTAG_ENABLED +`else +`ifdef CFG_DEBUG_ENABLED +`define LM32_JTAG_ENABLED +`else +`endif +`endif + +// Derive macro that indicates whether ROM debug is required +`ifdef CFG_GDBSTUB_ENABLED +`define CFG_ROM_DEBUG_ENABLED +`endif + +// Derive macro that indicates whether we have a barrel-shifter or not +`ifdef CFG_PL_BARREL_SHIFT_ENABLED +`define LM32_BARREL_SHIFT_ENABLED +`else // CFG_PL_BARREL_SHIFT_ENABLED +`ifdef CFG_MC_BARREL_SHIFT_ENABLED +`define LM32_BARREL_SHIFT_ENABLED +`else +`define LM32_NO_BARREL_SHIFT +`endif +`endif // CFG_PL_BARREL_SHIFT_ENABLED + +// Derive macro that indicates whether we have a multiplier or not +`ifdef CFG_PL_MULTIPLY_ENABLED +`define LM32_MULTIPLY_ENABLED +`else +`ifdef CFG_MC_MULTIPLY_ENABLED +`define LM32_MULTIPLY_ENABLED +`endif +`endif + +// Derive a macro that indicates whether or not the multi-cycle arithmetic unit is required +`ifdef CFG_MC_DIVIDE_ENABLED +`define LM32_MC_ARITHMETIC_ENABLED +`endif +`ifdef CFG_MC_MULTIPLY_ENABLED +`define LM32_MC_ARITHMETIC_ENABLED +`endif +`ifdef CFG_MC_BARREL_SHIFT_ENABLED +`define LM32_MC_ARITHMETIC_ENABLED +`endif + +// Derive macro that indicates if we are using an EBR register file +`ifdef CFG_EBR_POSEDGE_REGISTER_FILE +`define LM32_EBR_REGISTER_FILE +`endif +`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE +`define LM32_EBR_REGISTER_FILE +`endif + +// Revision number +`define LM32_REVISION 6'h02 + +// Logical operations - Function encoded directly in instruction +`define LM32_LOGIC_OP_RNG 3:0 + +// Conditions for conditional branches +`define LM32_CONDITION_WIDTH 3 +`define LM32_CONDITION_RNG (`LM32_CONDITION_WIDTH-1):0 +`define LM32_CONDITION_E 3'b001 +`define LM32_CONDITION_G 3'b010 +`define LM32_CONDITION_GE 3'b011 +`define LM32_CONDITION_GEU 3'b100 +`define LM32_CONDITION_GU 3'b101 +`define LM32_CONDITION_NE 3'b111 +`define LM32_CONDITION_U1 3'b000 +`define LM32_CONDITION_U2 3'b110 + +// Size of load or store instruction - Encoding corresponds to opcode +`define LM32_SIZE_WIDTH 2 +`define LM32_SIZE_RNG 1:0 +`define LM32_SIZE_BYTE 2'b00 +`define LM32_SIZE_HWORD 2'b11 +`define LM32_SIZE_WORD 2'b10 +`define LM32_ADDRESS_LSBS_WIDTH 2 + +// Width and range of a CSR index +`ifdef CFG_DEBUG_ENABLED +`define LM32_CSR_WIDTH 5 +`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0 +`else +`ifdef CFG_JTAG_ENABLED +`define LM32_CSR_WIDTH 4 +`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0 +`else +`define LM32_CSR_WIDTH 3 +`define LM32_CSR_RNG (`LM32_CSR_WIDTH-1):0 +`endif +`endif + +// CSR indices +`define LM32_CSR_IE `LM32_CSR_WIDTH'h0 +`define LM32_CSR_IM `LM32_CSR_WIDTH'h1 +`define LM32_CSR_IP `LM32_CSR_WIDTH'h2 +`define LM32_CSR_ICC `LM32_CSR_WIDTH'h3 +`define LM32_CSR_DCC `LM32_CSR_WIDTH'h4 +`define LM32_CSR_CC `LM32_CSR_WIDTH'h5 +`define LM32_CSR_CFG `LM32_CSR_WIDTH'h6 +`define LM32_CSR_EBA `LM32_CSR_WIDTH'h7 +`ifdef CFG_DEBUG_ENABLED +`define LM32_CSR_DC `LM32_CSR_WIDTH'h8 +`define LM32_CSR_DEBA `LM32_CSR_WIDTH'h9 +`endif +`define LM32_CSR_CFG2 `LM32_CSR_WIDTH'ha +`ifdef CFG_JTAG_ENABLED +`define LM32_CSR_JTX `LM32_CSR_WIDTH'he +`define LM32_CSR_JRX `LM32_CSR_WIDTH'hf +`endif +`ifdef CFG_DEBUG_ENABLED +`define LM32_CSR_BP0 `LM32_CSR_WIDTH'h10 +`define LM32_CSR_BP1 `LM32_CSR_WIDTH'h11 +`define LM32_CSR_BP2 `LM32_CSR_WIDTH'h12 +`define LM32_CSR_BP3 `LM32_CSR_WIDTH'h13 +`define LM32_CSR_WP0 `LM32_CSR_WIDTH'h18 +`define LM32_CSR_WP1 `LM32_CSR_WIDTH'h19 +`define LM32_CSR_WP2 `LM32_CSR_WIDTH'h1a +`define LM32_CSR_WP3 `LM32_CSR_WIDTH'h1b +`endif + +// Values for WPC CSR +`define LM32_WPC_C_RNG 1:0 +`define LM32_WPC_C_DISABLED 2'b00 +`define LM32_WPC_C_READ 2'b01 +`define LM32_WPC_C_WRITE 2'b10 +`define LM32_WPC_C_READ_WRITE 2'b11 + +// Exception IDs +`define LM32_EID_WIDTH 3 +`define LM32_EID_RNG (`LM32_EID_WIDTH-1):0 +`define LM32_EID_RESET 3'h0 +`define LM32_EID_BREAKPOINT 3'd1 +`define LM32_EID_INST_BUS_ERROR 3'h2 +`define LM32_EID_WATCHPOINT 3'd3 +`define LM32_EID_DATA_BUS_ERROR 3'h4 +`define LM32_EID_DIVIDE_BY_ZERO 3'h5 +`define LM32_EID_INTERRUPT 3'h6 +`define LM32_EID_SCALL 3'h7 + +// Pipeline result selection mux controls + +`define LM32_D_RESULT_SEL_0_RNG 0:0 +`define LM32_D_RESULT_SEL_0_REG_0 1'b0 +`define LM32_D_RESULT_SEL_0_NEXT_PC 1'b1 + +`define LM32_D_RESULT_SEL_1_RNG 1:0 +`define LM32_D_RESULT_SEL_1_ZERO 2'b00 +`define LM32_D_RESULT_SEL_1_REG_1 2'b01 +`define LM32_D_RESULT_SEL_1_IMMEDIATE 2'b10 + +`define LM32_USER_OPCODE_WIDTH 11 +`define LM32_USER_OPCODE_RNG (`LM32_USER_OPCODE_WIDTH-1):0 + +// Derive a macro to indicate if either of the caches are implemented +`ifdef CFG_ICACHE_ENABLED +`define LM32_CACHE_ENABLED +`else +`ifdef CFG_DCACHE_ENABLED +`define LM32_CACHE_ENABLED +`endif +`endif + +///////////////////////////////////////////////////// +// Interrupts +///////////////////////////////////////////////////// + +// Always enable interrupts +`define CFG_INTERRUPTS_ENABLED + +// Currently this is fixed to 32 and should not be changed +`define CFG_INTERRUPTS 32 +`define LM32_INTERRUPT_WIDTH `CFG_INTERRUPTS +`define LM32_INTERRUPT_RNG (`LM32_INTERRUPT_WIDTH-1):0 + +///////////////////////////////////////////////////// +// General +///////////////////////////////////////////////////// + +// Sub-word range types +`define LM32_BYTE_WIDTH 8 +`define LM32_BYTE_RNG 7:0 +`define LM32_HWORD_WIDTH 16 +`define LM32_HWORD_RNG 15:0 + +// Word sub-byte indicies +`define LM32_BYTE_0_RNG 7:0 +`define LM32_BYTE_1_RNG 15:8 +`define LM32_BYTE_2_RNG 23:16 +`define LM32_BYTE_3_RNG 31:24 + +// Word sub-halfword indices +`define LM32_HWORD_0_RNG 15:0 +`define LM32_HWORD_1_RNG 31:16 + +// Use a synchronous reset +`define CFG_RESET_SENSITIVITY + +// Wishbone defines +// Refer to Wishbone System-on-Chip Interconnection Architecture +// These should probably be moved to a Wishbone common file + +// Wishbone cycle types +`define LM32_CTYPE_WIDTH 3 +`define LM32_CTYPE_RNG (`LM32_CTYPE_WIDTH-1):0 +`define LM32_CTYPE_CLASSIC 3'b000 +`define LM32_CTYPE_CONSTANT 3'b001 +`define LM32_CTYPE_INCREMENTING 3'b010 +`define LM32_CTYPE_END 3'b111 + +// Wishbone burst types +`define LM32_BTYPE_WIDTH 2 +`define LM32_BTYPE_RNG (`LM32_BTYPE_WIDTH-1):0 +`define LM32_BTYPE_LINEAR 2'b00 +`define LM32_BTYPE_4_BEAT 2'b01 +`define LM32_BTYPE_8_BEAT 2'b10 +`define LM32_BTYPE_16_BEAT 2'b11 + +`endif diff --git a/cores/lm32/test/tb_lm32.v b/cores/lm32/test/tb_lm32.v new file mode 100644 index 0000000..6cae9c2 --- /dev/null +++ b/cores/lm32/test/tb_lm32.v @@ -0,0 +1,172 @@ +`include "lm32_include.v" + +module soc(); + +reg sys_rst; +reg sys_clk; +reg [31:0] interrupt; + +reg i_ack; +wire [31:0] i_adr; +wire i_cyc; +wire [31:0] i_dat; +wire i_stb; + +reg d_ack; +wire [31:0] d_adr; +wire d_cyc; +wire [31:0] d_dat_i; +wire [31:0] d_dat_o; +wire [3:0] d_sel; +wire d_stb; + +lm32_top lm32( + .clk_i(sys_clk), + .rst_i(sys_rst), + + .interrupt(interrupt), + + .I_ACK_I(i_ack), + .I_ADR_O(i_adr), + .I_BTE_O(), + .I_CTI_O(), + .I_CYC_O(i_cyc), + .I_DAT_I(i_dat), + .I_DAT_O(), + .I_ERR_I(1'b0), + .I_LOCK_O(), + .I_RTY_I(1'b0), + .I_SEL_O(), + .I_STB_O(i_stb), + .I_WE_O(), + + .D_ACK_I(d_ack), + .D_ADR_O(d_adr), + .D_BTE_O(), + .D_CTI_O(), + .D_CYC_O(d_cyc), + .D_DAT_I(d_dat_i), + .D_DAT_O(d_dat_o), + .D_ERR_I(1'b0), + .D_LOCK_O(), + .D_RTY_I(1'b0), + .D_SEL_O(d_sel), + .D_STB_O(d_stb), + .D_WE_O(d_we) +); + +// clock +initial sys_clk = 1'b0; +always #5 sys_clk = ~sys_clk; + +// reset +initial begin + sys_rst = 1'b1; + #20 + sys_rst = 1'b0; +end + +// data memory +reg [7:0] dmem[0:65536]; +wire [31:0] dmem_dat_i; +reg [31:0] dmem_dat_o; +wire [13:0] dmem_adr; +wire [3:0] dmem_we; +always @(posedge sys_clk) begin + if(dmem_we[0]) dmem[{dmem_adr, 2'b11}] <= dmem_dat_i[7:0]; + if(dmem_we[1]) dmem[{dmem_adr, 2'b10}] <= dmem_dat_i[15:8]; + if(dmem_we[2]) dmem[{dmem_adr, 2'b01}] <= dmem_dat_i[23:16]; + if(dmem_we[3]) dmem[{dmem_adr, 2'b00}] <= dmem_dat_i[31:24]; + dmem_dat_o[7:0] <= dmem[{dmem_adr, 2'b11}]; + dmem_dat_o[15:8] <= dmem[{dmem_adr, 2'b10}]; + dmem_dat_o[23:16] <= dmem[{dmem_adr, 2'b01}]; + dmem_dat_o[31:24] <= dmem[{dmem_adr, 2'b00}]; +end + +// program memory +reg [7:0] pmem[0:65536]; +wire [31:0] pmem_dat_i; +reg [31:0] pmem_dat_o; +wire [13:0] pmem_adr; +always @(posedge sys_clk) begin + pmem_dat_o[7:0] <= pmem[{pmem_adr, 2'b11}]; + pmem_dat_o[15:8] <= pmem[{pmem_adr, 2'b10}]; + pmem_dat_o[23:16] <= pmem[{pmem_adr, 2'b01}]; + pmem_dat_o[31:24] <= pmem[{pmem_adr, 2'b00}]; +end + +// uart +always @(posedge sys_clk) begin + if(d_cyc & d_stb & d_we & d_ack) + if(d_adr == 32'hff000000) + $write("%c", d_dat_o[7:0]); +end + +// wishbone interface for instruction bus +always @(posedge sys_clk) begin + if(sys_rst) + i_ack <= 1'b0; + else begin + i_ack <= 1'b0; + if(i_cyc & i_stb & ~i_ack) + i_ack <= 1'b1; + end +end + +assign i_dat = pmem_dat_o; +assign pmem_adr = i_adr[15:2]; + +// wishbone interface for data bus +always @(posedge sys_clk) begin + if(sys_rst) + d_ack <= 1'b0; + else begin + d_ack <= 1'b0; + if(d_cyc & d_stb & ~d_ack) + d_ack <= 1'b1; + end +end + +assign d_dat_i = dmem_dat_o; +assign dmem_dat_i = d_dat_o; +assign dmem_adr = d_adr[15:2]; +assign dmem_we = {4{d_cyc & d_stb & d_we}} & d_sel; + +// interrupts +initial interrupt <= 32'b0; + +// simulation end request +always @(posedge sys_clk) begin + if(d_cyc & d_stb & d_we & d_ack) + if(d_adr == 32'hdead0000 && d_dat_o == 32'hbeef) + $finish; +end + +// traces +`ifdef TB_ENABLE_WB_TRACES +always @(posedge sys_clk) begin + if(i_cyc & i_stb & i_ack) + $display("i load @%08x %08x", i_adr, i_dat); + if(d_cyc & d_stb & ~d_we & d_ack) + $display("d load @%08x %08x", d_adr, d_dat_o); + if(d_cyc & d_stb & d_we & d_ack) + $display("d store @%08x %08x", d_adr, d_dat_o); +end +`endif + +// dump signals +initial $dumpfile("tb_lm32.vcd"); +initial $dumpvars(0, soc); + +// init memory +reg [256*8:0] prog; +initial begin + if(! $value$plusargs("prog=%s", prog)) begin + $display("ERROR: please specify +prog=<file>.vh to start."); + $finish; + end +end +initial $readmemh(prog, dmem); +initial $readmemh(prog, pmem); + +endmodule -- 1.7.2.5 _______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkymist@Freenode