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

Reply via email to