OpenCores
URL https://opencores.org/ocsvn/mpx/mpx/trunk

Subversion Repositories mpx

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mpx/trunk/rtl
    from Rev 10 to Rev 9
    Reverse comparison

Rev 10 → Rev 9

/sim_verilator/top.cpp
0,0 → 1,306
//-----------------------------------------------------------------
// MPX 32-bit Soft-Core Processor
// V0.1
// Ultra-Embedded.com
// Copyright 2011 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//
// If you would like a version with a different license for use
// in commercial projects please contact the above email address
// for more details.
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2012 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
 
#include "top.h"
 
#include "Vtop.h"
#include "Vtop_top.h"
#include "Vtop_sram4__S13.h"
#include "Vtop_sram__S13.h"
#include "Vtop_soc_core__pi1.h"
#include "Vtop_cpu__B10000000_I10000000.h"
 
#include "verilated.h"
 
#if VM_TRACE
#include <verilated_vcd_c.h>
#endif
 
//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
// Memory start offset (set to 0x2000 to match FPGA version where
// bootloader exists in first 8K)
#define MEMORY_START 0x10000000
#define MEMORY_SIZE (512 * 1024)
#define REGISTERS 32
 
#define CPU_INSTANCE top->v->u1_cpu->u1_cpu
 
//-----------------------------------------------------------------
// Locals
//-----------------------------------------------------------------
static Vtop *top;
static unsigned int _stop_pc = 0xFFFFFFFF;
 
#if VM_TRACE
static unsigned int main_time = 0;
static VerilatedVcdC* tfp;
#endif
 
//-----------------------------------------------------------------
// top_init
//-----------------------------------------------------------------
int top_init(void)
{
top = new Vtop();
 
#if VM_TRACE
// If verilator was invoked with --trace
Verilated::traceEverOn(true);
VL_PRINTF("Enabling GTKWave Trace Output...\n");
tfp = new VerilatedVcdC;
top->trace (tfp, 99);
tfp->open ("wave_dump.vcd");
#endif
 
// Initial
top->clk_i = 0;
top->rst_i = 1;
top->en_i = 1;
top->intr_i = 0;
top->dbg_reg_addr_i = 0;
top->eval();
 
// Reset
top->clk_i = 1;
top->rst_i = 1;
top->eval();
 
top->clk_i = 0;
top->rst_i = 0;
top->eval();
 
return 0;
}
//-----------------------------------------------------------------
// top_load
//-----------------------------------------------------------------
int top_load(unsigned int addr, unsigned char val)
{
if (addr >= (MEMORY_SIZE - MEMORY_START))
return -1;
 
addr -= MEMORY_START;
 
switch (addr & 0x3)
{
case 0:
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__3__KET____DOT__u1_bram->ram[addr >> 2] = val;
break;
case 1:
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__2__KET____DOT__u1_bram->ram[addr >> 2] = val;
break;
case 2:
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__1__KET____DOT__u1_bram->ram[addr >> 2] = val;
break;
case 3:
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__0__KET____DOT__u1_bram->ram[addr >> 2] = val;
break;
}
 
return 0;
}
//-----------------------------------------------------------------
// top_mem_read
//-----------------------------------------------------------------
unsigned char top_mem_read(unsigned int addr)
{
unsigned char val = 0;
 
if (addr >= (MEMORY_SIZE - MEMORY_START))
return 0;
 
addr -= MEMORY_START;
 
switch (addr & 0x3)
{
case 0:
val = top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__3__KET____DOT__u1_bram->ram[addr >> 2];
break;
case 1:
val = top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__2__KET____DOT__u1_bram->ram[addr >> 2];
break;
case 2:
val = top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__1__KET____DOT__u1_bram->ram[addr >> 2];
break;
case 3:
val = top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__0__KET____DOT__u1_bram->ram[addr >> 2];
break;
}
 
return val;
}
//-----------------------------------------------------------------
// top_setbreakpoint
//-----------------------------------------------------------------
int top_setbreakpoint(int bp, unsigned int pc)
{
if (bp != 0)
return -1;
else
{
_stop_pc = pc;
return 0;
}
}
//-----------------------------------------------------------------
// top_run
//-----------------------------------------------------------------
int top_run(int cycles, int intr_after_cycles)
{
int current_cycle = 0;
unsigned int last_pc = CPU_INSTANCE->get_pc();
 
// Run until fault or number of cycles completed
while (!Verilated::gotFinish() && !top->fault_o && (current_cycle < cycles || cycles == -1))
{
// CLK->L
top->clk_i = 0;
top->eval();
 
#if VM_TRACE
if (tfp) tfp->dump (main_time++);
#endif
 
// CLK->H
top->clk_i = 1;
top->eval();
 
#if VM_TRACE
if (tfp) tfp->dump (main_time++);
#endif
 
if (top->uart_wr_o)
printf("%c", top->uart_data_o);
 
// Generate interrupt after a certain number of cycles?
if (intr_after_cycles >= 0 && intr_after_cycles == current_cycle)
{
top->intr_i = 1;
intr_after_cycles = -1;
}
else
top->intr_i = 0;
 
unsigned int new_pc = CPU_INSTANCE->get_pc();
if (last_pc != new_pc)
{
last_pc = new_pc;
current_cycle++;
}
 
// Breakpoint hit
if (_stop_pc == new_pc || top->break_o)
return TOP_RES_BREAKPOINT;
}
 
// Fault
if (top->fault_o)
return TOP_RES_FAULT;
// Number of cycles reached
else if (current_cycle >= cycles)
return TOP_RES_MAX_CYCLES;
// No error
else
return TOP_RES_OK;
}
//-----------------------------------------------------------------
// top_reset
//-----------------------------------------------------------------
void top_reset(void)
{
// Reset = H
top->rst_i = 1;
// Clock
top->clk_i = 1;
top->eval();
top->clk_i = 0;
top->eval();
 
// Reset = L
top->rst_i = 0;
top->eval();
}
//-----------------------------------------------------------------
// top_getreg
//-----------------------------------------------------------------
unsigned int top_getreg(int reg)
{
top->en_i = 0;
 
top->dbg_reg_addr_i = reg;
 
// Clock
top->clk_i = 1;
top->eval();
top->clk_i = 0;
top->eval();
 
top->en_i = 1;
 
return top->dbg_reg_out_o;
}
//-----------------------------------------------------------------
// top_reset
//-----------------------------------------------------------------
unsigned int top_getpc(void)
{
return CPU_INSTANCE->get_pc();
}
//-----------------------------------------------------------------
// top_done
//-----------------------------------------------------------------
void top_done(void)
{
top->final();
#if VM_TRACE
if (tfp)
{
tfp->close();
tfp = NULL;
}
#endif
}
/sim_verilator/main.cpp
0,0 → 1,164
//-----------------------------------------------------------------
// MPX 32-bit Soft-Core Processor
// V0.1
// Ultra-Embedded.com
// Copyright 2011 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//
// If you would like a version with a different license for use
// in commercial projects please contact the above email address
// for more details.
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2012 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
 
#include "top.h"
#include "verilated.h"
 
//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
#define MEM_BASE 0x10000000
 
//-----------------------------------------------------------------
// Locals
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(int argc, char **argv, char **env)
{
int c;
int err;
unsigned int loadAddr = MEM_BASE;
char *filename = NULL;
int help = 0;
int exitcode = 0;
int cycles = -1;
int intr_after = -1;
 
Verilated::commandArgs(argc, argv);
 
while ((c = getopt (argc, argv, "f:l:c:i:")) != -1)
{
switch(c)
{
case 'l':
loadAddr = strtoul(optarg, NULL, 0);
break;
case 'f':
filename = optarg;
break;
case 'c':
cycles = strtoul(optarg, NULL, 0);
break;
case 'i':
intr_after = strtoul(optarg, NULL, 0);
break;
case '?':
default:
help = 1;
break;
}
}
 
if (loadAddr < MEM_BASE)
{
fprintf (stderr,"Load address incorrect (0x%x)\n", loadAddr);
exit(-1);
}
 
if (help)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-t = Enable program trace\n");
fprintf (stderr,"-l 0xnnnn = Executable load address\n");
fprintf (stderr,"-f filename = Executable to load\n");
fprintf (stderr,"-c num = Max number of cycles\n");
fprintf (stderr,"-i num = Generate interrupt after num cycles\n");
exit(0);
}
 
top_init();
 
if (filename)
{
FILE *f;
 
printf("Opening %s\n", filename);
f = fopen(filename, "rb");
if (f)
{
long size;
char *buf;
 
// Get size
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
 
buf = (char*)malloc(size+1);
if (buf)
{
unsigned int addr;
 
// Read file data in
int len = fread(buf, 1, size, f);
buf[len] = 0;
 
printf("Loading to 0x%x\n", loadAddr);
for (addr=0;addr<len;addr++)
top_load(loadAddr + addr, buf[addr]);
 
free(buf);
fclose(f);
}
}
else
{
printf("Could not read file!\n");
exit(-1);
}
}
 
// Run
err = top_run(cycles, intr_after);
 
if (err == TOP_RES_FAULT)
printf("FAULT PC %x!\n", top_getpc());
 
top_done();
 
printf("Exit\n");
exit((err == TOP_RES_FAULT) ? 1 : 0);
}
/sim_verilator/sram.v
0,0 → 1,90
//-----------------------------------------------------------------
// MPX 32-bit Soft-Core Processor
// V0.1
// Ultra-Embedded.com
// Copyright 2011 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//
// If you would like a version with a different license for use
// in commercial projects please contact the above email address
// for more details.
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2012 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module sram
(
clk_i,
adr_i,
dat_i,
wr_i,
dat_o
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] WIDTH = 8;
parameter [31:0] SIZE = 14;
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
output [(WIDTH - 1):0] dat_o /*verilator public*/;
input [(WIDTH - 1):0] dat_i /*verilator public*/;
input [(SIZE - 1):0] adr_i /*verilator public*/;
input wr_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
reg [(SIZE - 1):0] rd_addr;
wire [(WIDTH - 1):0] dat_o;
 
//-----------------------------------------------------------------
// Processes
//-----------------------------------------------------------------
always @ (posedge clk_i)
begin
if (wr_i == 1'b1)
ram[adr_i] <= dat_i;
rd_addr <= adr_i;
end
 
//-------------------------------------------------------------------
// Combinatorial
//-------------------------------------------------------------------
assign dat_o = ram[rd_addr];
 
endmodule
/sim_verilator/top.v
0,0 → 1,185
//-----------------------------------------------------------------
// MPX 32-bit Soft-Core Processor
// V0.1
// Ultra-Embedded.com
// Copyright 2011 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//
// If you would like a version with a different license for use
// in commercial projects please contact the above email address
// for more details.
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2012 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module top
(
// Clocking & Reset
clk_i,
rst_i,
// Global Enable
en_i,
// Fault Output
fault_o,
// Break Output
break_o,
// Interrupt Input
intr_i,
// Debug Register Access
dbg_reg_addr_i,
dbg_reg_out_o,
// UART output
uart_data_o,
uart_wr_o
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter CLK_KHZ = (8192*7);
parameter SRAM_ADDR_WIDTH = 19;
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
input en_i /*verilator public*/;
output fault_o /*verilator public*/;
output break_o /*verilator public*/;
input intr_i /*verilator public*/;
input [8:0] dbg_reg_addr_i /*verilator public*/;
output [31:0] dbg_reg_out_o /*verilator public*/;
output [7:0] uart_data_o /*verilator public*/;
output uart_wr_o /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire fault_o;
wire break_o;
wire [31:0] dbg_reg_out_o;
wire [7:0] uart_data_o;
wire uart_wr_o;
wire [31:0] int_mem_addr_o;
wire [31:0] int_mem_data_o;
wire [31:0] int_mem_data_i;
wire [3:0] int_mem_wr_o;
 
wire [31:0] ext_mem_addr_o;
wire [31:0] ext_mem_data_o;
wire [31:0] ext_mem_data_i;
wire [3:0] ext_mem_wr_o;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
sram4
#(
.SRAM_ADDR_WIDTH(SRAM_ADDR_WIDTH)
)
u1_bram
(
.clk_i(clk_i),
.address_i(int_mem_addr_o),
.data_i(int_mem_data_o),
.data_o(int_mem_data_i),
.wr_i(int_mem_wr_o)
);
 
sram4
#(
.SRAM_ADDR_WIDTH(SRAM_ADDR_WIDTH)
)
u2_bram
(
.clk_i(clk_i),
.address_i(ext_mem_addr_o),
.data_i(ext_mem_data_o),
.data_o(ext_mem_data_i),
.wr_i(ext_mem_wr_o)
);
 
soc_core
#(
.CLK_KHZ(CLK_KHZ),
.UART_BAUD(115200),
.EXTERNAL_INTERRUPTS(1),
.BOOT_VECTOR(32'h10000000),
.ISR_VECTOR(32'h10000000),
.REGISTER_FILE_TYPE("SIMULATION")
)
u1_cpu
(
// Clock / Status
.clk_i(clk_i),
.rst_i(rst_i),
.en_i(en_i),
.ext_intr_i(intr_i),
.fault_o(fault_o),
.break_o(break_o),
// UART
.uart_tx_o(/* open */),
.uart_rx_i(1'b0),
// Internal Memory
.int_mem_addr_o(int_mem_addr_o),
.int_mem_data_o(int_mem_data_o),
.int_mem_data_i(int_mem_data_i),
.int_mem_wr_o(int_mem_wr_o),
.int_mem_rd_o(/*open */),
.int_mem_pause_i(1'b0),
// External Memory
.ext_mem_addr_o(ext_mem_addr_o),
.ext_mem_data_o(ext_mem_data_o),
.ext_mem_data_i(ext_mem_data_i),
.ext_mem_wr_o(ext_mem_wr_o),
.ext_mem_rd_o(/*open */),
.ext_mem_pause_i(1'b0),
// External I/O or Memory
.ext_io_addr_o(/*open */),
.ext_io_data_o(/*open */),
.ext_io_data_i(32'h00000000),
.ext_io_wr_o(/*open */),
.ext_io_rd_o(/*open */),
.ext_io_pause_i(1'b0),
// Debug UART output
.dbg_uart_data_o(uart_data_o),
.dbg_uart_wr_o(uart_wr_o)
);
endmodule
/sim_verilator/test_image.bin Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
sim_verilator/test_image.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: sim_verilator/top.h =================================================================== --- sim_verilator/top.h (nonexistent) +++ sim_verilator/top.h (revision 9) @@ -0,0 +1,25 @@ +#ifndef __TOP_H__ +#define __TOP_H__ + +//-------------------------------------------------------------------- +// Defines +//-------------------------------------------------------------------- +#define TOP_RES_FAULT -1 +#define TOP_RES_OK 0 +#define TOP_RES_MAX_CYCLES 1 +#define TOP_RES_BREAKPOINT 2 + +//-------------------------------------------------------------------- +// Prototypes +//-------------------------------------------------------------------- +int top_init(void); +int top_load(unsigned int addr, unsigned char val); +void top_reset(void); +void top_done(void); +unsigned int top_getreg(int reg); +unsigned int top_getpc(void); +int top_run(int cycles, int intr_after_cycles); +int top_setbreakpoint(int bp, unsigned int pc); + + +#endif Index: sim_verilator/sram4.v =================================================================== --- sim_verilator/sram4.v (nonexistent) +++ sim_verilator/sram4.v (revision 9) @@ -0,0 +1,100 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module sram4 +( + clk_i, + address_i, + data_i, + data_o, + wr_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] SRAM_ADDR_WIDTH = 14; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input [31:0] address_i /*verilator public*/; +input [31:0] data_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [3:0] wr_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +wire [31:0] address; +wire [31:0] data_o; + +//----------------------------------------------------------------- +// Implementation +//----------------------------------------------------------------- +assign address = {2'b00, address_i[31:2]}; + +generate +begin : sram_gen +genvar i; +for (i=0;i<4;i=i+1) + begin :sram_loop + sram + #( + .WIDTH(8), + .SIZE(SRAM_ADDR_WIDTH) + ) + u1_bram + ( + .clk_i(clk_i), + .dat_o(data_o[(((i + 1) * 8) - 1):(i * 8)]), + .dat_i(data_i[(((i + 1) * 8) - 1):(i * 8)]), + .adr_i(address[(SRAM_ADDR_WIDTH - 1):0]), + .wr_i(wr_i[i]) + ); + end +end +endgenerate + +endmodule Index: sim_verilator/Readme.txt =================================================================== --- sim_verilator/Readme.txt (nonexistent) +++ sim_verilator/Readme.txt (revision 9) @@ -0,0 +1,36 @@ +MPX RTL Simulation +------------------ + +This directory contains the Verilator RTL simulation model. + +Requirements: +- verilator-3.831 or newer +- GTKWave + +To run an application binary: + make TEST_IMAGE=test_image.bin + +Where test_image.bin is your compiled source which has a starting address of 0x10000000. + +To generate (GTKwave) waveforms; + make TEST_IMAGE=test_image.bin TRACE=1 + +To view waveform with GTKWave: + make view + +Test image expected output +-------------------------- + +Test: +1. Initialised data +2. Multiply +3. Divide +4. Shift left +5. Shift right +6. Shift right arithmetic +7. Signed comparision +8. Word access +9. Byte access +10. SYSCALL return PC check +11. Comparision +Exit Index: sim_verilator/makefile =================================================================== --- sim_verilator/makefile (nonexistent) +++ sim_verilator/makefile (revision 9) @@ -0,0 +1,49 @@ + +# Default binary to load & run +TEST_IMAGE ?= test_image.bin +SIMARGS ?= + +# Default core to simulate +RTL_CORE ?= mpx +CORE_FILENAME ?= mpx.v + +# Waveform trace disabled by default +TRACE?= 0 + +# Top module (without .v extension) +TOP_MODULE = top + +# Additional modules which can't be auto found +ADDITIONAL_MODULES = ../$(RTL_CORE)/$(CORE_FILENAME) + +# CPP Source Files +SRC_CPP = main.cpp top.cpp + +# Source directories +INC_DIRS = -I../$(RTL_CORE) -I../soc -I../peripheral + +# Build directory +BUILD_DIR = build + +VERILATOR_OPTS = + +ifeq ($(TRACE),1) + VERILATOR_OPTS += --trace +endif + +all: run + +compile: clean + verilator --cc $(TOP_MODULE).v $(ADDITIONAL_MODULES) $(SRC_CPP) $(INC_DIRS) +define+CONF_MPX_TARGET_SIM+ --exe -Mdir $(BUILD_DIR) $(VERILATOR_OPTS) + make -j -f V$(TOP_MODULE).mk -C $(BUILD_DIR) + +run: compile + ./$(BUILD_DIR)/V$(TOP_MODULE) -f $(TEST_IMAGE) $(SIMARGS) + +ifeq ($(TRACE),1) +view: + gtkwave wave_dump.vcd gtksettings.sav +endif + +clean : + -rm -rf $(BUILD_DIR) Index: mpx/mpx_regfile_xil.v =================================================================== --- mpx/mpx_regfile_xil.v (nonexistent) +++ mpx/mpx_regfile_xil.v (revision 9) @@ -0,0 +1,142 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module mpx_regfile_xil +( + clk_i, + rst_i, + en_i, + wr_i, + rs_i, + rt_i, + rd_i, + reg_rs_o, + reg_rt_o, + reg_rd_i +); + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input en_i /*verilator public*/; +input wr_i /*verilator public*/; +input [4:0] rs_i /*verilator public*/; +input [4:0] rt_i /*verilator public*/; +input [4:0] rd_i /*verilator public*/; +output [31:0] reg_rs_o /*verilator public*/; +output [31:0] reg_rt_o /*verilator public*/; +input [31:0] reg_rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [4:0] addr_write; +wire [31:0] data_out1; +wire [31:0] data_out2; +reg write_enable; +wire [31:0] data_out1a; +wire [31:0] data_out1b; +wire [31:0] data_out2a; +wire [31:0] data_out2b; +wire wea; +wire web; + +reg [31:0] reg_rs_o; +reg [31:0] reg_rt_o; + +//----------------------------------------------------------------- +// Async Read Process +//----------------------------------------------------------------- +always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i) +begin + // Read Rs + if (rs_i == 5'b00000) + reg_rs_o <= 32'h00000000; + else + reg_rs_o <= data_out1; + + // Read Rt + if (rt_i == 5'b00000) + reg_rt_o <= 32'h00000000; + else + reg_rt_o <= data_out2; + + // Write enabled? + addr_write <= rd_i[4:0]; + if ((rd_i != 5'b00000) & (wr_i == 1'b1)) + write_enable <= 1'b1; + else + write_enable <= 1'b0; +end + +//----------------------------------------------------------------- +// Register File (using RAM16X1D ) +//----------------------------------------------------------------- +generate +begin + genvar i; + for (i=0;i<32;i=i+1) + begin : reg_loop + RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1a[i]), .SPO(/* open */)); + RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1b[i]), .SPO(/* open */)); + RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2a[i]), .SPO(/* open */)); + RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2b[i]), .SPO(/* open */)); + end +end +endgenerate + +//----------------------------------------------------------------- +// Combinatorial Assignments +//----------------------------------------------------------------- +assign data_out1 = (rs_i[4] == 1'b0) ? data_out1a : data_out1b; +assign data_out2 = (rt_i[4] == 1'b0) ? data_out2a : data_out2b; +assign wea = (write_enable & ~ (addr_write[4])); +assign web = (write_enable & addr_write[4]); + +endmodule Index: mpx/mpx_funcs.v =================================================================== --- mpx/mpx_funcs.v (nonexistent) +++ mpx/mpx_funcs.v (revision 9) @@ -0,0 +1,301 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// shift_left: Shift left by specified amount +// Inputs: x = input, y = shift amount +// Return: x << y +//----------------------------------------------------------------- +function [31:0] shift_left; + input [31:0] x; + input [31:0] y; + reg [31:0] shift1l; + reg [31:0] shift2l; + reg [31:0] shift4l; + reg [31:0] shift8l; + reg [31:0] shift16l; +begin + if (y[0] == 1'b1) + shift1l = {x[30:0],1'b0}; + else + shift1l = x; + + if (y[1] == 1'b1) + shift2l = {shift1l[29:0],2'b00}; + else + shift2l = shift1l; + + if (y[2] == 1'b1) + shift4l = {shift2l[27:0],4'b0000}; + else + shift4l = shift2l; + + if (y[3] == 1'b1) + shift8l = {shift4l[23:0],8'b00000000}; + else + shift8l = shift4l; + + if (y[4] == 1'b1) + shift16l = {shift8l[15:0],16'b0000000000000000}; + else + shift16l = shift8l; + + shift_left = shift16l; +end +endfunction + +//----------------------------------------------------------------- +// shift_right: Shift right by specified amount +// Inputs: x = input, y = shift amount +// Return: x >> y +//----------------------------------------------------------------- +function [31:0] shift_right; + input [31:0] x; + input [31:0] y; + reg [31:16] fill; + reg [31:0] shift1r; + reg [31:0] shift2r; + reg [31:0] shift4r; + reg [31:0] shift8r; + reg [31:0] shift16r; +begin + fill = 16'b0000000000000000; + if (y[0] == 1'b1) + shift1r = {fill[31],x[31:1]}; + else + shift1r = x; + + if (y[1] == 1'b1) + shift2r = {fill[31:30],shift1r[31:2]}; + else + shift2r = shift1r; + + if (y[2] == 1'b1) + shift4r = {fill[31:28],shift2r[31:4]}; + else + shift4r = shift2r; + + if (y[3] == 1'b1) + shift8r = {fill[31:24],shift4r[31:8]}; + else + shift8r = shift4r; + + if (y[4] == 1'b1) + shift16r = {fill[31:16],shift8r[31:16]}; + else + shift16r = shift8r; + + shift_right = shift16r; +end +endfunction + +//----------------------------------------------------------------- +// shift_right_arith: Shift right by specified amount (sign extend) +// Inputs: x = input, y = shift amount +// Return: (int)x >> y +//----------------------------------------------------------------- +function [31:0] shift_right_arith; + input [31:0] x; + input [31:0] y; + reg [31:16] fill; + reg [31:0] shift1r; + reg [31:0] shift2r; + reg [31:0] shift4r; + reg [31:0] shift8r; + reg [31:0] shift16r; +begin + if (x[31] == 1'b1) + fill = 16'b1111111111111111; + else + fill = 16'b0000000000000000; + + if (y[0] == 1'b1) + shift1r = {fill[31],x[31:1]}; + else + shift1r = x; + + if (y[1] == 1'b1) + shift2r = {fill[31:30],shift1r[31:2]}; + else + shift2r = shift1r; + + if (y[2] == 1'b1) + shift4r = {fill[31:28],shift2r[31:4]}; + else + shift4r = shift2r; + + if (y[3] == 1'b1) + shift8r = {fill[31:24],shift4r[31:8]}; + else + shift8r = shift4r; + + if (y[4] == 1'b1) + shift16r = {fill[31:16],shift8r[31:16]}; + else + shift16r = shift8r; + + shift_right_arith = shift16r; +end +endfunction + +//----------------------------------------------------------------- +// less_than_signed: Less than operator (signed) +// Inputs: x = left operand, y = right operand +// Return: (int)x < (int)y +//----------------------------------------------------------------- +function [0:0] less_than_signed; + input [31:0] x; + input [31:0] y; + reg [31:0] v; +begin + v = (x - y); + if (x[31] != y[31]) + less_than_signed = x[31]; + else + less_than_signed = v[31]; +end +endfunction + +//----------------------------------------------------------------- +// less_than: Less than operator (unsigned) +// Inputs: x = left operand, y = right operand +// Return: x < y +//----------------------------------------------------------------- +function [0:0] less_than; + input [31:0] x; + input [31:0] y; +begin + if (x < y) + less_than = 1'b1; + else + less_than = 1'b0; +end +endfunction + +//----------------------------------------------------------------- +// sign_extend_imm16: Extend 16-bit signed value to 32-bit signed. +// Inputs: x = operand +// Return: (int)((short)x) +//----------------------------------------------------------------- +function [31:0] sign_extend_imm16; + input [15:0] x; + reg [31:0] y; +begin + if (x[15] == 1'b0) + y[31:16] = 16'b0000000000000000; + else + y[31:16] = 16'b1111111111111111; + + y[15:0] = x; + sign_extend_imm16 = y; +end +endfunction + +//----------------------------------------------------------------- +// extend_imm16: Extend 16-bit unsigned value to 32-bit unsigned. +// Inputs: x = operand +// Return: (unsigned int)x +//----------------------------------------------------------------- +function [31:0] extend_imm16; + input [15:0] x; +begin + extend_imm16 = {16'h0000,x}; +end +endfunction + +//----------------------------------------------------------------- +// less_than_zero: Is signed value less than 0? +// Inputs: x = operand +// Return: ((int)x) < 0 +//----------------------------------------------------------------- +function [0:0] less_than_zero; + input [31:0] x; +begin + if ((x != 32'h00000000) & (x[31] == 1'b1)) + less_than_zero = 1'b1; + else + less_than_zero = 1'b0; +end +endfunction + +//----------------------------------------------------------------- +// less_than_equal_zero: Is signed value less than or equal to 0? +// Inputs: x = operand +// Return: ((int)x) <= 0 +//----------------------------------------------------------------- +function [0:0] less_than_equal_zero; + input [31:0] x; +begin + if ((x == 32'h00000000) | (x[31] == 1'b1)) + less_than_equal_zero = 1'b1; + else + less_than_equal_zero = 1'b0; +end +endfunction + +//----------------------------------------------------------------- +// more_than_equal_zero: Is signed value more than or equal to 0? +// Inputs: x = operand +// Return: ((int)x) >= 0 +//----------------------------------------------------------------- +function [0:0] more_than_equal_zero; + input [31:0] x; +begin + if ((x == 32'h00000000) | (x[31] == 1'b0)) + more_than_equal_zero = 1'b1; + else + more_than_equal_zero = 1'b0; +end +endfunction + +//----------------------------------------------------------------- +// more_than_equal_zero: Is signed value more than 0? +// Inputs: x = operand +// Return: ((int)x) > 0 +//----------------------------------------------------------------- +function [0:0] more_than_zero; + input [31:0] x; +begin + if (((x != 32'h00000000) & (x[31] == 1'b0))) + more_than_zero = 1'b1; + else + more_than_zero = 1'b0; +end +endfunction Index: mpx/mpx.v =================================================================== --- mpx/mpx.v (nonexistent) +++ mpx/mpx.v (revision 9) @@ -0,0 +1,1329 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "mpx_defs.v" + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module cpu +( + // General + clk_i, + rst_i, + en_i, + intr_i, + fault_o, + break_o, + + // Data Memory + mem_addr_o, + mem_data_out_o, + mem_data_in_i, + mem_wr_o, + mem_rd_o, + mem_pause_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] BOOT_VECTOR = 32'h00000000; +parameter [31:0] ISR_VECTOR = 32'h0000003C; +parameter REGISTER_FILE_TYPE = "SIMULATION"; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +// General +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input en_i /*verilator public*/; +input intr_i /*verilator public*/; +output fault_o /*verilator public*/; +output break_o /*verilator public*/; + +// Data Memory +output [31:0] mem_addr_o /*verilator public*/; +output [31:0] mem_data_out_o /*verilator public*/; +input [31:0] mem_data_in_i /*verilator public*/; +output [3:0] mem_wr_o /*verilator public*/; +output mem_rd_o /*verilator public*/; +input mem_pause_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- + +// Other registers +reg [31:0] r_pc; +reg [31:0] r_epc; +reg [31:0] r_status; +reg [3:0] r_cause; +reg [31:0] r_fault_info; +reg [31:0] r_isr_vector; +reg [31:0] r_lo; +reg [31:0] r_hi; + +// Register file access +wire [4:0] r_rt; +wire [4:0] r_rd; +reg [4:0] r_rd_wb; +wire [4:0] r_rs; +wire [31:0] r_reg_rt; +wire [31:0] r_reg_rs; +reg [31:0] r_reg_result; +reg [31:0] r_reg_rd_out; +reg r_writeback; + +// Pipeline registers +reg [31:0] r_opcode; +reg [31:0] d_opcode; +reg r_branch_dslot; +reg [4:0] d_rd_wb; +reg [4:0] d2_rd_wb; +reg [31:0] d_reg_result; +reg c_load_op; +reg [31:0] c_mem_forward; +reg d_mem_access; + +// Memory +reg [31:0] mem_addr; +wire [31:0] mem_addr_mux; +reg [31:0] mem_addr_last; +reg [31:0] mem_data_out; +wire [31:0] mem_data_in; +reg [3:0] mem_wr; +reg mem_rd; +reg [1:0] mem_offset; +reg [1:0] d_mem_offset; +reg r_mem_access; +reg [31:0] r_pc_branch; +reg r_take_intr; +reg d_take_intr; +reg r_flush_next; + +// ALU +reg [31:0] alu_a; +reg [31:0] alu_b; +wire [31:0] alu_result; +reg [31:0] d_alu_result; +reg [3:0] alu_func; +reg [3:0] d_alu_func; + +reg fault_o; +reg break_o; +wire [31:0] mem_addr_o; +wire [31:0] mem_data_out_o; +wire [3:0] mem_wr_o; +wire mem_rd_o; + +//----------------------------------------------------------------- +// Instantiation +//----------------------------------------------------------------- + +// ALU +mpx_alu alu +( + .input_a(alu_a), + .input_b(alu_b), + .func(alu_func), + .result(alu_result) +); + +// Register file +generate +if (REGISTER_FILE_TYPE == "XILINX") +begin + mpx_regfile_xil + reg_bank + ( + // Clocking + .clk_i(clk_i), + .rst_i(rst_i), + .en_i(1'b1), + .wr_i(r_writeback), + + // Tri-port + .rs_i(r_rs), + .rt_i(r_rt), + .rd_i(d2_rd_wb), + .reg_rs_o(r_reg_rs), + .reg_rt_o(r_reg_rt), + .reg_rd_i(r_reg_rd_out) + ); +end +else +begin + mpx_regfile_sim + reg_bank + ( + // Clocking + .clk_i(clk_i), + .rst_i(rst_i), + .en_i(1'b1), + .wr_i(r_writeback), + + // Tri-port + .rs_i(r_rs), + .rt_i(r_rt), + .rd_i(d2_rd_wb), + .reg_rs_o(r_reg_rs), + .reg_rt_o(r_reg_rt), + .reg_rd_i(r_reg_rd_out) + ); +end +endgenerate + +//------------------------------------------------------------------- +// Pipeline +//------------------------------------------------------------------- +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + d_opcode <= 32'h00000000; + d_rd_wb <= 5'b00000; + d2_rd_wb <= 5'b00000; + d_reg_result <= 32'h00000000; + d_alu_result <= 32'h00000000; + d_alu_func <= 4'b0000; + d_mem_offset <= 2'b00; + d_mem_access <= 1'b0; + d_take_intr <= 1'b0; + mem_addr_last <= 32'h00000000; + end + else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) + begin + d_opcode <= r_opcode; + d_rd_wb <= r_rd_wb; + d2_rd_wb <= d_rd_wb; + d_reg_result <= r_reg_result; + d_alu_result <= alu_result; + d_alu_func <= alu_func; + d_mem_offset <= mem_offset; + d_mem_access <= r_mem_access; + d_take_intr <= r_take_intr; + + if (r_mem_access == 1'b1) + mem_addr_last <= mem_addr; + else + mem_addr_last <= r_pc; + end +end + +//------------------------------------------------------------------- +// Execute +//------------------------------------------------------------------- +reg [7:0] v_inst; +reg [4:0] v_rs; +reg [4:0] v_rt; +reg [4:0] v_rd; +reg [4:0] v_re; +reg [7:0] v_func; +reg [15:0] v_imm; +reg [31:0] v_imm_uint32; +reg [31:0] v_imm_int32; +reg [25:0] v_target; + +reg [31:0] v_reg_rs; +reg [31:0] v_reg_rt; + +reg [31:0] v_pc; +reg [31:0] v_pc_next; + +reg [31:0] v_reg_result; + +reg [31:0] v_offset; + +reg v_exception; +reg v_emulate; + +reg v_branch; +reg v_jmp; +reg v_write_rt; +reg v_write_rd; + +reg [31:0] v_mem_addr; +reg v_mem_access; +reg [31:0] v_mem_data_in; + +reg [31:0] v_status; + +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + + // Default to no ALU operation + alu_func <= `ALU_NONE; + + r_rd_wb <= 5'b00000; + r_pc <= BOOT_VECTOR; + + r_epc <= 32'h00000000; + r_status <= 32'h00000000; + r_cause <= `EXCEPTION_NONE; + r_fault_info <= 32'h00000000; + r_lo <= 32'h00000000; + r_hi <= 32'h00000000; + r_branch_dslot <= 1'b0; + r_pc_branch <= 32'h00000000; + r_take_intr <= 1'b0; + + r_opcode <= 32'h00000000; + + mem_addr <= 32'h00000000; + mem_data_out <= 32'h00000000; + mem_rd <= 1'b0; + mem_wr <= 4'b0000; + mem_offset <= 2'b00; + + // Default ISR vector address + r_isr_vector <= ISR_VECTOR; + + fault_o <= 1'b0; + break_o <= 1'b0; + r_mem_access <= 1'b0; + + // Flush first instruction execute to allow fetch to occur + r_flush_next <= 1'b1; + + end + else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) + begin + + mem_rd <= 1'b0; + mem_wr <= 4'b0000; + + break_o <= 1'b0; + + v_exception = 1'b0; + v_emulate = 1'b0; + v_branch = 1'b0; + v_jmp = 1'b0; + v_write_rt = 1'b0; + v_write_rd = 1'b0; + v_status = r_status; + v_mem_access = 1'b0; + v_mem_data_in = mem_data_in_i; + + // If memory access was done, check for no instruction to process. + // As memory access has a 1 cycle latency, invalid mem_data_in_i is + // aligned with d_mem_access not r_mem_access. + if (d_mem_access == 1'b1) + v_mem_data_in = `OPCODE_INST_BUBBLE; + + // Flush pipeline due to an exception/interrupt? + // NOTE: When d_take_intr=1, mem_data_in_i will be invalid for one more cycle + if ((r_take_intr == 1'b1) || (d_take_intr == 1'b1)) + v_mem_data_in = `OPCODE_INST_BUBBLE; + + // Flush next instruction for some reason + if (r_flush_next) + begin + v_mem_data_in = `OPCODE_INST_BUBBLE; + end + + r_take_intr <= 1'b0; + r_flush_next <= 1'b0; + + // Decode opcode + r_opcode <= v_mem_data_in; + v_inst = {2'b00,v_mem_data_in[31:26]}; + v_rs = v_mem_data_in[25:21]; + v_rt = v_mem_data_in[20:16]; + v_rd = v_mem_data_in[15:11]; + v_re = v_mem_data_in[10:6]; + v_func = {2'b00,v_mem_data_in[5:0]}; + v_imm = v_mem_data_in[15:0]; + v_target = v_mem_data_in[25:0]; + + // Signed & unsigned imm -> 32-bits + v_imm_int32 = sign_extend_imm16(v_imm); + v_imm_uint32 = extend_imm16(v_imm); + + // Load register[rs] + v_reg_rs = r_reg_rs; + + // Load register[rt] + v_reg_rt = r_reg_rt; + + // Register[rs] hazard detection & forwarding logic + // (higher priority = latest results!) + if (v_rs != 5'b00000) + begin + if (v_rs == r_rd_wb) + begin + // Result from memory / other + if (alu_func == `ALU_NONE) + begin + v_reg_rs = r_reg_result; + end + // Result from ALU + else + begin + v_reg_rs = alu_result; + end + end + else if (v_rs == d_rd_wb) + begin + // Result from memory load? + if (c_load_op == 1'b1) + begin + v_reg_rs = c_mem_forward; + end + // Result from memory / other + else if (d_alu_func == `ALU_NONE) + begin + v_reg_rs = d_reg_result; + end + // Result from ALU + else + begin + v_reg_rs = d_alu_result; + end + end + else if (v_rs == d2_rd_wb) + begin + v_reg_rs = r_reg_rd_out; + end + end + + // Register[rt] hazard detection & forwarding logic + // (higher priority = latest results!) + if (v_rt != 5'b00000) + begin + if (v_rt == r_rd_wb) + begin + // Result from memory / other + if (alu_func == `ALU_NONE) + begin + v_reg_rt = r_reg_result; + end + // Result from ALU + else + begin + v_reg_rt = alu_result; + end + end + else if (v_rt == d_rd_wb) + begin + // Result from memory load? + if (c_load_op == 1'b1) + begin + v_reg_rt = c_mem_forward; + end + // Result from non ALU function + else if (d_alu_func == `ALU_NONE) + begin + v_reg_rt = d_reg_result; + end + // Result from ALU + else + begin + v_reg_rt = d_alu_result; + end + + end + else if (v_rt == d2_rd_wb) + begin + v_reg_rt = r_reg_rd_out; + end + end + + // Zero result + v_reg_result = 32'h00000000; + + // Update PC to next value + v_pc = (r_pc + 4); + + // Default to no ALU operation + alu_func <= `ALU_NONE; + + // Default target is r_rd + r_rd_wb <= r_rd; + + // Reset branch delay slot status + r_branch_dslot <= 1'b0; + + // Execute instruction + case (v_inst) + 8'h00 : + case (v_func) + `INSTR_R_SLL: + begin + alu_func <= `ALU_SHIFTL; + alu_a <= v_reg_rt; + alu_b <= {27'b0, v_re}; + v_write_rd = 1'b1; + end + + `INSTR_R_SRL: + begin + alu_func <= `ALU_SHIFTR; + alu_a <= v_reg_rt; + alu_b <= {27'b0, v_re}; + v_write_rd = 1'b1; + end + + `INSTR_R_SRA: + begin + alu_func <= `ALU_SHIRTR_ARITH; + alu_a <= v_reg_rt; + alu_b <= {27'b0, v_re}; + v_write_rd = 1'b1; + end + + `INSTR_R_SLLV: + begin + alu_func <= `ALU_SHIFTL; + alu_a <= v_reg_rt; + alu_b <= v_reg_rs; + v_write_rd = 1'b1; + end + + `INSTR_R_SRLV: + begin + alu_func <= `ALU_SHIFTR; + alu_a <= v_reg_rt; + alu_b <= v_reg_rs; + v_write_rd = 1'b1; + end + + `INSTR_R_SRAV: + begin + alu_func <= `ALU_SHIRTR_ARITH; + alu_a <= v_reg_rt; + alu_b <= v_reg_rs; + v_write_rd = 1'b1; + end + + `INSTR_R_JR: + begin + v_pc = v_reg_rs; + v_jmp = 1'b1; + end + + `INSTR_R_JALR: + begin + v_reg_result = v_pc; + v_write_rd = 1'b1; + v_pc = v_reg_rs; + v_jmp = 1'b1; + end + + `INSTR_R_SYSCALL: + begin + v_exception = 1'b1; + r_cause <= `EXCEPTION_SYSCALL; + end + + `INSTR_R_BREAK: + begin + v_exception = 1'b1; + break_o <= 1'b1; + r_cause <= `EXCEPTION_BREAK; + end + + `INSTR_R_MFHI: + begin + v_reg_result = r_hi; + v_write_rd = 1'b1; + end + + `INSTR_R_MTHI: + begin + r_hi <= v_reg_rs; + end + + `INSTR_R_MFLO: + begin + v_reg_result = r_lo; + v_write_rd = 1'b1; + end + + `INSTR_R_MTLO: + begin + r_lo <= v_reg_rs; + end + + `INSTR_R_MULT: + begin + v_exception = 1'b1; + v_emulate = 1'b1; + r_cause <= `EXCEPTION_MULT; + end + + `INSTR_R_MULTU: + begin + v_exception = 1'b1; + v_emulate = 1'b1; + r_cause <= `EXCEPTION_UMULT; + end + + `INSTR_R_DIV: + begin + v_exception = 1'b1; + v_emulate = 1'b1; + r_cause <= `EXCEPTION_DIV; + end + + `INSTR_R_DIVU: + begin + v_exception = 1'b1; + v_emulate = 1'b1; + r_cause <= `EXCEPTION_UDIV; + end + + `INSTR_R_ADD: + begin + alu_func <= `ALU_ADD; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_ADDU: + begin + alu_func <= `ALU_ADD; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_SUB: + begin + alu_func <= `ALU_SUB; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_SUBU: + begin + alu_func <= `ALU_SUB; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_AND: + begin + alu_func <= `ALU_AND; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_OR: + begin + alu_func <= `ALU_OR; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_XOR: + begin + alu_func <= `ALU_XOR; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_NOR: + begin + alu_func <= `ALU_NOR; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_SLT: + begin + alu_func <= `ALU_SLT; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + + `INSTR_R_SLTU: + begin + alu_func <= `ALU_SLTU; + alu_a <= v_reg_rs; + alu_b <= v_reg_rt; + v_write_rd = 1'b1; + end + default : + begin + fault_o <= 1'b1; + v_exception = 1'b1; + r_cause <= `EXCEPTION_FAULT; + r_fault_info <= v_mem_data_in; + end + endcase + + // REGIMM + `INSTR_I_REGIMM : + case (v_rt) + `INSTR_I_COND_BLTZAL : // BLTZAL [ branch = ((int)v_reg_rs < 0) ] + begin + v_reg_result = v_pc; + v_write_rd = 1'b1; + r_rd_wb <= 5'b11111; // Write to $ra + v_branch = less_than_zero(v_reg_rs); + end + + `INSTR_I_COND_BLTZ : // BLTZ [ branch = ((int)v_reg_rs < 0) ] + begin + v_branch = less_than_zero(v_reg_rs); + end + + `INSTR_I_COND_BGEZAL : // BGEZAL [ branch = ((int)v_reg_rs >= 0) ] + begin + v_reg_result = v_pc; + v_write_rd = 1'b1; + r_rd_wb <= 5'b11111; // Write to $ra + v_branch = more_than_equal_zero(v_reg_rs); + end + + `INSTR_I_COND_BGEZ : // BGEZ [ branch = ((int)v_reg_rs >= 0) ] + begin + v_branch = more_than_equal_zero(v_reg_rs); + end + + default : + begin + fault_o <= 1'b1; + v_exception = 1'b1; + r_cause <= `EXCEPTION_FAULT; + r_fault_info <= v_mem_data_in; + end + endcase + + `INSTR_J_JAL: + begin + v_reg_result = v_pc; + v_write_rd = 1'b1; + r_rd_wb <= 5'b11111; // Write to $ra + v_pc = {{v_pc[31:28],v_target[25:0]},2'b00}; + v_jmp = 1'b1; + end + + `INSTR_J_J: + begin + v_pc = {{v_pc[31:28],v_target[25:0]},2'b00}; + v_jmp = 1'b1; + end + + `INSTR_J_BEQ: + begin + if (v_reg_rs == v_reg_rt) + v_branch = 1'b1; + end + + `INSTR_J_BNE: + begin + if (v_reg_rs != v_reg_rt) + v_branch = 1'b1; + end + + `INSTR_J_BLEZ : // BLEZ [ branch = (int)v_reg_rs <= 0 ] + v_branch = less_than_equal_zero(v_reg_rs); + + `INSTR_J_BGTZ : // BGTZ [ branch = (int)v_reg_rs > 0 ] + v_branch = more_than_zero(v_reg_rs); + + `INSTR_I_ADDI: + begin + alu_func <= `ALU_ADD; + alu_a <= v_reg_rs; + alu_b <= v_imm_int32; + v_write_rt = 1'b1; + end + + `INSTR_I_ADDIU: + begin + alu_func <= `ALU_ADD; + alu_a <= v_reg_rs; + alu_b <= v_imm_int32; + v_write_rt = 1'b1; + end + + `INSTR_I_SLTI: + begin + alu_func <= `ALU_SLT; + alu_a <= v_reg_rs; + alu_b <= v_imm_int32; + v_write_rt = 1'b1; + end + + `INSTR_I_SLTIU: + begin + alu_func <= `ALU_SLTU; + alu_a <= v_reg_rs; + alu_b <= v_imm_int32; + v_write_rt = 1'b1; + end + + `INSTR_I_ANDI: + begin + alu_func <= `ALU_AND; + alu_a <= v_reg_rs; + alu_b <= v_imm_uint32; + v_write_rt = 1'b1; + end + + `INSTR_I_ORI: + begin + alu_func <= `ALU_OR; + alu_a <= v_reg_rs; + alu_b <= v_imm_uint32; + v_write_rt = 1'b1; + end + + `INSTR_I_XORI: + begin + alu_func <= `ALU_XOR; + alu_a <= v_reg_rs; + alu_b <= v_imm_uint32; + v_write_rt = 1'b1; + end + + `INSTR_I_LUI: + begin + v_reg_result = {v_imm,16'h0000}; + v_write_rt = 1'b1; + end + + `INSTR_COP0: + begin + + // Move from CP0 + if (v_rs[2] == 1'b0) + case (v_rd) + `COP0_STATUS: + begin + v_reg_result = r_status; + v_write_rt = 1'b1; + end + + `COP0_CAUSE: + begin + v_reg_result = {28'h0000000,r_cause}; + v_write_rt = 1'b1; + end + + `COP0_EPC: + begin + v_reg_result = r_epc; + v_write_rt = 1'b1; + end + + `COP0_ISR_VECT: + begin + v_reg_result = r_isr_vector; + v_write_rt = 1'b1; + end + + `COP0_FAULT_INFO: + begin + v_reg_result = r_fault_info; + v_write_rt = 1'b1; + end + + default : + begin + end + + endcase + + // Move to CP0 + else + case (v_rd) + `COP0_STATUS: + begin + r_status <= v_reg_rt; + v_status = v_reg_rt; + end + + `COP0_CAUSE: + r_cause <= v_reg_rt[3:0]; + + `COP0_EPC: + r_epc <= v_reg_rt; + + `COP0_ISR_VECT: + r_isr_vector <= v_reg_rt; + + `COP0_FAULT_INFO: + r_fault_info <= v_reg_rt; + + default : + begin + end + endcase + end + + // Memory load / store instructions + + `INSTR_I_LB, `INSTR_I_LH, `INSTR_I_LW, `INSTR_I_LBU, `INSTR_I_LHU : + begin + v_mem_addr = (v_reg_rs + v_imm_int32); + mem_addr <= {v_mem_addr[31:2],2'b00}; + mem_data_out <= 32'h00000000; + mem_rd <= 1'b1; + mem_offset <= v_mem_addr[1:0]; + v_write_rt = 1'b1; + v_mem_access = 1'b1; + end + + `INSTR_I_SB: + begin + v_mem_addr = (v_reg_rs + v_imm_int32); + mem_addr <= {v_mem_addr[31:2],2'b00}; + case (v_mem_addr[1:0]) + 2'b00 : + begin + mem_data_out <= {v_reg_rt[7:0],24'h000000}; + mem_wr <= 4'b1000; + v_mem_access = 1'b1; + end + 2'b01 : + begin + mem_data_out <= {{8'h00,v_reg_rt[7:0]},16'h0000}; + mem_wr <= 4'b0100; + v_mem_access = 1'b1; + end + 2'b10 : + begin + mem_data_out <= {{16'h0000,v_reg_rt[7:0]},8'h00}; + mem_wr <= 4'b0010; + v_mem_access = 1'b1; + end + 2'b11 : + begin + mem_data_out <= {24'h000000,v_reg_rt[7:0]}; + mem_wr <= 4'b0001; + v_mem_access = 1'b1; + end + default : + begin + mem_data_out <= 32'h00000000; + mem_wr <= 4'b0000; + end + endcase + end + + `INSTR_I_SH: + begin + v_mem_addr = (v_reg_rs + v_imm_int32); + mem_addr <= {v_mem_addr[31:2],2'b00}; + case (v_mem_addr[1:0]) + 2'b00 : + begin + mem_data_out <= {v_reg_rt[15:0],16'h0000}; + mem_wr <= 4'b1100; + v_mem_access = 1'b1; + end + 2'b10 : + begin + mem_data_out <= {16'h0000,v_reg_rt[15:0]}; + mem_wr <= 4'b0011; + v_mem_access = 1'b1; + end + default : + begin + mem_data_out <= 32'h00000000; + mem_wr <= 4'b0000; + end + endcase + end + + `INSTR_I_SW: + begin + v_mem_addr = (v_reg_rs + v_imm_int32); + mem_addr <= {v_mem_addr[31:2],2'b00}; + mem_data_out <= v_reg_rt; + mem_wr <= 4'b1111; + v_mem_access = 1'b1; + end + + `INSTR_BUBBLE: + begin + end + + default : + begin + fault_o <= 1'b1; + v_exception = 1'b1; + r_cause <= `EXCEPTION_FAULT; + r_fault_info <= v_mem_data_in; + end + endcase + + // Handle branches + if (v_branch == 1'b1) + begin + v_offset = v_imm_int32; + v_offset = {v_offset[29:0],2'b00}; + v_pc = (r_pc + v_offset); + + // Next instruction is branch delay slot + r_branch_dslot <= 1'b1; + r_pc_branch <= v_pc; + end + // If not branching, handle interrupts / exceptions + else if ((v_jmp == 1'b0) && (v_inst != `INSTR_BUBBLE)) + begin + + // Exception (Fault/Mult/Div/Syscall/Break) + if (v_exception == 1'b1) + begin + + // Schedule interrupt after pipeline flush + r_take_intr <= 1'b1; + + // Record instruction to continue from + r_epc <= r_pc; + + // Disable interrupts by shifting left status register + r_status <= {v_status[30:0],1'b0}; + end + // External interrupt (and not handling an exception, branch or bubble)? + // NOTE: d_mem_access & r_branch_dslot are exclusive as this would result in a bubble + else if ((intr_i == 1'b1) && (v_status[0] == 1'b1)) + begin + // Schedule interrupt after pipeline flush + r_take_intr <= 1'b1; + + // Interrupt src is external + r_cause <= `EXCEPTION_EXTINT; + + // Record instruction to continue from + r_epc <= r_pc; + + // Disable interrupts by shifting left status register + r_status <= {v_status[30:0],1'b0}; + end + end + // Handle jumps + else if (v_jmp == 1'b1) + begin + // Next instruction is branch delay slot + r_branch_dslot <= 1'b1; + r_pc_branch <= v_pc; + end + + // Update to new PC value only if last cycle wasn't a memory access + if (r_mem_access == 1'b0) + r_pc <= v_pc; + + // Stall in branch delay slot due to mem access? + if ((d_mem_access == 1'b1) && (r_branch_dslot == 1'b1)) + r_pc <= r_pc_branch; + + // If pipeline flushed due to interrupt request + if (r_take_intr == 1'b1) + begin + // Jump to ISR + r_pc <= r_isr_vector; + end + + // Update other registers with variable values + r_reg_result <= v_reg_result; + r_mem_access <= v_mem_access; + + // Target is Register[rt] + if (v_write_rt == 1'b1) + begin + // Store new value to register[rt] instead of register[rd] + r_rd_wb <= r_rt; + end + // No writeback required? + else if ((v_write_rt == 1'b0) && (v_write_rd == 1'b0)) + begin + // Target register is $0 which is read-only + r_rd_wb <= 5'b00000; + end + end +end + +//------------------------------------------------------------------- +// Writeback +//------------------------------------------------------------------- +reg [31:0] wb_v_reg_result; +reg [7:0] wb_v_inst; + +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + r_writeback <= 1'b1; + end + else + begin + r_writeback <= 1'b0; + + if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) + begin + + wb_v_reg_result = d_reg_result; + + // Handle delayed result instructions + wb_v_inst = {2'b00,d_opcode[31:26]}; + case (wb_v_inst) + `INSTR_I_LB: + begin + case (d_mem_offset) + 2'b00 : + wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; + 2'b01 : + wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; + 2'b10 : + wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; + 2'b11 : + wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; + default : + wb_v_reg_result = 32'h00000000; + endcase + + // Sign extend LB + if (wb_v_reg_result[7] == 1'b1) + wb_v_reg_result = {24'hFFFFFF,wb_v_reg_result[7:0]}; + end + + `INSTR_I_LBU: + case (d_mem_offset) + 2'b00 : + wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; + 2'b01 : + wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; + 2'b10 : + wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; + 2'b11 : + wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; + default : + wb_v_reg_result = 32'h00000000; + endcase + + `INSTR_I_LH: + begin + case (d_mem_offset) + 2'b00 : + wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; + 2'b10 : + wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; + default : + wb_v_reg_result = 32'h00000000; + endcase + + // Sign extend LH + if (wb_v_reg_result[15] == 1'b1) + wb_v_reg_result = {16'h1111,wb_v_reg_result[15:0]}; + end + + `INSTR_I_LHU: + case (d_mem_offset) + 2'b00 : + wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; + 2'b10 : + wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; + default : + wb_v_reg_result = 32'h00000000; + endcase + + `INSTR_I_LW: + wb_v_reg_result = mem_data_in_i; + + default : + wb_v_reg_result = d_reg_result; + endcase + + // Result from memory / other + if ((d_alu_func == `ALU_NONE)) + begin + r_reg_rd_out <= wb_v_reg_result; + end + // Result from ALU + else + begin + r_reg_rd_out <= d_alu_result; + end + + // Register writeback required? + if (d_rd_wb != 5'b00000) + r_writeback <= 1'b1; + end + end +end + +//------------------------------------------------------------------- +// Combinatorial +//-----------------------------------------------------------------// + +// Memory access mux +assign mem_data_in = mem_data_in_i; +assign mem_addr_mux = (r_mem_access == 1'b1) ? mem_addr : r_pc; +assign mem_addr_o = (mem_pause_i == 1'b1) ? mem_addr_last : mem_addr_mux; +assign mem_data_out_o = mem_data_out; +assign mem_rd_o = (r_mem_access == 1'b1) ? mem_rd : 1'b1; +assign mem_wr_o = (mem_pause_i == 1'b0) ? mem_wr : 4'b0000; + +// Opcode register decoding +assign r_rs = mem_data_in_i[25:21]; +assign r_rt = mem_data_in_i[20:16]; +assign r_rd = mem_data_in_i[15:11]; + +//------------------------------------------------------------------- +// Async memory result forwarding +//------------------------------------------------------------------- +reg [31:0] ldf_v_reg_result; +reg [7:0] ldf_v_inst; + +always @ (d_opcode or mem_offset or mem_data_in_i ) +begin + + // Handle delayed result instructions + ldf_v_inst = {2'b00,d_opcode[31:26]}; + case (ldf_v_inst) + + `INSTR_I_LB: + begin + c_load_op = 1'b1; + case (mem_offset) + 2'b00 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; + 2'b01 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; + 2'b10 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; + 2'b11 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; + default : + ldf_v_reg_result = 32'h00000000; + endcase + + // Sign extend LB + if (ldf_v_reg_result[7] == 1'b1) + ldf_v_reg_result = {24'hFFFFFF,ldf_v_reg_result[7:0]}; + end + + `INSTR_I_LBU: + begin + c_load_op = 1'b1; + case (mem_offset) + 2'b00 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; + 2'b01 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; + 2'b10 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; + 2'b11 : + ldf_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; + default : + ldf_v_reg_result = 32'h00000000; + endcase + end + + `INSTR_I_LH: + begin + c_load_op = 1'b1; + case (mem_offset) + 2'b00 : + ldf_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; + 2'b10 : + ldf_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; + default : + ldf_v_reg_result = 32'h00000000; + endcase + + // Sign extend LH + if (ldf_v_reg_result[15] == 1'b1) + ldf_v_reg_result = {16'h1111,ldf_v_reg_result[15:0]}; + end + + `INSTR_I_LHU: + begin + c_load_op = 1'b1; + case (mem_offset) + 2'b00 : + ldf_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; + 2'b10 : + ldf_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; + default : + ldf_v_reg_result = 32'h00000000; + endcase + end + + `INSTR_I_LW: + begin + c_load_op = 1'b1; + ldf_v_reg_result = mem_data_in_i; + end + + default : + begin + c_load_op = 1'b0; + ldf_v_reg_result = 32'h00000000; + end + endcase + + c_mem_forward = ldf_v_reg_result; +end + +`include "mpx_funcs.v" + +//------------------------------------------------------------------- +// Hooks for debug +//------------------------------------------------------------------- +`ifdef verilator + function [31:0] get_pc; + // verilator public + get_pc = r_pc; + endfunction +`endif + + +endmodule Index: mpx/mpx_defs.v =================================================================== --- mpx/mpx_defs.v (nonexistent) +++ mpx/mpx_defs.v (revision 9) @@ -0,0 +1,152 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// ALU Operations +//----------------------------------------------------------------- +`define ALU_NONE 4'b0000 +`define ALU_SHIFTL 4'b0001 +`define ALU_SHIFTR 4'b0010 +`define ALU_SHIRTR_ARITH 4'b0011 +`define ALU_ADD 4'b0100 +`define ALU_SUB 4'b0101 +`define ALU_AND 4'b0110 +`define ALU_OR 4'b0111 +`define ALU_XOR 4'b1000 +`define ALU_NOR 4'b1001 +`define ALU_SLT 4'b1010 +`define ALU_SLTE 4'b1011 +`define ALU_SLTU 4'b1100 + +//----------------------------------------------------------------- +// Instructions +//----------------------------------------------------------------- + +// R Type +`define INSTR_R_SLL 8'h00 +`define INSTR_R_SRL 8'h02 +`define INSTR_R_SRA 8'h03 +`define INSTR_R_SLLV 8'h04 +`define INSTR_R_SRLV 8'h06 +`define INSTR_R_SRAV 8'h07 +`define INSTR_R_JR 8'h08 +`define INSTR_R_JALR 8'h09 +`define INSTR_R_SYSCALL 8'h0c +`define INSTR_R_BREAK 8'h0d +`define INSTR_R_MFHI 8'h10 +`define INSTR_R_MTHI 8'h11 +`define INSTR_R_MFLO 8'h12 +`define INSTR_R_MTLO 8'h13 +`define INSTR_R_MULT 8'h18 +`define INSTR_R_MULTU 8'h19 +`define INSTR_R_DIV 8'h1a +`define INSTR_R_DIVU 8'h1b +`define INSTR_R_ADD 8'h20 +`define INSTR_R_ADDU 8'h21 +`define INSTR_R_SUB 8'h22 +`define INSTR_R_SUBU 8'h23 +`define INSTR_R_AND 8'h24 +`define INSTR_R_OR 8'h25 +`define INSTR_R_XOR 8'h26 +`define INSTR_R_NOR 8'h27 +`define INSTR_R_SLT 8'h2a +`define INSTR_R_SLTU 8'h2b + +`define INSTR_COP0 8'h10 + +// J Type +`define INSTR_J_JAL 8'h03 +`define INSTR_J_J 8'h02 +`define INSTR_J_BEQ 8'h04 +`define INSTR_J_BNE 8'h05 +`define INSTR_J_BLEZ 8'h06 +`define INSTR_J_BGTZ 8'h07 + +// I Type +`define INSTR_I_ADDI 8'h08 +`define INSTR_I_ADDIU 8'h09 +`define INSTR_I_SLTI 8'h0a +`define INSTR_I_SLTIU 8'h0b +`define INSTR_I_ANDI 8'h0c +`define INSTR_I_ORI 8'h0d +`define INSTR_I_XORI 8'h0e +`define INSTR_I_LUI 8'h0f +`define INSTR_I_LB 8'h20 +`define INSTR_I_LH 8'h21 +`define INSTR_I_LW 8'h23 +`define INSTR_I_LBU 8'h24 +`define INSTR_I_LHU 8'h25 +`define INSTR_I_SB 8'h28 +`define INSTR_I_SH 8'h29 +`define INSTR_I_SW 8'h2b + +`define INSTR_I_REGIMM 8'h01 +`define INSTR_I_COND_BLTZAL 5'b10000 +`define INSTR_I_COND_BLTZ 5'b00000 +`define INSTR_I_COND_BGEZAL 5'b10001 +`define INSTR_I_COND_BGEZ 5'b00001 + +`define INSTR_BUBBLE 8'h3F + +`define OPCODE_INST_BUBBLE 32'hFC000000 + +//----------------------------------------------------------------- +// COP0 +//----------------------------------------------------------------- +`define COP0_STATUS 5'b01100 +`define COP0_CAUSE 5'b01101 +`define COP0_EPC 5'b01110 +`define COP0_ISR_VECT 5'b01111 +`define COP0_FAULT_INFO 5'b10000 +`define COP0_MULT_LO 5'b10001 +`define COP0_MULT_HI 5'b10010 + +//----------------------------------------------------------------- +// Exception Cause (COP0_CAUSE) +//----------------------------------------------------------------- +`define EXCEPTION_NONE 4'b0000 +`define EXCEPTION_SYSCALL 4'b0001 +`define EXCEPTION_BREAK 4'b0010 +`define EXCEPTION_EXTINT 4'b0011 +`define EXCEPTION_FAULT 4'b0100 +`define EXCEPTION_MULT 4'b0101 +`define EXCEPTION_UMULT 4'b0110 +`define EXCEPTION_DIV 4'b0111 +`define EXCEPTION_UDIV 4'b1000 Index: mpx/mpx_alu.v =================================================================== --- mpx/mpx_alu.v (nonexistent) +++ mpx/mpx_alu.v (revision 9) @@ -0,0 +1,113 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "mpx_defs.v" + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module mpx_alu +( + input_a, + input_b, + func, + result +); + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input [31:0] input_a /*verilator public*/; +input [31:0] input_b /*verilator public*/; +input [3:0] func /*verilator public*/; +output [31:0] result /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [31:0] result; + +//----------------------------------------------------------------- +// ALU +//----------------------------------------------------------------- +always @ (func or input_a or input_b ) +begin + case (func) + `ALU_SHIFTL : result = shift_left(input_a, input_b); + `ALU_SHIFTR : result = shift_right(input_a, input_b); + `ALU_SHIRTR_ARITH: result = shift_right_arith(input_a, input_b); + `ALU_ADD : result = (input_a + input_b); + `ALU_SUB : result = (input_a - input_b); + `ALU_AND : result = (input_a & input_b); + `ALU_OR : result = (input_a | input_b); + `ALU_XOR : result = (input_a ^ input_b); + `ALU_NOR : result = (~(input_a | input_b)); + `ALU_SLT : + begin + if (less_than_signed(input_a, input_b) == 1'b1) + result = 32'h00000001; + else + result = 32'h00000000; + end + `ALU_SLTE : + begin + if ((less_than_signed(input_a, input_b) == 1'b1) || (input_a == input_b)) + result = 32'h00000001; + else + result = 32'h00000000; + end + `ALU_SLTU : + begin + if (less_than(input_a, input_b) == 1'b1) + result = 32'h00000001; + else + result = 32'h00000000; + end + default : + result = 32'h00000000; + endcase +end + +`include "mpx_funcs.v" + +endmodule Index: mpx/mpx_regfile_sim.v =================================================================== --- mpx/mpx_regfile_sim.v (nonexistent) +++ mpx/mpx_regfile_sim.v (revision 9) @@ -0,0 +1,372 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "mpx_defs.v" + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module mpx_regfile_sim +( + clk_i, + rst_i, + en_i, + wr_i, + rs_i, + rt_i, + rd_i, + reg_rs_o, + reg_rt_o, + reg_rd_i +); + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input en_i /*verilator public*/; +input wr_i /*verilator public*/; +input [4:0] rs_i /*verilator public*/; +input [4:0] rt_i /*verilator public*/; +input [4:0] rd_i /*verilator public*/; +output [31:0] reg_rs_o /*verilator public*/; +output [31:0] reg_rt_o /*verilator public*/; +input [31:0] reg_rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- + +// Register file +reg [31:0] reg_r1_at; +reg [31:0] reg_r2_v0; +reg [31:0] reg_r3_v1; +reg [31:0] reg_r4_a0; +reg [31:0] reg_r5_a1; +reg [31:0] reg_r6_a2; +reg [31:0] reg_r7_a3; +reg [31:0] reg_r8; +reg [31:0] reg_r9; +reg [31:0] reg_r10; +reg [31:0] reg_r11; +reg [31:0] reg_r12; +reg [31:0] reg_r13; +reg [31:0] reg_r14; +reg [31:0] reg_r15; +reg [31:0] reg_r16; +reg [31:0] reg_r17; +reg [31:0] reg_r18; +reg [31:0] reg_r19; +reg [31:0] reg_r20; +reg [31:0] reg_r21; +reg [31:0] reg_r22; +reg [31:0] reg_r23; +reg [31:0] reg_r24; +reg [31:0] reg_r25; +reg [31:0] reg_k0; +reg [31:0] reg_k1; +reg [31:0] reg_gp; +reg [31:0] reg_sp; +reg [31:0] reg_fp; +reg [31:0] reg_ra; + +reg [31:0] reg_rs_o; +reg [31:0] reg_rt_o; + +//----------------------------------------------------------------- +// Register File (for simulation) +//----------------------------------------------------------------- + +// Synchronous register write back +always @ (posedge clk_i or posedge rst_i) +begin + if (rst_i) + begin + reg_r1_at <= 32'h00000000; + reg_r2_v0 <= 32'h00000000; + reg_r3_v1 <= 32'h00000000; + reg_r4_a0 <= 32'h00000000; + reg_r5_a1 <= 32'h00000000; + reg_r6_a2 <= 32'h00000000; + reg_r7_a3 <= 32'h00000000; + reg_r8 <= 32'h00000000; + reg_r9 <= 32'h00000000; + reg_r10 <= 32'h00000000; + reg_r11 <= 32'h00000000; + reg_r12 <= 32'h00000000; + reg_r13 <= 32'h00000000; + reg_r14 <= 32'h00000000; + reg_r15 <= 32'h00000000; + reg_r16 <= 32'h00000000; + reg_r17 <= 32'h00000000; + reg_r18 <= 32'h00000000; + reg_r19 <= 32'h00000000; + reg_r20 <= 32'h00000000; + reg_r21 <= 32'h00000000; + reg_r22 <= 32'h00000000; + reg_r23 <= 32'h00000000; + reg_r24 <= 32'h00000000; + reg_r25 <= 32'h00000000; + reg_k0 <= 32'h00000000; + reg_k1 <= 32'h00000000; + reg_gp <= 32'h00000000; + reg_sp <= 32'h00000000; + reg_fp <= 32'h00000000; + reg_ra <= 32'h00000000; + end + else if (en_i == 1'b1) + begin + if (wr_i == 1'b1) + case (rd_i[4:0]) + 5'b00001 : + reg_r1_at <= reg_rd_i; + 5'b00010 : + reg_r2_v0 <= reg_rd_i; + 5'b00011 : + reg_r3_v1 <= reg_rd_i; + 5'b00100 : + reg_r4_a0 <= reg_rd_i; + 5'b00101 : + reg_r5_a1 <= reg_rd_i; + 5'b00110 : + reg_r6_a2 <= reg_rd_i; + 5'b00111 : + reg_r7_a3 <= reg_rd_i; + 5'b01000 : + reg_r8 <= reg_rd_i; + 5'b01001 : + reg_r9 <= reg_rd_i; + 5'b01010 : + reg_r10 <= reg_rd_i; + 5'b01011 : + reg_r11 <= reg_rd_i; + 5'b01100 : + reg_r12 <= reg_rd_i; + 5'b01101 : + reg_r13 <= reg_rd_i; + 5'b01110 : + reg_r14 <= reg_rd_i; + 5'b01111 : + reg_r15 <= reg_rd_i; + 5'b10000 : + reg_r16 <= reg_rd_i; + 5'b10001 : + reg_r17 <= reg_rd_i; + 5'b10010 : + reg_r18 <= reg_rd_i; + 5'b10011 : + reg_r19 <= reg_rd_i; + 5'b10100 : + reg_r20 <= reg_rd_i; + 5'b10101 : + reg_r21 <= reg_rd_i; + 5'b10110 : + reg_r22 <= reg_rd_i; + 5'b10111 : + reg_r23 <= reg_rd_i; + 5'b11000 : + reg_r24 <= reg_rd_i; + 5'b11001 : + reg_r25 <= reg_rd_i; + 5'b11010 : + reg_k0 <= reg_rd_i; + 5'b11011 : + reg_k1 <= reg_rd_i; + 5'b11100 : + reg_gp <= reg_rd_i; + 5'b11101 : + reg_sp <= reg_rd_i; + 5'b11110 : + reg_fp <= reg_rd_i; + 5'b11111 : + reg_ra <= reg_rd_i; + default : + ; + endcase + end +end + +// Asynchronous Register read (Rs & Rd) +always @ (rs_i or rt_i or reg_r1_at or reg_r2_v0 or reg_r3_v1 or reg_r4_a0 or reg_r5_a1 or reg_r6_a2 or reg_r7_a3 or reg_r8 or reg_r9 or reg_r10 or reg_r11 or reg_r12 or reg_r13 or reg_r14 or reg_r15 or reg_r16 or reg_r17 or reg_r18 or reg_r19 or reg_r20 or reg_r21 or reg_r22 or reg_r23 or reg_r24 or reg_r25 or reg_k0 or reg_k1 or reg_gp or reg_sp or reg_fp or reg_ra ) +begin + case (rs_i) + 5'b00000 : + reg_rs_o = 32'h00000000; + 5'b00001 : + reg_rs_o = reg_r1_at; + 5'b00010 : + reg_rs_o = reg_r2_v0; + 5'b00011 : + reg_rs_o = reg_r3_v1; + 5'b00100 : + reg_rs_o = reg_r4_a0; + 5'b00101 : + reg_rs_o = reg_r5_a1; + 5'b00110 : + reg_rs_o = reg_r6_a2; + 5'b00111 : + reg_rs_o = reg_r7_a3; + 5'b01000 : + reg_rs_o = reg_r8; + 5'b01001 : + reg_rs_o = reg_r9; + 5'b01010 : + reg_rs_o = reg_r10; + 5'b01011 : + reg_rs_o = reg_r11; + 5'b01100 : + reg_rs_o = reg_r12; + 5'b01101 : + reg_rs_o = reg_r13; + 5'b01110 : + reg_rs_o = reg_r14; + 5'b01111 : + reg_rs_o = reg_r15; + 5'b10000 : + reg_rs_o = reg_r16; + 5'b10001 : + reg_rs_o = reg_r17; + 5'b10010 : + reg_rs_o = reg_r18; + 5'b10011 : + reg_rs_o = reg_r19; + 5'b10100 : + reg_rs_o = reg_r20; + 5'b10101 : + reg_rs_o = reg_r21; + 5'b10110 : + reg_rs_o = reg_r22; + 5'b10111 : + reg_rs_o = reg_r23; + 5'b11000 : + reg_rs_o = reg_r24; + 5'b11001 : + reg_rs_o = reg_r25; + 5'b11010 : + reg_rs_o = reg_k0; + 5'b11011 : + reg_rs_o = reg_k1; + 5'b11100 : + reg_rs_o = reg_gp; + 5'b11101 : + reg_rs_o = reg_sp; + 5'b11110 : + reg_rs_o = reg_fp; + 5'b11111 : + reg_rs_o = reg_ra; + default : + reg_rs_o = 32'h00000000; + endcase + + case (rt_i) + 5'b00000 : + reg_rt_o = 32'h00000000; + 5'b00001 : + reg_rt_o = reg_r1_at; + 5'b00010 : + reg_rt_o = reg_r2_v0; + 5'b00011 : + reg_rt_o = reg_r3_v1; + 5'b00100 : + reg_rt_o = reg_r4_a0; + 5'b00101 : + reg_rt_o = reg_r5_a1; + 5'b00110 : + reg_rt_o = reg_r6_a2; + 5'b00111 : + reg_rt_o = reg_r7_a3; + 5'b01000 : + reg_rt_o = reg_r8; + 5'b01001 : + reg_rt_o = reg_r9; + 5'b01010 : + reg_rt_o = reg_r10; + 5'b01011 : + reg_rt_o = reg_r11; + 5'b01100 : + reg_rt_o = reg_r12; + 5'b01101 : + reg_rt_o = reg_r13; + 5'b01110 : + reg_rt_o = reg_r14; + 5'b01111 : + reg_rt_o = reg_r15; + 5'b10000 : + reg_rt_o = reg_r16; + 5'b10001 : + reg_rt_o = reg_r17; + 5'b10010 : + reg_rt_o = reg_r18; + 5'b10011 : + reg_rt_o = reg_r19; + 5'b10100 : + reg_rt_o = reg_r20; + 5'b10101 : + reg_rt_o = reg_r21; + 5'b10110 : + reg_rt_o = reg_r22; + 5'b10111 : + reg_rt_o = reg_r23; + 5'b11000 : + reg_rt_o = reg_r24; + 5'b11001 : + reg_rt_o = reg_r25; + 5'b11010 : + reg_rt_o = reg_k0; + 5'b11011 : + reg_rt_o = reg_k1; + 5'b11100 : + reg_rt_o = reg_gp; + 5'b11101 : + reg_rt_o = reg_sp; + 5'b11110 : + reg_rt_o = reg_fp; + 5'b11111 : + reg_rt_o = reg_ra; + default : + reg_rt_o = 32'h00000000; + endcase +end + +endmodule Index: soc/soc_core.v =================================================================== --- soc/soc_core.v (nonexistent) +++ soc/soc_core.v (revision 9) @@ -0,0 +1,539 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module soc_core +( + // General - Clocking & Reset + clk_i, + rst_i, + en_i, + ext_intr_i, + fault_o, + break_o, + + // UART + uart_tx_o, + uart_rx_i, + + // BootRAM + int_mem_addr_o, + int_mem_data_o, + int_mem_data_i, + int_mem_wr_o, + int_mem_rd_o, + int_mem_pause_i, + + // External Memory (0x11000000 - 0x11FFFFFF) + ext_mem_addr_o, + ext_mem_data_o, + ext_mem_data_i, + ext_mem_wr_o, + ext_mem_rd_o, + ext_mem_pause_i, + + // External IO ( 0x13000000 - 0x13FFFFFF) + ext_io_addr_o, + ext_io_data_o, + ext_io_data_i, + ext_io_wr_o, + ext_io_rd_o, + ext_io_pause_i, + + // Other Memory (0x14000000 - 0x14FFFFFF) +`ifdef CONF_ALTSOC_BUS_ALT + ext_alt_addr_o, + ext_alt_data_o, + ext_alt_data_i, + ext_alt_wr_o, + ext_alt_rd_o, + ext_alt_pause_i, +`endif + + // SPI Flash + flash_cs_o, + flash_si_o, + flash_so_i, + flash_sck_o, + + // Debug UART output + dbg_uart_data_o, + dbg_uart_wr_o +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] CLK_KHZ = 12288; +parameter [31:0] UART_BAUD = 115200; +parameter [31:0] SPI_FLASH_CLK_KHZ = (12288/2); +parameter [31:0] EXTERNAL_INTERRUPTS = 1; +parameter BOOT_VECTOR = 0; +parameter ISR_VECTOR = 0; +parameter REGISTER_FILE_TYPE = "SIMULATION"; +parameter ENABLE_UART = "ENABLED"; +parameter ENABLE_SPI_FLASH = "ENABLED"; +parameter SYSTICK_INTR_MS = 1; +parameter ENABLE_SYSTICK_TIMER = "ENABLED"; +parameter ENABLE_HIGHRES_TIMER = "ENABLED"; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input en_i /*verilator public*/; +output fault_o /*verilator public*/; +output break_o /*verilator public*/; +input [(EXTERNAL_INTERRUPTS - 1):0] ext_intr_i /*verilator public*/; +output uart_tx_o /*verilator public*/; +input uart_rx_i /*verilator public*/; +output [31:0] int_mem_addr_o /*verilator public*/; +output [31:0] int_mem_data_o /*verilator public*/; +input [31:0] int_mem_data_i /*verilator public*/; +output [3:0] int_mem_wr_o /*verilator public*/; +output int_mem_rd_o /*verilator public*/; +input int_mem_pause_i /*verilator public*/; +output [31:0] ext_mem_addr_o /*verilator public*/; +output [31:0] ext_mem_data_o /*verilator public*/; +input [31:0] ext_mem_data_i /*verilator public*/; +output [3:0] ext_mem_wr_o /*verilator public*/; +output ext_mem_rd_o /*verilator public*/; +input ext_mem_pause_i /*verilator public*/; +output [31:0] ext_io_addr_o /*verilator public*/; +output [31:0] ext_io_data_o /*verilator public*/; +input [31:0] ext_io_data_i /*verilator public*/; +output [3:0] ext_io_wr_o /*verilator public*/; +output ext_io_rd_o /*verilator public*/; +input ext_io_pause_i /*verilator public*/; +`ifdef CONF_ALTSOC_BUS_ALT +output [31:0] ext_alt_addr_o /*verilator public*/; +output [31:0] ext_alt_data_o /*verilator public*/; +input [31:0] ext_alt_data_i /*verilator public*/; +output [3:0] ext_alt_wr_o /*verilator public*/; +output ext_alt_rd_o /*verilator public*/; +input ext_alt_pause_i /*verilator public*/; +`endif +output flash_cs_o /*verilator public*/; +output flash_si_o /*verilator public*/; +input flash_so_i /*verilator public*/; +output flash_sck_o /*verilator public*/; +output [7:0] dbg_uart_data_o /*verilator public*/; +output dbg_uart_wr_o /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +wire [31:0] cpu_address; +wire [3:0] cpu_wr; +wire cpu_rd; +wire [31:0] cpu_data_w; +wire [31:0] cpu_data_r; +wire cpu_pause; + +wire [31:0] io_address; +wire [31:0] io_data_w; +wire [31:0] io_data_r; +wire [3:0] io_wr; +wire io_rd; + +// IRQ Status +wire intr_in; + +// Output Signals +wire uart_tx_o; +wire [31:0] int_mem_addr_o; +wire [31:0] int_mem_data_o; +wire [3:0] int_mem_wr_o; +wire int_mem_rd_o; +wire [31:0] ext_io_addr_o; +wire [31:0] ext_io_data_o; +wire [3:0] ext_io_wr_o; +wire ext_io_rd_o; +wire [31:0] ext_mem_addr_o; +wire [31:0] ext_mem_data_o; +wire [3:0] ext_mem_wr_o; +wire ext_mem_rd_o; +`ifdef CONF_ALTSOC_BUS_ALT +wire [31:0] ext_alt_addr_o; +wire [31:0] ext_alt_data_o; +wire [3:0] ext_alt_wr_o; +wire ext_alt_rd_o; +`endif +wire flash_cs_o; +wire flash_si_o; +wire flash_sck_o; + +// Peripheral Interface +wire [7:0] uart_addr; +wire [31:0] uart_data_o; +wire [31:0] uart_data_i; +wire [3:0] uart_wr; +wire uart_rd; +wire uart_intr; + +wire [7:0] spi_addr; +wire [31:0] spi_data_o; +wire [31:0] spi_data_i; +wire [3:0] spi_wr; +wire spi_rd; + +wire [7:0] timer_addr; +wire [31:0] timer_data_o; +wire [31:0] timer_data_i; +wire [3:0] timer_wr; +wire timer_rd; +wire timer_intr_systick; +wire timer_intr_hires; + +wire [7:0] intr_addr; +wire [31:0] intr_data_o; +wire [31:0] intr_data_i; +wire [3:0] intr_wr; +wire intr_rd; + +//----------------------------------------------------------------- +// CPU core +//----------------------------------------------------------------- +cpu +#( + .BOOT_VECTOR(BOOT_VECTOR), + .ISR_VECTOR(ISR_VECTOR), + .REGISTER_FILE_TYPE(REGISTER_FILE_TYPE) +) +u1_cpu +( + .clk_i(clk_i), + .rst_i(rst_i), + .en_i(en_i), + .intr_i(intr_in), + .fault_o(fault_o), + .break_o(break_o), + .mem_addr_o(cpu_address), + .mem_data_out_o(cpu_data_w), + .mem_data_in_i(cpu_data_r), + .mem_wr_o(cpu_wr), + .mem_rd_o(cpu_rd), + .mem_pause_i(cpu_pause) +); + +//----------------------------------------------------------------- +// Memory MUX +//----------------------------------------------------------------- +mem_mux +#( + .BOOT_VECTOR(BOOT_VECTOR), + .ADDR_MUX_START(24) +) +u2_mux +( + .clk_i(clk_i), + .rst_i(rst_i), + + // Input - CPU core bus + .mem_addr_i(cpu_address), + .mem_data_i(cpu_data_w), + .mem_data_o(cpu_data_r), + .mem_wr_i(cpu_wr), + .mem_rd_i(cpu_rd), + .mem_pause_o(cpu_pause), + + // Outputs + // 0x10000000 - 0x10FFFFFF + .out0_addr_o(int_mem_addr_o), + .out0_data_o(int_mem_data_o), + .out0_data_i(int_mem_data_i), + .out0_wr_o(int_mem_wr_o), + .out0_rd_o(int_mem_rd_o), + .out0_pause_i(int_mem_pause_i), + + // 0x11000000 - 0x11FFFFFF + .out1_addr_o(ext_mem_addr_o), + .out1_data_o(ext_mem_data_o), + .out1_data_i(ext_mem_data_i), + .out1_wr_o(ext_mem_wr_o), + .out1_rd_o(ext_mem_rd_o), + .out1_pause_i(ext_mem_pause_i), + + // 0x12000000 - 0x12FFFFFF + .out2_addr_o(io_address), + .out2_data_o(io_data_w), + .out2_data_i(io_data_r), + .out2_wr_o(io_wr), + .out2_rd_o(io_rd), + .out2_pause_i(1'b0), + + // 0x13000000 - 0x13FFFFFF + .out3_addr_o(ext_io_addr_o), + .out3_data_o(ext_io_data_o), + .out3_data_i(ext_io_data_i), + .out3_wr_o(ext_io_wr_o), + .out3_rd_o(ext_io_rd_o), + .out3_pause_i(ext_io_pause_i), + + // 0x14000000 - 0x14FFFFFF +`ifdef CONF_ALTSOC_BUS_ALT + .out4_addr_o(ext_alt_addr_o), + .out4_data_o(ext_alt_data_o), + .out4_data_i(ext_alt_data_i), + .out4_wr_o(ext_alt_wr_o), + .out4_rd_o(ext_alt_rd_o), + .out4_pause_i(ext_alt_pause_i) +`else + .out4_addr_o(/*open*/), + .out4_data_o(/*open*/), + .out4_data_i(32'h00000000), + .out4_wr_o(/*open*/), + .out4_rd_o(/*open*/), + .out4_pause_i(1'b0) +`endif +); + +//----------------------------------------------------------------- +// Peripheral Interconnect +//----------------------------------------------------------------- +soc_pif +u2_soc +( + // General - Clocking & Reset + .clk_i(clk_i), + .rst_i(rst_i), + + // I/O bus (from mem_mux) + // 0x12000000 - 0x12FFFFFF + .io_addr_i(io_address), + .io_data_i(io_data_w), + .io_data_o(io_data_r), + .io_wr_i(io_wr), + .io_rd_i(io_rd), + + // Peripherals + // UART = 0x12000000 - 0x120000FF + .periph0_addr_o(uart_addr), + .periph0_data_o(uart_data_o), + .periph0_data_i(uart_data_i), + .periph0_wr_o(uart_wr), + .periph0_rd_o(uart_rd), + + // Timer = 0x12000100 - 0x120001FF + .periph1_addr_o(timer_addr), + .periph1_data_o(timer_data_o), + .periph1_data_i(timer_data_i), + .periph1_wr_o(timer_wr), + .periph1_rd_o(timer_rd), + + // Interrupt Controller = 0x12000200 - 0x120002FF + .periph2_addr_o(intr_addr), + .periph2_data_o(intr_data_o), + .periph2_data_i(intr_data_i), + .periph2_wr_o(intr_wr), + .periph2_rd_o(intr_rd), + + // SPI Flash = 0x12000300 - 0x120003FF + .periph3_addr_o(spi_addr), + .periph3_data_o(spi_data_o), + .periph3_data_i(spi_data_i), + .periph3_wr_o(spi_wr), + .periph3_rd_o(spi_rd), + + // Unused = 0x12000400 - 0x120004FF + .periph4_addr_o(/*open*/), + .periph4_data_o(/*open*/), + .periph4_data_i(32'h00000000), + .periph4_wr_o(/*open*/), + .periph4_rd_o(/*open*/), + + // Unused = 0x12000500 - 0x120005FF + .periph5_addr_o(/*open*/), + .periph5_data_o(/*open*/), + .periph5_data_i(32'h00000000), + .periph5_wr_o(/*open*/), + .periph5_rd_o(/*open*/), + + // Unused = 0x12000600 - 0x120006FF + .periph6_addr_o(/*open*/), + .periph6_data_o(/*open*/), + .periph6_data_i(32'h00000000), + .periph6_wr_o(/*open*/), + .periph6_rd_o(/*open*/), + + // Unused = 0x12000700 - 0x120007FF + .periph7_addr_o(/*open*/), + .periph7_data_o(/*open*/), + .periph7_data_i(32'h00000000), + .periph7_wr_o(/*open*/), + .periph7_rd_o(/*open*/) +); + +//----------------------------------------------------------------- +// UART +//----------------------------------------------------------------- +generate +if (ENABLE_UART == "ENABLED") +begin + // UART + uart_periph + #( + .UART_DIVISOR(((CLK_KHZ * 1000) / UART_BAUD)) + ) + u3_uart + ( + .clk_i(clk_i), + .rst_i(rst_i), + .intr_o(uart_intr), + .addr_i(uart_addr), + .data_o(uart_data_i), + .data_i(uart_data_o), + .wr_i(uart_wr), + .rd_i(uart_rd), + .rx_i(uart_rx_i), + .tx_o(uart_tx_o) + ); + + // Debug UART + assign dbg_uart_data_o = uart_data_o[7:0]; + assign dbg_uart_wr_o = (uart_wr != 4'b0000) ? 1'b1 : 1'b0; +end +else +begin + // UART Disabled + assign uart_tx_o = 1'b1; + assign dbg_uart_data_o = 8'h00; + assign dbg_uart_wr_o = 1'b0; + assign uart_data_i = 32'h00000000; +end +endgenerate + +//----------------------------------------------------------------- +// SPI Flash Master +//----------------------------------------------------------------- +generate +if (ENABLE_SPI_FLASH == "ENABLED") +begin + // SPI Flash Master + spim_periph + #( + .CLK_DIV(CLK_KHZ / SPI_FLASH_CLK_KHZ) + ) + u4_spi_flash + ( + // Clocking / Reset + .clk_i(clk_i), + .rst_i(rst_i), + .intr_o(/*open*/), + // Peripheral I/O + .addr_i(spi_addr), + .data_o(spi_data_i), + .data_i(spi_data_o), + .wr_i(spi_wr), + .rd_i(spi_rd), + // SPI interface + .spi_clk_o(flash_sck_o), + .spi_ss_o(flash_cs_o), + .spi_mosi_o(flash_si_o), + .spi_miso_i(flash_so_i) + ); +end +else +begin + // SPI Flash Disabled + assign flash_cs_o = 1'b1; + assign flash_si_o = 1'b0; + assign flash_sck_o = 1'b0; + assign spi_data_i = 32'h00000000; +end +endgenerate + +//----------------------------------------------------------------- +// Timer +//----------------------------------------------------------------- +timer_periph +#( + .CLK_KHZ(CLK_KHZ), + .SYSTICK_INTR_MS(SYSTICK_INTR_MS), + .ENABLE_SYSTICK_TIMER(ENABLE_SYSTICK_TIMER), + .ENABLE_HIGHRES_TIMER(ENABLE_HIGHRES_TIMER) +) +u5_timer +( + .clk_i(clk_i), + .rst_i(rst_i), + .intr_systick_o(timer_intr_systick), + .intr_hires_o(timer_intr_hires), + .addr_i(timer_addr), + .data_o(timer_data_i), + .data_i(timer_data_o), + .wr_i(timer_wr), + .rd_i(timer_rd) +); + +//----------------------------------------------------------------- +// Interrupt Controller +//----------------------------------------------------------------- +intr_periph +#( + .EXTERNAL_INTERRUPTS(EXTERNAL_INTERRUPTS) +) +u6_intr +( + .clk_i(clk_i), + .rst_i(rst_i), + .intr_o(intr_in), + + .intr0_i(uart_intr), + .intr1_i(timer_intr_systick), + .intr2_i(timer_intr_hires), + .intr3_i(1'b0), + .intr4_i(1'b0), + .intr5_i(1'b0), + .intr6_i(1'b0), + .intr7_i(1'b0), + .intr_ext_i(ext_intr_i), + + .addr_i(intr_addr), + .data_o(intr_data_i), + .data_i(intr_data_o), + .wr_i(intr_wr), + .rd_i(intr_rd) +); + +endmodule Index: soc/soc_pif.v =================================================================== --- soc/soc_pif.v (nonexistent) +++ soc/soc_pif.v (revision 9) @@ -0,0 +1,695 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module soc_pif +( + // General - Clocking & Reset + clk_i, + rst_i, + + // I/O bus + io_addr_i, + io_data_i, + io_data_o, + io_wr_i, + io_rd_i, + + // Peripherals + periph0_addr_o, + periph0_data_o, + periph0_data_i, + periph0_wr_o, + periph0_rd_o, + + periph1_addr_o, + periph1_data_o, + periph1_data_i, + periph1_wr_o, + periph1_rd_o, + + periph2_addr_o, + periph2_data_o, + periph2_data_i, + periph2_wr_o, + periph2_rd_o, + + periph3_addr_o, + periph3_data_o, + periph3_data_i, + periph3_wr_o, + periph3_rd_o, + + periph4_addr_o, + periph4_data_o, + periph4_data_i, + periph4_wr_o, + periph4_rd_o, + + periph5_addr_o, + periph5_data_o, + periph5_data_i, + periph5_wr_o, + periph5_rd_o, + + periph6_addr_o, + periph6_data_o, + periph6_data_i, + periph6_wr_o, + periph6_rd_o, + + periph7_addr_o, + periph7_data_o, + periph7_data_i, + periph7_wr_o, + periph7_rd_o +); + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; + +input [31:0] io_addr_i /*verilator public*/; +output [31:0] io_data_o /*verilator public*/; +input [31:0] io_data_i /*verilator public*/; +input [3:0] io_wr_i /*verilator public*/; +input io_rd_i /*verilator public*/; + +output [7:0] periph0_addr_o /*verilator public*/; +output [31:0] periph0_data_o /*verilator public*/; +input [31:0] periph0_data_i /*verilator public*/; +output [3:0] periph0_wr_o /*verilator public*/; +output periph0_rd_o /*verilator public*/; + +output [7:0] periph1_addr_o /*verilator public*/; +output [31:0] periph1_data_o /*verilator public*/; +input [31:0] periph1_data_i /*verilator public*/; +output [3:0] periph1_wr_o /*verilator public*/; +output periph1_rd_o /*verilator public*/; + +output [7:0] periph2_addr_o /*verilator public*/; +output [31:0] periph2_data_o /*verilator public*/; +input [31:0] periph2_data_i /*verilator public*/; +output [3:0] periph2_wr_o /*verilator public*/; +output periph2_rd_o /*verilator public*/; + +output [7:0] periph3_addr_o /*verilator public*/; +output [31:0] periph3_data_o /*verilator public*/; +input [31:0] periph3_data_i /*verilator public*/; +output [3:0] periph3_wr_o /*verilator public*/; +output periph3_rd_o /*verilator public*/; + +output [7:0] periph4_addr_o /*verilator public*/; +output [31:0] periph4_data_o /*verilator public*/; +input [31:0] periph4_data_i /*verilator public*/; +output [3:0] periph4_wr_o /*verilator public*/; +output periph4_rd_o /*verilator public*/; + +output [7:0] periph5_addr_o /*verilator public*/; +output [31:0] periph5_data_o /*verilator public*/; +input [31:0] periph5_data_i /*verilator public*/; +output [3:0] periph5_wr_o /*verilator public*/; +output periph5_rd_o /*verilator public*/; + +output [7:0] periph6_addr_o /*verilator public*/; +output [31:0] periph6_data_o /*verilator public*/; +input [31:0] periph6_data_i /*verilator public*/; +output [3:0] periph6_wr_o /*verilator public*/; +output periph6_rd_o /*verilator public*/; + +output [7:0] periph7_addr_o /*verilator public*/; +output [31:0] periph7_data_o /*verilator public*/; +input [31:0] periph7_data_i /*verilator public*/; +output [3:0] periph7_wr_o /*verilator public*/; +output periph7_rd_o /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [3:0] r_mem_sel; + +reg [31:0] io_data_o; + +reg [7:0] periph0_addr_o; +reg [31:0] periph0_data_o; +reg [3:0] periph0_wr_o; +reg periph0_rd_o; + +reg [7:0] periph1_addr_o; +reg [31:0] periph1_data_o; +reg [3:0] periph1_wr_o; +reg periph1_rd_o; + +reg [7:0] periph2_addr_o; +reg [31:0] periph2_data_o; +reg [3:0] periph2_wr_o; +reg periph2_rd_o; + +reg [7:0] periph3_addr_o; +reg [31:0] periph3_data_o; +reg [3:0] periph3_wr_o; +reg periph3_rd_o; + +reg [7:0] periph4_addr_o; +reg [31:0] periph4_data_o; +reg [3:0] periph4_wr_o; +reg periph4_rd_o; + +reg [7:0] periph5_addr_o; +reg [31:0] periph5_data_o; +reg [3:0] periph5_wr_o; +reg periph5_rd_o; + +reg [7:0] periph6_addr_o; +reg [31:0] periph6_data_o; +reg [3:0] periph6_wr_o; +reg periph6_rd_o; + +reg [7:0] periph7_addr_o; +reg [31:0] periph7_data_o; +reg [3:0] periph7_wr_o; +reg periph7_rd_o; + +//----------------------------------------------------------------- +// Memory Map +//----------------------------------------------------------------- +always @ (io_addr_i or io_wr_i or io_rd_i or io_data_i) +begin + // Decode 4-bit peripheral select + case (io_addr_i[11:8]) + + // Peripheral 0 + 4'h0 : + begin + + periph0_addr_o = io_addr_i[7:0]; + periph0_wr_o = io_wr_i; + periph0_rd_o = io_rd_i; + periph0_data_o = io_data_i; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + + end + + // Peripheral 1 + 4'h1 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = io_addr_i[7:0]; + periph1_wr_o = io_wr_i; + periph1_rd_o = io_rd_i; + periph1_data_o = io_data_i; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 2 + 4'h2 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = io_addr_i[7:0]; + periph2_wr_o = io_wr_i; + periph2_rd_o = io_rd_i; + periph2_data_o = io_data_i; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 3 + 4'h3 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = io_addr_i[7:0]; + periph3_wr_o = io_wr_i; + periph3_rd_o = io_rd_i; + periph3_data_o = io_data_i; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 4 + 4'h4 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = io_addr_i[7:0]; + periph4_wr_o = io_wr_i; + periph4_rd_o = io_rd_i; + periph4_data_o = io_data_i; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 5 + 4'h5 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = io_addr_i[7:0]; + periph5_wr_o = io_wr_i; + periph5_rd_o = io_rd_i; + periph5_data_o = io_data_i; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 6 + 4'h6 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = io_addr_i[7:0]; + periph6_wr_o = io_wr_i; + periph6_rd_o = io_rd_i; + periph6_data_o = io_data_i; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + + // Peripheral 7 + 4'h7 : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = io_addr_i[7:0]; + periph7_wr_o = io_wr_i; + periph7_rd_o = io_rd_i; + periph7_data_o = io_data_i; + end + + default : + begin + periph0_addr_o = 8'h00; + periph0_wr_o = 4'b0000; + periph0_rd_o = 1'b0; + periph0_data_o = 32'h00000000; + + periph1_addr_o = 8'h00; + periph1_wr_o = 4'b0000; + periph1_rd_o = 1'b0; + periph1_data_o = 32'h00000000; + + periph2_addr_o = 8'h00; + periph2_wr_o = 4'b0000; + periph2_rd_o = 1'b0; + periph2_data_o = 32'h00000000; + + periph3_addr_o = 8'h00; + periph3_wr_o = 4'b0000; + periph3_rd_o = 1'b0; + periph3_data_o = 32'h00000000; + + periph4_addr_o = 8'h00; + periph4_wr_o = 4'b0000; + periph4_rd_o = 1'b0; + periph4_data_o = 32'h00000000; + + periph5_addr_o = 8'h00; + periph5_wr_o = 4'b0000; + periph5_rd_o = 1'b0; + periph5_data_o = 32'h00000000; + + periph6_addr_o = 8'h00; + periph6_wr_o = 4'b0000; + periph6_rd_o = 1'b0; + periph6_data_o = 32'h00000000; + + periph7_addr_o = 8'h00; + periph7_wr_o = 4'b0000; + periph7_rd_o = 1'b0; + periph7_data_o = 32'h00000000; + end + endcase +end + +//----------------------------------------------------------------- +// Read Port +//----------------------------------------------------------------- +always @ (r_mem_sel or periph0_data_i or periph1_data_i or periph2_data_i or + periph3_data_i or periph4_data_i or periph5_data_i or periph6_data_i or periph7_data_i) +begin + case (r_mem_sel) + + // Peripheral 0 + 4'h0 : + begin + io_data_o = periph0_data_i; + end + + // Peripheral 1 + 4'h1 : + begin + io_data_o = periph1_data_i; + end + + // Peripheral 2 + 4'h2 : + begin + io_data_o = periph2_data_i; + end + + // Peripheral 3 + 4'h3 : + begin + io_data_o = periph3_data_i; + end + + // Peripheral 4 + 4'h4 : + begin + io_data_o = periph4_data_i; + end + + // Peripheral 5 + 4'h5 : + begin + io_data_o = periph5_data_i; + end + + // Peripheral 6 + 4'h6 : + begin + io_data_o = periph6_data_i; + end + + // Peripheral 7 + 4'h7 : + begin + io_data_o = periph7_data_i; + end + + default : + begin + io_data_o = 32'h00000000; + end + endcase +end + +//----------------------------------------------------------------- +// Registered peripheral select +//----------------------------------------------------------------- +always @ (posedge clk_i or posedge rst_i) +begin + if (rst_i == 1'b1) + r_mem_sel <= 4'h0; + else + r_mem_sel <= io_addr_i[11:8]; +end + +endmodule Index: soc/mem_mux.v =================================================================== --- soc/mem_mux.v (nonexistent) +++ soc/mem_mux.v (revision 9) @@ -0,0 +1,415 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module mem_mux +( + // General + clk_i, + rst_i, + + // Input + mem_addr_i, + mem_data_i, + mem_data_o, + mem_wr_i, + mem_rd_i, + mem_pause_o, + + // Outputs + out0_addr_o, + out0_data_o, + out0_data_i, + out0_wr_o, + out0_rd_o, + out0_pause_i, + + out1_addr_o, + out1_data_o, + out1_data_i, + out1_wr_o, + out1_rd_o, + out1_pause_i, + + out2_addr_o, + out2_data_o, + out2_data_i, + out2_wr_o, + out2_rd_o, + out2_pause_i, + + out3_addr_o, + out3_data_o, + out3_data_i, + out3_wr_o, + out3_rd_o, + out3_pause_i, + + out4_addr_o, + out4_data_o, + out4_data_i, + out4_wr_o, + out4_rd_o, + out4_pause_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter BOOT_VECTOR = 0; +parameter ADDR_MUX_START = 28; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input [31:0] mem_addr_i /*verilator public*/; +input [31:0] mem_data_i /*verilator public*/; +output [31:0] mem_data_o /*verilator public*/; +input [3:0] mem_wr_i /*verilator public*/; +input mem_rd_i /*verilator public*/; +output mem_pause_o /*verilator public*/; +output [31:0] out0_addr_o /*verilator public*/; +output [31:0] out0_data_o /*verilator public*/; +input [31:0] out0_data_i /*verilator public*/; +output [3:0] out0_wr_o /*verilator public*/; +output out0_rd_o /*verilator public*/; +input out0_pause_i /*verilator public*/; +output [31:0] out1_addr_o /*verilator public*/; +output [31:0] out1_data_o /*verilator public*/; +input [31:0] out1_data_i /*verilator public*/; +output [3:0] out1_wr_o /*verilator public*/; +output out1_rd_o /*verilator public*/; +input out1_pause_i /*verilator public*/; +output [31:0] out2_addr_o /*verilator public*/; +output [31:0] out2_data_o /*verilator public*/; +input [31:0] out2_data_i /*verilator public*/; +output [3:0] out2_wr_o /*verilator public*/; +output out2_rd_o /*verilator public*/; +input out2_pause_i /*verilator public*/; +output [31:0] out3_addr_o /*verilator public*/; +output [31:0] out3_data_o /*verilator public*/; +input [31:0] out3_data_i /*verilator public*/; +output [3:0] out3_wr_o /*verilator public*/; +output out3_rd_o /*verilator public*/; +input out3_pause_i /*verilator public*/; +output [31:0] out4_addr_o /*verilator public*/; +output [31:0] out4_data_o /*verilator public*/; +input [31:0] out4_data_i /*verilator public*/; +output [3:0] out4_wr_o /*verilator public*/; +output out4_rd_o /*verilator public*/; +input out4_pause_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [2:0] r_mem_sel; + +// Output Signals +reg mem_pause_o; +reg [31:0] mem_data_o; +reg [31:0] out0_addr_o; +reg [31:0] out0_data_o; +reg [3:0] out0_wr_o; +reg out0_rd_o; +reg [31:0] out1_addr_o; +reg [31:0] out1_data_o; +reg [3:0] out1_wr_o; +reg out1_rd_o; +reg [31:0] out2_addr_o; +reg [31:0] out2_data_o; +reg [3:0] out2_wr_o; +reg out2_rd_o; +reg [31:0] out3_addr_o; +reg [31:0] out3_data_o; +reg [3:0] out3_wr_o; +reg out3_rd_o; +reg [31:0] out4_addr_o; +reg [31:0] out4_data_o; +reg [3:0] out4_wr_o; +reg out4_rd_o; + +//----------------------------------------------------------------- +// Memory Map +//----------------------------------------------------------------- +always @ (mem_addr_i or mem_wr_i or mem_rd_i or mem_data_i ) +begin + case (mem_addr_i[ADDR_MUX_START+2:ADDR_MUX_START]) + + 3'b000 : + begin + out0_addr_o = mem_addr_i; + out0_wr_o = mem_wr_i; + out0_rd_o = mem_rd_i; + out0_data_o = mem_data_i; + + out1_addr_o = 32'h00000000; + out1_wr_o = 4'b0000; + out1_rd_o = 1'b0; + out1_data_o = 32'h00000000; + + out2_addr_o = 32'h00000000; + out2_wr_o = 4'b0000; + out2_rd_o = 1'b0; + out2_data_o = 32'h00000000; + + out3_addr_o = 32'h00000000; + out3_wr_o = 4'b0000; + out3_rd_o = 1'b0; + out3_data_o = 32'h00000000; + + out4_addr_o = 32'h00000000; + out4_wr_o = 4'b0000; + out4_rd_o = 1'b0; + out4_data_o = 32'h00000000; + end + + 3'b001 : + begin + out0_addr_o = 32'h00000000; + out0_wr_o = 4'b0000; + out0_rd_o = 1'b0; + out0_data_o = 32'h00000000; + + out1_addr_o = mem_addr_i; + out1_wr_o = mem_wr_i; + out1_rd_o = mem_rd_i; + out1_data_o = mem_data_i; + + out2_addr_o = 32'h00000000; + out2_wr_o = 4'b0000; + out2_rd_o = 1'b0; + out2_data_o = 32'h00000000; + + out3_addr_o = 32'h00000000; + out3_wr_o = 4'b0000; + out3_rd_o = 1'b0; + out3_data_o = 32'h00000000; + + out4_addr_o = 32'h00000000; + out4_wr_o = 4'b0000; + out4_rd_o = 1'b0; + out4_data_o = 32'h00000000; + end + + 3'b010 : + begin + out0_addr_o = 32'h00000000; + out0_wr_o = 4'b0000; + out0_rd_o = 1'b0; + out0_data_o = 32'h00000000; + + out1_addr_o = 32'h00000000; + out1_wr_o = 4'b0000; + out1_rd_o = 1'b0; + out1_data_o = 32'h00000000; + + out2_addr_o = mem_addr_i; + out2_wr_o = mem_wr_i; + out2_rd_o = mem_rd_i; + out2_data_o = mem_data_i; + + out3_addr_o = 32'h00000000; + out3_wr_o = 4'b0000; + out3_rd_o = 1'b0; + out3_data_o = 32'h00000000; + + out4_addr_o = 32'h00000000; + out4_wr_o = 4'b0000; + out4_rd_o = 1'b0; + out4_data_o = 32'h00000000; + end + + 3'b011 : + begin + out0_addr_o = 32'h00000000; + out0_wr_o = 4'b0000; + out0_rd_o = 1'b0; + out0_data_o = 32'h00000000; + + out1_addr_o = 32'h00000000; + out1_wr_o = 4'b0000; + out1_rd_o = 1'b0; + out1_data_o = 32'h00000000; + + out2_addr_o = 32'h00000000; + out2_wr_o = 4'b0000; + out2_rd_o = 1'b0; + out2_data_o = 32'h00000000; + + out3_addr_o = mem_addr_i; + out3_wr_o = mem_wr_i; + out3_rd_o = mem_rd_i; + out3_data_o = mem_data_i; + + out4_addr_o = 32'h00000000; + out4_wr_o = 4'b0000; + out4_rd_o = 1'b0; + out4_data_o = 32'h00000000; + end + + 3'b100 : + begin + out0_addr_o = 32'h00000000; + out0_wr_o = 4'b0000; + out0_rd_o = 1'b0; + out0_data_o = 32'h00000000; + + out1_addr_o = 32'h00000000; + out1_wr_o = 4'b0000; + out1_rd_o = 1'b0; + out1_data_o = 32'h00000000; + + out2_addr_o = 32'h00000000; + out2_wr_o = 4'b0000; + out2_rd_o = 1'b0; + out2_data_o = 32'h00000000; + + out3_addr_o = 32'h00000000; + out3_wr_o = 4'b0000; + out3_rd_o = 1'b0; + out3_data_o = 32'h00000000; + + out4_addr_o = mem_addr_i; + out4_wr_o = mem_wr_i; + out4_rd_o = mem_rd_i; + out4_data_o = mem_data_i; + end + + default : + begin + out0_addr_o = 32'h00000000; + out0_wr_o = 4'b0000; + out0_rd_o = 1'b0; + out0_data_o = 32'h00000000; + + out1_addr_o = 32'h00000000; + out1_wr_o = 4'b0000; + out1_rd_o = 1'b0; + out1_data_o = 32'h00000000; + + out2_addr_o = 32'h00000000; + out2_wr_o = 4'b0000; + out2_rd_o = 1'b0; + out2_data_o = 32'h00000000; + + out3_addr_o = 32'h00000000; + out3_wr_o = 4'b0000; + out3_rd_o = 1'b0; + out3_data_o = 32'h00000000; + + out4_addr_o = 32'h00000000; + out4_wr_o = 4'b0000; + out4_rd_o = 1'b0; + out4_data_o = 32'h00000000; + end + endcase +end + +//----------------------------------------------------------------- +// Read Port +//----------------------------------------------------------------- +always @ ( r_mem_sel or + out0_data_i or out0_pause_i or + out1_data_i or out1_pause_i or + out2_data_i or out2_pause_i or + out3_data_i or out3_pause_i or + out4_data_i or out4_pause_i ) +begin + case (r_mem_sel) + + 3'b000 : + begin + mem_data_o = out0_data_i; + mem_pause_o = out0_pause_i; + end + + 3'b001 : + begin + mem_data_o = out1_data_i; + mem_pause_o = out1_pause_i; + end + + 3'b010 : + begin + mem_data_o = out2_data_i; + mem_pause_o = out2_pause_i; + end + + 3'b011 : + begin + mem_data_o = out3_data_i; + mem_pause_o = out3_pause_i; + end + + 3'b100 : + begin + mem_data_o = out4_data_i; + mem_pause_o = out4_pause_i; + end + + default : + begin + mem_data_o = 32'h00000000; + mem_pause_o = 1'b0; + end + endcase +end + +//----------------------------------------------------------------- +// Registered device select +//----------------------------------------------------------------- +reg [31:0] v_mem_sel; + +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + v_mem_sel = BOOT_VECTOR; + r_mem_sel <= v_mem_sel[ADDR_MUX_START+2:ADDR_MUX_START]; + end + else + r_mem_sel <= mem_addr_i[ADDR_MUX_START+2:ADDR_MUX_START]; +end + +endmodule Index: peripheral/uart.v =================================================================== --- peripheral/uart.v (nonexistent) +++ peripheral/uart.v (revision 9) @@ -0,0 +1,284 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module uart +( + // Clock & Reset + clk_i, + rst_i, + // Status + tx_busy_o, + rx_ready_o, + // Data + data_i, + wr_i, + data_o, + rd_i, + // UART pins + rxd_i, + txd_o +); +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] UART_DIVISOR = 278; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input [7:0] data_i /*verilator public*/; +output [7:0] data_o /*verilator public*/; +input wr_i /*verilator public*/; +input rd_i /*verilator public*/; +output tx_busy_o /*verilator public*/; +output rx_ready_o /*verilator public*/; +input rxd_i /*verilator public*/; +output txd_o /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +parameter FULL_BIT = UART_DIVISOR; +parameter HALF_BIT = (FULL_BIT / 2); + +// TX Signals +reg [7:0] tx_buf; +reg tx_buf_full; +reg tx_busy; +reg [3:0] tx_bits; +integer tx_count; +reg [7:0] tx_shift_reg; +reg txd_o; + +// RX Signals +reg i_rxd; +reg [7:0] data_o; +reg [3:0] rx_bits; +integer rx_count; +reg [7:0] rx_shift_reg; +reg rx_ready_o; + +//----------------------------------------------------------------- +// Re-sync RXD +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + i_rxd <= 1'b1; + else + i_rxd <= rxd_i; +end + +//----------------------------------------------------------------- +// RX Process +//----------------------------------------------------------------- +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + rx_bits <= 0; + rx_count <= 0; + rx_ready_o <= 1'b0; + rx_shift_reg <= 8'h00; + data_o <= 8'h00; + end + else + begin + + // If reading data, reset data ready state + if (rd_i == 1'b1) + rx_ready_o <= 1'b0; + + // Rx bit timer + if (rx_count != 0) + rx_count <= (rx_count - 1); + else + begin + //------------------------------- + // Start bit detection + //------------------------------- + if (rx_bits == 0) + begin + // If RXD low, check again in half bit time + if (i_rxd == 1'b0) + begin + rx_count <= HALF_BIT; + rx_bits <= 1; + end + end + //------------------------------- + // Start bit (mid bit time point) + //------------------------------- + else if (rx_bits == 1) + begin + // RXD should still be low at mid point of bit period + if (i_rxd == 1'b0) + begin + rx_count <= FULL_BIT; + rx_bits <= rx_bits + 1'b1; + rx_shift_reg <= 8'h00; + end + // Start bit not still low, reset RX process + else + begin + rx_bits <= 0; + end + end + //------------------------------- + // Stop bit + //------------------------------- + else if (rx_bits == 10) + begin + // RXD should be still high + if (i_rxd == 1'b1) + begin + rx_count <= 0; + rx_bits <= 0; + data_o <= rx_shift_reg; + rx_ready_o <= 1'b1; + end + // Bad Stop bit - wait for a full bit period + // before allowing start bit detection again + else + begin + rx_count <= FULL_BIT; + rx_bits <= 0; + end + end + //------------------------------- + // Data bits + //------------------------------- + else + begin + // Receive data LSB first + rx_shift_reg[7] <= i_rxd; + rx_shift_reg[6:0]<= rx_shift_reg[7:1]; + rx_count <= FULL_BIT; + rx_bits <= rx_bits + 1'b1; + end + end + end +end + +//----------------------------------------------------------------- +// TX Process +//----------------------------------------------------------------- +always @ (posedge clk_i or posedge rst_i ) +begin + if (rst_i == 1'b1) + begin + tx_count <= 0; + tx_bits <= 0; + tx_busy <= 1'b0; + txd_o <= 1'b1; + tx_shift_reg <= 8'h00; + tx_buf <= 8'h00; + tx_buf_full <= 1'b0; + end + else + begin + + // Buffer data to transmit + if (wr_i == 1'b1) + begin + tx_buf <= data_i; + tx_buf_full <= 1'b1; + end + + // Tx bit timer + if (tx_count != 0) + tx_count <= (tx_count - 1); + else + begin + + //------------------------------- + // Start bit (TXD = L) + //------------------------------- + if (tx_bits == 0) + begin + + tx_busy <= 1'b0; + + // Data in buffer ready to transmit? + if (tx_buf_full == 1'b1) + begin + tx_shift_reg <= tx_buf; + tx_busy <= 1'b1; + txd_o <= 1'b0; + tx_buf_full <= 1'b0; + tx_bits <= 1; + tx_count <= FULL_BIT; + end + end + //------------------------------- + // Stop bit (TXD = H) + //------------------------------- + else if (tx_bits == 9) + begin + txd_o <= 1'b1; + tx_bits <= 0; + tx_count <= FULL_BIT; + end + //------------------------------- + // Data bits + //------------------------------- + else + begin + // Shift data out LSB first + txd_o <= tx_shift_reg[0]; + tx_shift_reg[6:0]<= tx_shift_reg[7:1]; + tx_bits <= tx_bits + 1'b1; + tx_count <= FULL_BIT; + end + end + end +end + +//----------------------------------------------------------------- +// Combinatorial +//----------------------------------------------------------------- +assign tx_busy_o = (tx_busy | tx_buf_full | wr_i); + +endmodule Index: peripheral/uart_defs.v =================================================================== --- peripheral/uart_defs.v (nonexistent) +++ peripheral/uart_defs.v (revision 9) @@ -0,0 +1,47 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- + +// Basic Peripherals +`define UART_USR 8'h04 +`define UART_UDR 8'h08 Index: peripheral/intr_defs.v =================================================================== --- peripheral/intr_defs.v (nonexistent) +++ peripheral/intr_defs.v (revision 9) @@ -0,0 +1,47 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define IRQ_MASK_SET 8'h00 +`define IRQ_MASK_CLR 8'h04 +`define IRQ_STATUS 8'h08 + `define IRQ_EXT_FIRST (8) Index: peripheral/gpio_defs.v =================================================================== --- peripheral/gpio_defs.v (nonexistent) +++ peripheral/gpio_defs.v (revision 9) @@ -0,0 +1,49 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define GPIO_OUT 8'h00 +`define GPIO_IN 8'h04 +`define GPIO_DIR 8'h08 +`define GPIO_INT_MASK 8'h0C +`define GPIO_INT_POLARITY 8'h10 +`define GPIO_INT_EDGE 8'h14 Index: peripheral/spim_periph.v =================================================================== --- peripheral/spim_periph.v (nonexistent) +++ peripheral/spim_periph.v (revision 9) @@ -0,0 +1,202 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "spim_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module spim_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + intr_o, + + // SPI Bus + spi_clk_o, + spi_ss_o, + spi_mosi_o, + spi_miso_i, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] CLK_DIV = 32; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +output intr_o /*verilator public*/; + +output spi_clk_o /*verilator public*/; +output spi_ss_o /*verilator public*/; +output spi_mosi_o /*verilator public*/; +input spi_miso_i /*verilator public*/; + +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- +reg [31:0] data_o; +reg spi_ss_o; +reg spi_start; +wire spi_busy; +reg [7:0] spi_data_wr; +wire [7:0] spi_data_rd; + +//----------------------------------------------------------------- +// Instantiation +//----------------------------------------------------------------- + +// SPI Master +spi_master +#( + .CLK_DIV(CLK_DIV), + .TRANSFER_WIDTH(8) +) +u1_spi_master +( + // Clocking / Reset + .clk_i(clk_i), + .rst_i(rst_i), + // Control & Status + .start_i(spi_start), + .done_o(intr_o), + .busy_o(spi_busy), + // Data + .data_i(spi_data_wr), + .data_o(spi_data_rd), + // SPI interface + .spi_clk_o(spi_clk_o), + .spi_ss_o(/*open */), + .spi_mosi_o(spi_mosi_o), + .spi_miso_i(spi_miso_i) +); + +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + spi_ss_o <= 1'b1; + spi_start <= 1'b0; + spi_data_wr <= 8'h00; + end + else + begin + + spi_start <= 1'b0; + + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `SPI_MASTER_CTRL : + begin + spi_ss_o <= data_i[0]; + end + + `SPI_MASTER_DATA : + begin + spi_data_wr <= data_i[7:0]; + spi_start <= 1'b1; + end + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + `SPI_MASTER_STAT : + data_o <= {31'h00000000, spi_busy}; + + `SPI_MASTER_DATA : + data_o <= {24'h000000, spi_data_rd}; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +endmodule Index: peripheral/timer_defs.v =================================================================== --- peripheral/timer_defs.v (nonexistent) +++ peripheral/timer_defs.v (revision 9) @@ -0,0 +1,45 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define TIMER_SYSTICK_VAL 8'h00 +`define TIMER_HIRES 8'h04 Index: peripheral/uart_periph.v =================================================================== --- peripheral/uart_periph.v (nonexistent) +++ peripheral/uart_periph.v (revision 9) @@ -0,0 +1,198 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "uart_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module uart_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + intr_o, + + // UART + tx_o, + rx_i, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] UART_DIVISOR = 1; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +output intr_o /*verilator public*/; + +output tx_o /*verilator public*/; +input rx_i /*verilator public*/; + +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- +reg [31:0] data_o; + +// UART +reg [7:0] uart_tx_data; +wire [7:0] uart_rx_data; +reg uart_wr; +reg uart_rd; +wire uart_tx_busy; +wire uart_rx_avail; + +//----------------------------------------------------------------- +// Instantiation +//----------------------------------------------------------------- + +// UART +uart +#( + .UART_DIVISOR(UART_DIVISOR) +) +u1_uart +( + .clk_i(clk_i), + .rst_i(rst_i), + .data_i(uart_tx_data), + .data_o(uart_rx_data), + .wr_i(uart_wr), + .rd_i(uart_rd), + .tx_busy_o(uart_tx_busy), + .rx_ready_o(uart_rx_avail), + .rxd_i(rx_i), + .txd_o(tx_o) +); + +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + uart_tx_data <= 8'h00; + uart_wr <= 1'b0; + end + else + begin + + uart_wr <= 1'b0; + + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `UART_UDR : + begin + uart_tx_data <= data_i[7:0]; + uart_wr <= 1'b1; + end + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + uart_rd <= 1'b0; + end + else + begin + uart_rd <= 1'b0; + + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + `UART_USR : + data_o <= {27'h0000000, 1'b0, uart_tx_busy, 1'b0, 1'b0, uart_rx_avail}; + + `UART_UDR : + begin + data_o <= {24'h000000,uart_rx_data}; + uart_rd <= 1'b1; + end + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +//----------------------------------------------------------------- +// Assignments +//----------------------------------------------------------------- +assign intr_o = uart_rx_avail; + +endmodule Index: peripheral/intr_periph.v =================================================================== --- peripheral/intr_periph.v (nonexistent) +++ peripheral/intr_periph.v (revision 9) @@ -0,0 +1,233 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "intr_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module intr_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + intr_o, + + // Interrupts + intr0_i, + intr1_i, + intr2_i, + intr3_i, + intr4_i, + intr5_i, + intr6_i, + intr7_i, + intr_ext_i, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter EXTERNAL_INTERRUPTS = 1; +parameter INTERRUPT_COUNT = EXTERNAL_INTERRUPTS + 8; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +output intr_o /*verilator public*/; + +input intr0_i /*verilator public*/; +input intr1_i /*verilator public*/; +input intr2_i /*verilator public*/; +input intr3_i /*verilator public*/; +input intr4_i /*verilator public*/; +input intr5_i /*verilator public*/; +input intr6_i /*verilator public*/; +input intr7_i /*verilator public*/; +input [(EXTERNAL_INTERRUPTS - 1):0] intr_ext_i /*verilator public*/; +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- +reg [31:0] data_o; +reg intr_o; + +// IRQ Status +wire intr_in; +reg [INTERRUPT_COUNT-1:0] irq_status; +reg [INTERRUPT_COUNT-1:0] irq_mask; +reg [INTERRUPT_COUNT-1:0] v_irq_status; + +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + irq_status <= {(INTERRUPT_COUNT){1'b0}}; + irq_mask <= {(INTERRUPT_COUNT){1'b0}}; + intr_o <= 1'b0; + end + else + begin + + // Get current IRQ status + v_irq_status = irq_status; + + // IRQ0 + if (intr0_i == 1'b1) + v_irq_status[0] = 1'b1; + + // IRQ1 + if (intr1_i == 1'b1) + v_irq_status[1] = 1'b1; + + // IRQ2 + if (intr2_i == 1'b1) + v_irq_status[2] = 1'b1; + + // IRQ3 + if (intr3_i == 1'b1) + v_irq_status[3] = 1'b1; + + // IRQ4 + if (intr4_i == 1'b1) + v_irq_status[4] = 1'b1; + + // IRQ5 + if (intr5_i == 1'b1) + v_irq_status[5] = 1'b1; + + // IRQ6 + if (intr6_i == 1'b1) + v_irq_status[6] = 1'b1; + + // IRQ7 + if (intr7_i == 1'b1) + v_irq_status[7] = 1'b1; + + // External interrupts + begin : ext_ints_loop + integer i; + for (i=0; i< EXTERNAL_INTERRUPTS; i=i+1) + begin + if (intr_ext_i[i] == 1'b1) + v_irq_status[(`IRQ_EXT_FIRST + i)] = 1'b1; + end + end + + // Update IRQ status + irq_status <= v_irq_status; + + // Generate interrupt based on masked status + intr_o <= ((v_irq_status & irq_mask) != {(INTERRUPT_COUNT){1'b0}}) ? 1'b1 : 1'b0; + + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `IRQ_MASK_SET : + irq_mask <= (irq_mask | data_i[INTERRUPT_COUNT-1:0]); + + `IRQ_MASK_CLR : + irq_mask <= (irq_mask & ~ (data_i[INTERRUPT_COUNT-1:0])); + + `IRQ_STATUS : // (IRQ Acknowledge) + irq_status <= (v_irq_status & ~ (data_i[INTERRUPT_COUNT-1:0])); + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + `IRQ_MASK_SET : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask}; + + `IRQ_MASK_CLR : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask}; + + `IRQ_STATUS : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_status}; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +endmodule Index: peripheral/gpio_periph.v =================================================================== --- peripheral/gpio_periph.v (nonexistent) +++ peripheral/gpio_periph.v (revision 9) @@ -0,0 +1,287 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "gpio_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module gpio_periph +( + // General + clk_i, + rst_i, + intr_o, + + // Ports + gpio_i, + gpio_o, + gpio_out_en_o, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter GPIO_WIDTH = 8; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +output intr_o /*verilator public*/; +input [GPIO_WIDTH-1:0] gpio_i /*verilator public*/; +output [GPIO_WIDTH-1:0] gpio_o /*verilator public*/; +output [GPIO_WIDTH-1:0] gpio_out_en_o /*verilator public*/; +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- + +reg [31:0] data_o; +wire[GPIO_WIDTH-1:0] gpio_o; +wire[GPIO_WIDTH-1:0] gpio_out_en_o; +reg intr_o; + +reg [GPIO_WIDTH-1:0] gpio_out; +reg [GPIO_WIDTH-1:0] gpio_in; +reg [GPIO_WIDTH-1:0] gpio_in_last; +reg [GPIO_WIDTH-1:0] gpio_in_sync; +reg [GPIO_WIDTH-1:0] gpio_out_en; +reg [GPIO_WIDTH-1:0] gpio_int_mask; +reg [GPIO_WIDTH-1:0] gpio_int_polarity; +reg [GPIO_WIDTH-1:0] gpio_int_edge; + +//----------------------------------------------------------------- +// Resync inputs +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + gpio_in_sync <= {(GPIO_WIDTH){1'b0}}; + gpio_in <= {(GPIO_WIDTH){1'b0}}; + end + else + begin + gpio_in_sync <= gpio_i; + gpio_in <= gpio_in_sync; + end +end + +//----------------------------------------------------------------- +// GPIO interrupt handling +//----------------------------------------------------------------- +reg v_gpio_in; +reg v_intr_out; + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + gpio_in_last <= {(GPIO_WIDTH){1'b0}}; + intr_o <= 1'b0; + end + else + begin + gpio_in_last <= gpio_in; + + v_intr_out = 1'b0; + + // GPIO interrupt? + begin : ext_ints_loop + integer i; + for (i=0; i< GPIO_WIDTH; i=i+1) + begin + + // Input & interrupt enabled on this input + if (gpio_out_en[i] == 1'b0 && gpio_int_mask[i] == 1'b1) + begin + // Level sensitive interrupt + if (gpio_int_edge[i] == 1'b0) + begin + v_gpio_in = gpio_in[i]; + + // Invert polarity for active low interrupts? + if (gpio_int_polarity[i] == 1'b0) + v_gpio_in = !v_gpio_in; + + // Interrupt active? + if (v_gpio_in == 1'b1) + v_intr_out = 1'b1; + end + // Edge sensitive interrupt + else + begin + + // Falling edge triggered + if (gpio_int_polarity[i] == 1'b0) + begin + + // Pin H -> L + if (gpio_in_last[i] == 1'b1 && gpio_in[i] == 1'b0) + v_intr_out = 1'b1; + + end + // Rising edge triggered + else + begin + + // Pin L -> H + if (gpio_in_last[i] == 1'b0 && gpio_in[i] == 1'b1) + v_intr_out = 1'b1; + + end + end + end + + end + end + + intr_o <= v_intr_out; + end +end + +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + gpio_out <= {(GPIO_WIDTH){1'b0}}; + gpio_out_en <= {(GPIO_WIDTH){1'b1}}; + gpio_int_mask <= {(GPIO_WIDTH){1'b0}}; + gpio_int_polarity <= {(GPIO_WIDTH){1'b0}}; + gpio_int_edge <= {(GPIO_WIDTH){1'b0}}; + end + else + begin + + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `GPIO_OUT : + gpio_out <= data_i[GPIO_WIDTH-1:0]; + + `GPIO_DIR : + gpio_out_en <= data_i[GPIO_WIDTH-1:0]; + + `GPIO_INT_MASK : + gpio_int_mask <= data_i[GPIO_WIDTH-1:0]; + + `GPIO_INT_POLARITY : + gpio_int_polarity <= data_i[GPIO_WIDTH-1:0]; + + `GPIO_INT_EDGE : + gpio_int_edge <= data_i[GPIO_WIDTH-1:0]; + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + `GPIO_OUT : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_out}; + + `GPIO_DIR : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_out_en}; + + `GPIO_IN : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_in}; + + `GPIO_INT_MASK : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_int_mask}; + + `GPIO_INT_POLARITY : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_int_polarity}; + + `GPIO_INT_EDGE : + data_o <= {{(32-GPIO_WIDTH){1'b0}}, gpio_int_edge}; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +//----------------------------------------------------------------- +// Assignments +//----------------------------------------------------------------- +assign gpio_o = gpio_out; +assign gpio_out_en_o = gpio_out_en; + +endmodule Index: peripheral/spi_master.v =================================================================== --- peripheral/spi_master.v (nonexistent) +++ peripheral/spi_master.v (revision 9) @@ -0,0 +1,214 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Module +//----------------------------------------------------------------- +module spi_master +( + // Clocking & Reset + clk_i, + rst_i, + // Control & Status + start_i, + done_o, + busy_o, + // Data + data_i, + data_o, + // SPI Bus + spi_clk_o, + spi_ss_o, + spi_mosi_o, + spi_miso_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] CLK_DIV = 32; +parameter [31:0] TRANSFER_WIDTH = 8; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +input start_i /*verilator public*/; +output done_o /*verilator public*/; +output busy_o /*verilator public*/; +input [(TRANSFER_WIDTH - 1):0] data_i /*verilator public*/; +output [(TRANSFER_WIDTH - 1):0] data_o /*verilator public*/; +output spi_clk_o /*verilator public*/; +output spi_ss_o /*verilator public*/; +output spi_mosi_o /*verilator public*/; +input spi_miso_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg running; +integer cycle_count; +reg [(TRANSFER_WIDTH - 1):0] shift_reg; +reg spi_clk_gen; +reg last_clk_gen; +integer clk_div_count; +reg done_o; +reg spi_ss_o; +reg spi_clk_o; + +//----------------------------------------------------------------- +// Implementation +//----------------------------------------------------------------- + +// SPI Clock Generator +always @ (posedge clk_i or posedge rst_i ) +begin + // Async Reset + if (rst_i == 1'b1) + begin + clk_div_count <= 0; + spi_clk_gen <= 1'b0; + end + else + begin + // SPI transfer active? + if (running == 1'b1) + begin + // Clock divider cycle_count matched? + if (clk_div_count == (CLK_DIV - 1)) + begin + // Toggle clock (input to SPI transfer process) + spi_clk_gen <= ~(spi_clk_gen); + + // Reset counter + clk_div_count <= 0; + end + // Increment SPI clock divider counter + else + clk_div_count <= (clk_div_count + 1); + end + else // (!running) + spi_clk_gen <= 1'b0; + end +end + +// SPI transfer process +always @ (posedge clk_i or posedge rst_i ) +begin + // Async Reset + if (rst_i == 1'b1) + begin + cycle_count <= 0; + shift_reg <= {(TRANSFER_WIDTH - 0){1'b0}}; + last_clk_gen <= 1'b0; + spi_clk_o <= 1'b0; + running <= 1'b0; + done_o <= 1'b0; + spi_ss_o <= 1'b0; + end + else + begin + + // Update previous SCLK value + last_clk_gen <= spi_clk_gen; + + done_o <= 1'b0; + + //------------------------------- + // SPI = IDLE + //------------------------------- + if (running == 1'b0) + begin + // Wait until start_i = 1 to start_i transfer + if (start_i == 1'b1) + begin + cycle_count <= 0; + shift_reg <= data_i; + running <= 1'b1; + spi_ss_o <= 1'b1; + end + end + else + //------------------------------- + // SPI = RUNNING + //------------------------------- + begin + // SCLK 1->0 - Falling Edge + if ((last_clk_gen == 1'b1) && (spi_clk_gen == 1'b0)) + begin + // SCLK_OUT = L + spi_clk_o <= 1'b0; + + // Increment cycle counter + cycle_count <= (cycle_count + 1); + + // Shift left & add MISO to LSB + shift_reg <= {shift_reg[(TRANSFER_WIDTH - 2):0],spi_miso_i}; + + // End of SPI transfer reached + if (cycle_count == (TRANSFER_WIDTH - 1)) + begin + // Go back to IDLE running + running <= 1'b0; + + // Set transfer complete flags + done_o <= 1'b1; + spi_ss_o <= 1'b0; + end + end + // SCLK 0->1 - Rising Edge + else if ((last_clk_gen == 1'b0) & (spi_clk_gen == 1'b1)) + begin + // SCLK_OUT = H + spi_clk_o <= 1'b1; + end + end + end +end + +//----------------------------------------------------------------- +// Combinatorial Logic +//----------------------------------------------------------------- +assign spi_mosi_o = shift_reg[(TRANSFER_WIDTH - 1)]; +assign data_o = shift_reg; +assign busy_o = ((running == 1'b1) || (start_i == 1'b1)) ? 1'b1 : 1'b0; + +endmodule Index: peripheral/timer_periph.v =================================================================== --- peripheral/timer_periph.v (nonexistent) +++ peripheral/timer_periph.v (revision 9) @@ -0,0 +1,282 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "timer_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module timer_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + + // Interrupts + intr_systick_o, + intr_hires_o, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] CLK_KHZ = 12288; +parameter SYSTICK_INTR_MS = 1; +parameter ENABLE_SYSTICK_TIMER = "ENABLED"; +parameter ENABLE_HIGHRES_TIMER = "ENABLED"; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; + +output intr_systick_o /*verilator public*/; +output intr_hires_o /*verilator public*/; + +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- + +reg [31:0] data_o; + +// Systick Timer +reg systick_event; +reg [31:0] systick_count; +reg [31:0] systick_clk_count; + +// Hi-res system clock tick counter +reg hr_timer_intr; +reg [31:0] hr_timer_cnt; +reg [31:0] hr_timer_match; + +//----------------------------------------------------------------- +// Systick +//----------------------------------------------------------------- +generate +if (ENABLE_SYSTICK_TIMER == "ENABLED") +begin + + // SysTick Timer (1 ms resolution) + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + systick_count <= 32'h00000000; + systick_clk_count <= 32'h00000000; + systick_event <= 1'b0; + end + else + begin + systick_event <= 1'b0; + + if (systick_clk_count == CLK_KHZ) + begin + systick_count <= (systick_count + 1); + systick_event <= 1'b1; + systick_clk_count <= 32'h00000000; + end + else + systick_clk_count <= (systick_clk_count + 1); + end + end + + // SysTick Interrupt + integer systick_event_count; + reg systick_event_intr; + + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + systick_event_count <= 0; + systick_event_intr <= 1'b0; + end + else + begin + systick_event_intr <= 1'b0; + + if (systick_event) + begin + systick_event_count <= (systick_event_count + 1); + + if (systick_event_count == (SYSTICK_INTR_MS-1)) + begin + systick_event_intr <= 1'b1; + systick_event_count <= 0; + end + end + end + end + + assign intr_systick_o = systick_event_intr; +end +else +begin + // Systick disabled + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + systick_count <= 32'h00000000; + else + systick_count <= 32'h00000000; + end + + assign intr_systick_o = 1'b0; +end +endgenerate + +//----------------------------------------------------------------- +// Hi Resolution Timer +//----------------------------------------------------------------- +generate +if (ENABLE_HIGHRES_TIMER == "ENABLED") +begin + + always @ (posedge rst_i or posedge clk_i) + begin + if (rst_i == 1'b1) + begin + hr_timer_cnt <= 32'h00000000; + hr_timer_intr <= 1'b0; + end + else + begin + hr_timer_intr <= 1'b0; + + // Clock tick counter + hr_timer_cnt <= (hr_timer_cnt + 1); + + // Hi-res Timer IRQ + if ((hr_timer_match != 32'h00000000) && (hr_timer_match == hr_timer_cnt)) + hr_timer_intr <= 1'b1; + end + end + + assign intr_hires_o = hr_timer_intr; +end +else +begin + // Hi resolution timer disabled + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + hr_timer_cnt <= 32'h00000000; + else + hr_timer_cnt <= 32'h00000000; + end + + assign intr_hires_o = 1'b0; +end +endgenerate +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + hr_timer_match <= 32'h00000000; + end + else + begin + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `TIMER_HIRES : + hr_timer_match <= data_i; + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + // 32-bit systick/1ms counter + `TIMER_SYSTICK_VAL : + data_o <= systick_count; + + // Hi res timer (clock rate) + `TIMER_HIRES : + data_o <= hr_timer_cnt; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +endmodule Index: peripheral/spim_defs.v =================================================================== --- peripheral/spim_defs.v (nonexistent) +++ peripheral/spim_defs.v (revision 9) @@ -0,0 +1,46 @@ +//----------------------------------------------------------------- +// MPX 32-bit Soft-Core Processor +// V0.1 +// Ultra-Embedded.com +// Copyright 2011 - 2012 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +// +// If you would like a version with a different license for use +// in commercial projects please contact the above email address +// for more details. +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2012 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define SPI_MASTER_CTRL 8'h00 +`define SPI_MASTER_STAT 8'h00 +`define SPI_MASTER_DATA 8'h04

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.