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

Subversion Repositories softavrcore

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /softavrcore
    from Rev 2 to Rev 1
    Reverse comparison

Rev 2 → Rev 1

/trunk/synth/main.v File deleted \ No newline at end of file
trunk/synth/main.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/top.pcf =================================================================== --- trunk/synth/top.pcf (revision 2) +++ trunk/synth/top.pcf (nonexistent) @@ -1 +0,0 @@ -link top-ct256.pcf \ No newline at end of file
trunk/synth/top.pcf Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/top-ct256.pcf =================================================================== --- trunk/synth/top-ct256.pcf (revision 2) +++ trunk/synth/top-ct256.pcf (nonexistent) @@ -1,35 +0,0 @@ -# iCE40HX8K-CT256 ICE40HX8K-B-EVN - -set_io led[7] B5 -set_io led[6] B4 -set_io led[5] A2 -set_io led[4] A1 -set_io led[3] C5 -set_io led[2] C4 -set_io led[1] B3 -set_io led[0] C3 - -set_io hwclk J3 - -# This is the input for the FPGA top module: -set_io ftdi_rx B10 # input -# This is the output for the FPGA top module: -set_io ftdi_tx B12 # output - -set_io pin_scl0 D16 -set_io pin_sda0 C16 - -# Another 5 ports connected to the FTDI transceiver: -#set_io ftdi_nrts B13 # input -#set_io ftdi_ncts A15 # output -#set_io ftdi_ndtr A16 # input -#set_io ftdi_ndsr B14 # output -#set_io ftdi_ndcd B15 # output -#set_io ftdi_rx B9 # orange -#set_io ftdi_tx A7 # yellow -#set_io nss B8 -#set_io sck A9 -#set_io miso A10 -#set_io mosi A11 - - Index: trunk/synth/avr_io_out.v =================================================================== --- trunk/synth/avr_io_out.v (revision 2) +++ trunk/synth/avr_io_out.v (nonexistent) @@ -1 +0,0 @@ -link ../peripherals/avr_io_out.v \ No newline at end of file
trunk/synth/avr_io_out.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/Makefile =================================================================== --- trunk/synth/Makefile (revision 2) +++ trunk/synth/Makefile (nonexistent) @@ -1,27 +0,0 @@ -SHELL=/bin/bash - -SYNTH=yosys -PNR=nextpnr-ice40 -PACK=icepack - -DEVICE=hx8k -#PACKAGE=bg121 -PACKAGE=ct256 - -.PHONY: all clean - -TOP=top - -all: $(TOP).bin - -$(TOP).json: $(TOP).v - $(SYNTH) -q -p 'synth_ice40 -top $(TOP) -json $(TOP).json' $(TOP).v - -$(TOP).asc: $(TOP).json $(TOP).pcf - $(PNR) --$(DEVICE) --package $(PACKAGE) --json $(TOP).json --pcf $(TOP).pcf --seed 1 --randomize-seed --asc $(TOP).asc - -$(TOP).bin: $(TOP).asc - $(PACK) $(TOP).asc $(TOP).bin - -clean: - rm -f $(TOP).bin $(TOP).asc $(TOP).json Index: trunk/synth/avr_io_uart.v =================================================================== --- trunk/synth/avr_io_uart.v (revision 2) +++ trunk/synth/avr_io_uart.v (nonexistent) @@ -1 +0,0 @@ -link ../peripherals/avr_io_uart.v \ No newline at end of file
trunk/synth/avr_io_uart.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/top-digilent_nexys_a7-cx7a100t.xdc =================================================================== --- trunk/synth/top-digilent_nexys_a7-cx7a100t.xdc (revision 2) +++ trunk/synth/top-digilent_nexys_a7-cx7a100t.xdc (nonexistent) @@ -1,11 +0,0 @@ -set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN E3 } [get_ports hwclk] -set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN H17 } [get_ports {led[0]}] -set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN K15 } [get_ports {led[1]}] -set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN C4 } [get_ports ftdi_rx] -set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN D4 } [get_ports ftdi_tx] - -create_clock -period 10 [get_ports hwclk] - -set_property CONFIG_VOLTAGE 3.3 [current_design] -set_property CFGBVS VCCO [current_design] - Index: trunk/synth/flash_array.v =================================================================== --- trunk/synth/flash_array.v (revision 2) +++ trunk/synth/flash_array.v (nonexistent) @@ -1 +0,0 @@ -link ../build/flash_array.v \ No newline at end of file
trunk/synth/flash_array.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/main.mem =================================================================== --- trunk/synth/main.mem (revision 2) +++ trunk/synth/main.mem (nonexistent) @@ -1 +0,0 @@ -link ../build/main.mem \ No newline at end of file
trunk/synth/main.mem Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/flash.v =================================================================== --- trunk/synth/flash.v (revision 2) +++ trunk/synth/flash.v (nonexistent) @@ -1,26 +0,0 @@ -module flash - #( parameter flash_file = "main.mem", - parameter flash_width = 10 - ) - ( input clk, - input mem_ce, - input [flash_width-1:0] mem_a, - output [15:0] mem_d - ); - -reg [15:0] flash_array [0:2**flash_width-1]; - -reg [15:0] data_read; - -assign mem_d = data_read; - -always @(posedge clk) begin - if (mem_ce) data_read <= flash_array[mem_a]; -end - -initial begin -// $readmemh(flash_file, flash_array); - `include "flash_array.v" -end - -endmodule Index: trunk/synth/avr_io_timer.v =================================================================== --- trunk/synth/avr_io_timer.v (revision 2) +++ trunk/synth/avr_io_timer.v (nonexistent) @@ -1 +0,0 @@ -link ../peripherals/avr_io_timer.v \ No newline at end of file
trunk/synth/avr_io_timer.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/top-bg121.pcf =================================================================== --- trunk/synth/top-bg121.pcf (revision 2) +++ trunk/synth/top-bg121.pcf (nonexistent) @@ -1,25 +0,0 @@ -# GRBAlpha ballon payload board - -set_io led[1] A4 -set_io led[0] B4 - -set_io hwclk L5 - -# This is the input for the FPGA, signal comes from the FT2232: -set_io ftdi_rx K7 -# This is the output for the FPGA, signal goes to the FT2232: -set_io ftdi_tx L7 - -set_io sseg4[12] B2 # DD -set_io sseg4[11] D2 # D1 -set_io sseg4[10] C2 # D2 -set_io sseg4[9] A2 # D3 -set_io sseg4[8] B3 # D4 -set_io sseg4[7] G2 # a -set_io sseg4[6] E2 # b -set_io sseg4[5] H1 # c -set_io sseg4[4] E1 # d -set_io sseg4[3] F1 # e -set_io sseg4[2] F2 # f -set_io sseg4[1] D1 # g -set_io sseg4[0] G1 # dp Index: trunk/synth/ram.v =================================================================== --- trunk/synth/ram.v (revision 2) +++ trunk/synth/ram.v (nonexistent) @@ -1,25 +0,0 @@ -module ram - #( parameter ram_width = 9 - ) - ( input clk, - input re, - input we, - input [ram_width-1:0] addr, - output [7:0] data_read, - input [7:0] data_write - ); - -reg [7:0] ram_array [0:2**ram_width-1]; -reg [7:0] data_out; - -assign data_read = data_out; - -always @(posedge clk) begin - if (we) ram_array[addr] <= data_write; -end - -always @(posedge clk) begin - if (re) data_out <= ram_array[addr]; -end - -endmodule Index: trunk/synth/avr_core.v =================================================================== --- trunk/synth/avr_core.v (revision 2) +++ trunk/synth/avr_core.v (nonexistent) @@ -1 +0,0 @@ -link ../core/avr_core.v \ No newline at end of file
trunk/synth/avr_core.v Property changes : Deleted: svn:special ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/synth/top.v =================================================================== --- trunk/synth/top.v (revision 2) +++ trunk/synth/top.v (nonexistent) @@ -1,237 +0,0 @@ -`include "avr_core.v" -`include "avr_io_out.v" -`include "avr_io_uart.v" -`include "avr_io_timer.v" -`include "main.v" -//`include "flash.v" -`include "ram.v" - -//`include "avr_io_spi.v" - -/*****************************************************************************/ - -module priority_encoder ( input [3:0] irq_lines , output iflag, output reg [1:0] ivect ); - -//reg [1:0] ivect; - -always @(*) begin - if (irq_lines[0]) ivect = 0; - else if (irq_lines[1]) ivect = 1; - else if (irq_lines[2]) ivect = 2; - else if (irq_lines[3]) ivect = 3; - else ivect = 0; -end - -assign iflag = |irq_lines; - -endmodule - -/*****************************************************************************/ - -module top - ( input hwclk, - output [7:0] led, - input ftdi_rx, - output ftdi_tx, - inout pin_scl0, - inout pin_sda0 - - ); - -//assign sseg4 = 13'b1_1111_1111_1111; - -wire clk; - -parameter pmem_width = 10; -parameter dmem_width = 9; - -wire pmem_ce; -wire [pmem_width-1:0] pmem_a; -wire [15:0] pmem_d; - -wire dmem_re; -wire dmem_we; -wire [dmem_width-1:0] dmem_a; -wire [7:0] dmem_di; -wire [7:0] dmem_do; - -wire io_re; -wire io_we; -wire [5:0] io_a; -wire [7:0] io_do; - - -SB_PLL40_CORE - #( .FEEDBACK_PATH("SIMPLE"), - .PLLOUT_SELECT("GENCLK"), - .ENABLE_ICEGATE("0"), - .DIVR(4'b0000), - .DIVF(7'b0111111), - .DIVQ(3'b100), - .FILTER_RANGE(3'b001) - ) -pll - ( .RESETB(1'b1), - .BYPASS(1'b1), - .EXTFEEDBACK(1'b0), - .LATCHINPUTVALUE(1'b0), - .DYNAMICDELAY(8'b00000000), - .REFERENCECLK(hwclk), - .SDI(1'b0), - .SCLK(1'b0), - .PLLOUTGLOBAL(clk) - ); - -//reg [1:0] clkcnt; -//always @(posedge hwclk) clkcnt <= clkcnt + 1; -//assign clk = clkcnt[1]; -//BUFG clkcrt ( .I(clkcnt[1]), .O(clk) ); - -/*****************************************************************************/ - -ram core0_ram ( clk, dmem_re, dmem_we, dmem_a, dmem_di, dmem_do ); -defparam core0_ram.ram_width = dmem_width; - -flash core0_flash ( clk, pmem_ce,pmem_a, pmem_d ); -//defparam core0_flash.flash_width = pmem_width; - -/*****************************************************************************/ - -wor [7:0] io_di; - -`define TIMER0 - -`ifdef TIMER0 -wire timer0_io_select = (io_a[5:2] == 4'b0010); -wire timer0_io_re = timer0_io_select & io_re; -wire timer0_io_we = timer0_io_select & io_we; -wire timer0_irq; - -avr_io_timer timer0 - ( clk, 1'b0, - timer0_io_re, timer0_io_we, io_a[1:0], io_di, io_do, - timer0_irq - ); -`else -wire timer0_irq = 0; -`endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -`define PORT0 - -`ifdef PORT0 -wire port0_io_select = (io_a[5:0] == 6'b000100); -wire port0_io_re = (port0_io_select ? io_re : 1'b0); -wire port0_io_we = (port0_io_select ? io_we : 1'b0); -wire [7:0] port0_out; - -avr_io_out port0 - ( clk, 1'b0, - port0_io_re, port0_io_we, io_di, io_do, - port0_out - ); - -assign led = port0_out; -`else -assign led = 8'b00000000; -`endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -`define UART0 - -`ifdef UART0 -wire uart0_io_select = (io_a[5:2] == 4'b0000); -wire uart0_io_re = (uart0_io_select ? io_re : 1'b0); -wire uart0_io_we = (uart0_io_select ? io_we : 1'b0); -wire uart0_txd; -wire uart0_rxd; -wire [2:0] uart0_irq; - -assign ftdi_tx = uart0_txd; -assign uart0_rxd = ftdi_rx; - -avr_io_uart uart0 - ( clk, 1'b0, - uart0_io_re, uart0_io_we, io_a[1:0], io_di, io_do, - uart0_txd, uart0_rxd, - uart0_irq - ); -`else -assign ftdi_tx = ftdi_rx; -wire [2:0] uart0_irq; -assign uart0_irq = 3'b000; -`endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// `define SPI0 - -`ifdef SPI0 -wire spi0_io_select = (io_a[5:2] == 4'b0100); -wire spi0_io_re = (spi0_io_select ? io_re : 1'b0); -wire spi0_io_we = (spi0_io_select ? io_we : 1'b0); -wire spi0_enable; -wire spi0_master; -wire spi0_master_out; -wire spi0_master_in; -wire spi0_master_clk; -wire spi0_master_select; -wire spi0_slave_out; - -`define ASYNC_SPI_SAMPLING - -`ifdef ASYNC_SPI_SAMPLING -assign mosi = spi0_master_out; -assign spi0_master_in = miso; -assign sck = spi0_master_clk; -assign nss = ~spi0_master_select; -`else -reg mosi, spi0_master_in, sck, nss; -always @(posedge clk) begin - mosi <= spi0_master_out; - spi0_master_in <= miso; - sck <= spi0_master_clk; - nss <= ~spi0_master_select; -end -`endif - -avr_io_spi spi0 - ( clk, 1'b0, - spi0_io_re, spi0_io_we, io_a[1:0], io_di, io_do, - spi0_enable, spi0_master, - spi0_master_clk, spi0_master_out, spi0_master_in, spi0_master_select, - 1'b0, 1'b0, spi0_slave_out, 1'b0 - ); -`else - -//assign sck = 1'b0; -//assign mosi = 1'b0; -//assign nss = 1'b1; - -`endif - - -/*****************************************************************************/ - -wire iflag; -wire [1:0] ivect; - -priority_encoder irq0 ( { uart0_irq[2], 1'b0, timer0_irq, 1'b0 }, iflag, ivect ); - -avr_core core0 - ( clk, 1'b0, - pmem_ce, pmem_a, pmem_d, - dmem_re, dmem_we, dmem_a, dmem_di, dmem_do, - io_re, io_we, io_a, io_di, io_do, - iflag, ivect - ); - -defparam core0.pmem_width = pmem_width; -defparam core0.dmem_width = dmem_width; -defparam core0.interrupt = 1; -defparam core0.intr_width = 2; - -endmodule - Index: trunk/README =================================================================== --- trunk/README (revision 2) +++ trunk/README (nonexistent) @@ -1,121 +0,0 @@ -Soft AVR Core + Interfaces -========================== - -Introduction ------------- - -This package is a full-stack implementation of the AVR 2-stage pipeline, -featuring synthesis for AVR2 (classic core), AVR2.5 (classic plus), AVR3 -(with extended program memory), AVR4 (enhanced core) and AVR5 (enhanced core -with extended program memory). Interrupts are supported with customized number -of IRQ vector width. - -The project comes with some example peripherals, such as UART, SPI, a -basic timer, output port and SysTick timer. - -Synthetized and tested using various tools, including free & open source -packages: - - iCE40HX8K-BG121 and iCE40HX8K-CT256 (on ICE40HX8K-B-EVN and custom -design boards): Project IceStorm: yosys-0.9, nextpnr-ice40 and icestorm -utilities; - - iCE40HX8K-BG121 and iCE40HX8K-CT256 (on ICE40HX8K-B-EVN and custom -design boards): Lattice iCEcube2; and - - XA7A100T-1CSG324 (on a Digilent Nexys A7 board): Xilinx Vivado 2019.1. - -Software run by the core can seamlessly be built with the AVR-GCC -toolchain. This bundle includes utilities aiding the conversion from ELF -output to BRAM initializations (designed for iCE40 EBRs) or generic -synchronous ROM interface to set up the initial program memory. A -configurable startup code (crt0.s) is included in the package with -options to be matched to the synthetized core architecture. - -Availability ------------- - -This package is available from https://szofi.net/pub/verilog/softavrcore/. -Select the softavrcore-latest.tar.gz file for the latest version. Comments -are welcomed! Contact: Andras Pal . - -Getting started ---------------- - - - On a Linux system, install the following toolchains and utilities: - * gcc-avr - * avr-libc - * binutils-avr - * icestorm - * yosys - * nextpnr-ice40 - then enter `make` in the main directory. This will compile the example - C code (found in ./build) and then run the synthesis and place-and-route - targeted for the ICE40HX8K-B-EVN board. This step is automatically following - by the generation of the FPGA configuration bitstream for iCE40HX8K-CT256 - in the file top.bin. - - - On another operating systems for non-Lattice FPGA targets: - * use the corresponding AVR port to compile the source and create - the main.bin file. A working bash/awk is needed to automatically - create the *.v files containing the flash interface for this - virtual MCU. These are available on MacOS by default. On Windows, you - may need to install additional components (e.g. Cygwin). - * Collect the source *.v files, including the core (avr_core.v), - peripherals (avr_io_*.v), flash interface (main.v), data memory - (ram.v) and the top module (top.v) into a single directory _if_ your - operating system does not support symlinks. - * Import the top.v to your synthesis toolchain (icecube2, vivado, ...). - You can use the shipped *.pcf files for Lattice tools (such as - icecube2) without any further modifications. For Xilinx, you may - use the file top-digilent_nexys_a7-cx7a100t.xdc as a starting point, - or use it without any modifications for the Digilent Nexys A7 board. - -By default the example code (./build/main.c) sends the following series of -messages via the built-in secondary UART interface of the ICE40HX8K-B-EVN -board at 115200 baud: - [x] 0 => 0 - [x] 1 => 1 - [x] 2 => 4 - [x] 3 => 9 - [x] 4 => 16 - [x] 5 => 25 - [x] 6 => 36 - ... -Here the cadence is one message per minute. The cores and the C code expect -a 12MHz clock input for baud rate configuration and during the computation -of the timer delay. - -You may change the contents of the main() function to switch to another -examples. Note also that the example is fitted for 1024 words of program code -(i.e. 2048 bytes of program flash memory). Change top.v and ./build/Makefile -accordingly for larger (or smaller) program memory configurations. - -Known issues ------------- - - - LD/ST operations work only on data memory interface, not on the I/O -port and the register file. GCC is not known to generate such code unless -register mappings are explicitly indexed with the X, Y or Z pointer registers. -Since registers are not available directly for C code and I/O ports are -defined to be constants for all of the relevant peripherals, it is not -expected at all and access to those areas are seamlessly translated by GCC to -the faster MOV, IN and OUT instructions instead of LD/ST. - - SPM instruction is not supported, however, equivalent -self-programming interfaces can be synthetized by custom peripherals. - - Watchdog is not supported, however, equivalent functionality can be -synthetized by custom peripherals. - - Automatic interrupt acknowledgement is not supported at the moment. - - Fuse bits and in-system programming are not supported. These are, in -practice, nearly meaningless on such an FPGA-based CPU/MCU implementation. - - This soft AVR CPU is cycle compatible with the exception of the store -operations (LD, LDS, LDD, PUSH). These store operations runs faster by 1 cycle -compared to the AVR hardware. Use a preceeding or following NOP to be -cycle compatible with off-the-shelf AVR hardware. - -Coming soon ------------ - - - I2C peripheral - - CAN bus interface - - An implementation of the AVR architecture using a 4-stage pipeline - - FreeRTOS port - - some more detaild documentation - Index: trunk/doc/diagram.txt =================================================================== --- trunk/doc/diagram.txt (revision 2) +++ trunk/doc/diagram.txt (nonexistent) @@ -1,9 +0,0 @@ -This section is still to be done... - - /-----\ /-----\ /-----\ /-----\ -CLK: / \ / \ / \ / \ / - \-----/ \-----/ \-----/ \-----/ - - /-------------\ /-------------\ /-------------\ /-------------\ - < X X X X - \-------------/ \-------------/ \-------------/ \-------------/ Index: trunk/util/progmem-ice40.sh =================================================================== --- trunk/util/progmem-ice40.sh (revision 2) +++ trunk/util/progmem-ice40.sh (nonexistent) @@ -1,115 +0,0 @@ -#!/bin/bash - -infile="" - -depth=8 - -name=rom_16bit - -while [ -n "$1" ]; do - case "$1" in - -h|--help) - echo -e "Usage:\t$0 [-h|--help] [-w|--width ] <16-bit-image.bin>" - exit 0 - ;; - -w|--width|-d|--depth) - depth="$2" - shift - ;; - -n|--name) - name="$2" - shift - ;; - -*) - echo -e "$0: error: invalid command line argument near '$1'." >> /dev/stderr - exit 1 - ;; - *) - infile="$1" - ;; - esac; shift -done - -if ! [ -n "$infile" ] || ! [ -f "$infile" ]; then - echo "$0: error: input file is missing or not found." >> /dev/stderr - exit 1 -fi - -nword=$((1<
trunk/util/progmem-ice40.sh Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/util/progmem-generic.sh =================================================================== --- trunk/util/progmem-generic.sh (revision 2) +++ trunk/util/progmem-generic.sh (nonexistent) @@ -1,67 +0,0 @@ -#!/bin/bash - -infile="" - -depth=8 - -name=rom_16bit - -while [ -n "$1" ]; do - case "$1" in - -h|--help) - echo -e "Usage:\t$0 [-h|--help] [-w|--width ] <16-bit-image.bin>" - exit 0 - ;; - -w|--width|-d|--depth) - depth="$2" - shift - ;; - -n|--name) - name="$2" - shift - ;; - -*) - echo -e "$0: error: invalid command line argument near '$1'." >> /dev/stderr - exit 1 - ;; - *) - infile="$1" - ;; - esac; shift -done - -if ! [ -n "$infile" ] || ! [ -f "$infile" ]; then - echo "$0: error: input file is missing or not found." >> /dev/stderr - exit 1 -fi - -nword=$((1<
trunk/util/progmem-generic.sh Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/build/main.c =================================================================== --- trunk/build/main.c (revision 2) +++ trunk/build/main.c (nonexistent) @@ -1,195 +0,0 @@ -#define F_CPU 12000000UL - -#include -#include -#include -#include -#include - -/*****************************************************************************/ - -#define __IOR(x) (*(volatile uint8_t *)(0x20+(x))) -#define __IOW(x) (*(volatile uint16_t *)(0x20+(x))) - -/*****************************************************************************/ - - -#define IO_BASE_UART0 0x00 -#define IO_BASE_PORTOUT0 0x04 -#define IO_BASE_TIMER0 0x08 - -/* uart.h */ - -#define UDR0 __IOR(IO_BASE_UART0+0x00) -#define UCSRA0 __IOR(IO_BASE_UART0+0x01) -#define UCSRB0 __IOR(IO_BASE_UART0+0x02) -#define UBRR0 __IOR(IO_BASE_UART0+0x03) - -/* UCSRA */ -#define RXB8 0 -#define PE 2 -#define DOR 3 -#define FE 4 -#define UDRE 5 -#define TXC 6 -#define RXC 7 - -/* UCSRB */ -#define TXB8 0 -#define UCSZ 1 -#define UPM0 2 -#define UPM1 3 -#define USBS 4 -#define UDRIE 5 -#define TXCIE 6 -#define RXCIE 7 - -/* timer.h */ - -#define TCNT0 __IOW(IO_BASE_TIMER0+0x00) -#define TCR0 __IOR(IO_BASE_TIMER0+0x02) -#define TSR0 __IOR(IO_BASE_TIMER0+0x03) - -#define TOF 7 /* timer overflow */ -#define TOFIE 7 /* timer overflow interrupt enable */ -#define TPRESC0 0 /* timer prescaler bit 0 */ -#define TPRESC1 1 /* timer prescaler bit 1 */ - -/* port.h */ - -#define PORTOUT0 __IOR(IO_BASE_PORTOUT0+0x00) - -/*****************************************************************************/ - -static int uart_putchar(char c, FILE *stream) -{ - loop_until_bit_is_set(UCSRA0, UDRE); - UDR0 = c; - return(0); -} - -static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); - -/*****************************************************************************/ - -/* RXC */ -ISR(_VECTOR(3)) -{ - uint8_t c; - c=UDR0; - if ( 'a' <= c && c <= 'z' ) c-=('a'-'A'); - UDR0=c; -} - -ISR(_VECTOR(1)) -{ - TCR0=TCR0; - PORTOUT0 ^= 0x02; -} - - -static inline void msleep(uint16_t msec) -{ - while ( msec ) - { _delay_loop_2((uint32_t)F_CPU/4000UL); - msec--; - } -} - -static void test_memory_buffer(void) -{ - static char * string="0123456789"; - uint8_t length=10,offset,cnt; - - msleep(10); - - offset=0; - cnt=0; - while ( 1 ) - { uint8_t c; - - while ( ! (UCSRA0&(1< %d\n",i,i*i); - msleep(1000); - i++; - } -} - -void test_interrupt(void) -{ - UCSRB0 |= (1< main.mem - -flash_array.v: main.mem - awk '{ printf("flash_array[%d]=16%ch%s;\n",n,39,$$1);n++; }' < main.mem > flash_array.v - -main.disasm: main.elf - $(OBJDUMP) -s -m $(ARCH) -d main.elf > main.disasm - -main.instr: main.disasm - expand < main.disasm | grep -v "file format" | awk '{ if ( substr($$1,length($$1))==":" ) print substr($$0,25,8); }' | sort | uniq | awk '{ print $$1; }' > main.instr - -main.v: main.bin - $(PROGMEM) --depth $(PMEM_DEPTH) --name flash main.bin > main.v - -clean: - rm -f $(TARGETS) *.o *.elf *.mem *.disasm *.hex *.bin Index: trunk/peripherals/avr_io_out.v =================================================================== --- trunk/peripherals/avr_io_out.v (revision 2) +++ trunk/peripherals/avr_io_out.v (nonexistent) @@ -1,42 +0,0 @@ -/*****************************************************************************/ -/* avr_io_out.v */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* (c) 2019-2020; Andras Pal */ -/*****************************************************************************/ - -module avr_io_out - ( input clk, - input rst, - - input io_re, - input io_we, - output [7:0] io_do, - input [7:0] io_di, - - output [7:0] port - ); - -reg [7:0] PORT; - -assign port[7:0] = PORT[7:0]; - -assign io_do = io_re ? PORT : 8'b00000000; - -always @(posedge clk) begin - - if (io_we) begin - PORT <= io_di; - end - -end - - -/*****************************************************************************/ -/* Debug section starts here */ - -/* end of debug section */ -/*****************************************************************************/ - -endmodule - -/*****************************************************************************/ Index: trunk/peripherals/avr_io_uart.v =================================================================== --- trunk/peripherals/avr_io_uart.v (revision 2) +++ trunk/peripherals/avr_io_uart.v (nonexistent) @@ -1,244 +0,0 @@ -/*****************************************************************************/ -/* avr_io_uart.v */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* (c) 2019-2020; Andras Pal */ -/*****************************************************************************/ - -module uart_tx (input clk, input [7:0] prescaler, input [7:0] tx_in, input strobe, output reg txd, output busy, output prefetch); - -parameter TX_STATE_IDLE = 0; -parameter TX_STATE_TRANSMIT = 1; - -reg state = TX_STATE_IDLE; - -//reg txd = 1; - -reg [7:0] count = 0; -reg [7:0] scaler_counter = 0; - -reg [7:0] dataout = 0; - -parameter count_step = 2; -assign busy = state; - -wire scaler_limit = (scaler_counter==0); -wire bit_limit = (count[3:0] == 4'b0000); -wire last_bit = (count[7:4]==4'd10); - -assign prefetch = ( state==TX_STATE_TRANSMIT ) & scaler_limit & bit_limit & last_bit; - -always @(posedge clk) begin - - if ( state==TX_STATE_IDLE && strobe ) begin - state <= TX_STATE_TRANSMIT; - txd <= 0; - count <= count_step; - dataout <= tx_in; - scaler_counter <= prescaler; - end else if ( state==TX_STATE_TRANSMIT && scaler_limit ) begin - if ( bit_limit ) begin - if ( last_bit ) begin - if ( strobe ) begin - txd <= 0; - count <= count_step; - dataout <= tx_in; - end else begin - txd <= 1; - state <= TX_STATE_IDLE; - end - end else begin - txd <= dataout[0]; - dataout <= { 1'b1, dataout[7:1] }; - count <= count + count_step; - end - end else begin - count <= count + count_step; - end - scaler_counter <= prescaler; - end else if ( state==TX_STATE_TRANSMIT ) begin - scaler_counter <= scaler_counter - 1; - end - -end - -endmodule - -/*****************************************************************************/ - -module uart_rx (input clk, input [7:0] prescaler, input rxd, input reset, output [7:0] rx_out, output reg avail); - -parameter STATE_IDLE = 0; -parameter STATE_STARTBIT = 2; -parameter STATE_RECEIVE = 3; - -reg [1:0] state = STATE_IDLE; - -reg [7:0] count = 0; -reg [7:0] scaler_counter = 0; - -reg [7:0] datain = 0; -//reg avail = 0; - -parameter count_step = 2; - -wire rx_sub_bit = ( state==STATE_RECEIVE && scaler_counter==0 ); -wire rx_bit = (rx_sub_bit && count[3:0] == 4'b0000); -wire rx_completed = (rx_bit && count[7:4]==4'd9 ); - -assign rx_out = datain; - -always @(posedge clk) begin - - if ( state==STATE_IDLE && rxd==0 ) begin - state <= STATE_STARTBIT; - count <= count_step; - scaler_counter <= prescaler; - end else if ( state==STATE_STARTBIT && scaler_counter==0 ) begin - if ( count[3:0] == 4'b1000 ) begin - state <= STATE_RECEIVE; - count <= count_step; - end else begin - count <= count + count_step; - end - scaler_counter <= prescaler; - end else if ( state==STATE_RECEIVE && scaler_counter==0 ) begin - if ( count[3:0] == 4'b0000 ) begin - if ( count[7:4]==4'd9 ) begin - state <= STATE_IDLE; - end else begin - datain <= { rxd, datain[7:1] }; - count <= count + count_step; - end - end else begin - count <= count + count_step; - end - scaler_counter <= prescaler; - end else if ( state[1] ) begin - scaler_counter <= scaler_counter - 1; - end - - avail <= rx_completed | (avail & ~reset); - -end - -endmodule - -/*****************************************************************************/ - -module avr_io_uart - ( input clk, - input rst, - - input io_re, - input io_we, - input [1:0] io_a, - output [7:0] io_do, - input [7:0] io_di, - - output txd, - input rxd, - - output [2:0] irq - ); - -reg [7:0] UDR_TX = 0; -reg [7:0] UDR_RX = 0; -reg [7:0] UCSRB = 0; -reg [7:0] UBRR = 0; - -parameter UCSRA_RXB8 = 3'd0; -parameter UCSRA_x1 = 3'd1; -parameter UCSRA_PE = 3'd2; -parameter UCSRA_DOR = 3'd3; -parameter UCSRA_FE = 3'd4; -parameter UCSRA_UDRE = 3'd5; -parameter UCSRA_TXC = 3'd6; -parameter UCSRA_RXC = 3'd7; - -wire RXCIE, TXCIE, UDRIE, USBS, UPM1, UPM0, UCSZ, TXB8; -assign { RXCIE, TXCIE, UDRIE, USBS, UPM1, UPM0, UCSZ, TXB8 } = UCSRB; - -reg rx0_non_empty = 0, rx0_overrun = 0, rx0_reset = 0; -wire tx0_txd,tx0_busy,tx0_prefetch; -reg tx0_non_empty = 0; - -wire [7:0] UCSRA = { rx0_non_empty, ~tx0_busy, ~tx0_non_empty, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0 }; - -assign irq = UCSRB[7:5] & UCSRA[7:5]; - -/* I/O read: */ -reg [7:0] io_do_data; -always @(*) begin - casex (io_a) - 2'b00: io_do_data = UDR_RX[7:0]; - 2'b01: io_do_data = UCSRA; - 2'b10: io_do_data = UCSRB; - 2'b11: io_do_data = UBRR; - endcase -end -assign io_do = io_re ? io_do_data : 8'b00000000; - -/* I/O write: configuration: */ -always @(posedge clk) begin - if ( io_we ) begin - casex (io_a) - 2'b10: UCSRB <= io_di; - 2'b11: UBRR <= io_di; - endcase - end -end - -/* TX */ - - -uart_tx tx0 (clk, UBRR, UDR_TX, tx0_non_empty, tx0_txd, tx0_busy, tx0_prefetch); - -/* transmitter state changes: */ -always @(posedge clk) begin - if ( io_we && io_a == 2'b00 && ~tx0_non_empty ) begin - tx0_non_empty <= 1; - UDR_TX <= io_di; - end else if ( (tx0_non_empty & ~tx0_busy) | tx0_prefetch ) - tx0_non_empty <= 0; -end - -assign txd = tx0_txd | (~tx0_busy); - -/* RX */ - -wire [7:0] rx0_data; -wire rx0_avail; - -uart_rx rx0 (clk, UBRR, rxd, rx0_reset, rx0_data, rx0_avail); - -/* receiver state changes: */ -always @(posedge clk) begin - if ( io_re && io_a == 2'b00 ) begin - rx0_non_empty <= 0; - rx0_overrun <= 0; - end else if ( rx0_avail && ~rx0_reset ) begin - UDR_RX <= rx0_data; - rx0_non_empty <= 1; - rx0_overrun <= rx0_non_empty; - rx0_reset <= 1; - end else begin - rx0_reset <= 0; - end -end - -/*****************************************************************************/ -/* Debug section starts here */ - -`ifdef SIMULATOR -initial begin - $dumpvars(1,UDR_TX,UDR_RX,UCSRB,UBRR,tx0_non_empty,tx0_busy,tx0_prefetch); - $dumpvars(1,rxd,rx0_non_empty,rx0_avail,rx0_data,rx0_reset,rx0_overrun); -end -`endif - -/* end of debug section */ -/*****************************************************************************/ - -endmodule - -/*****************************************************************************/ Index: trunk/peripherals/avr_io_timer.v =================================================================== --- trunk/peripherals/avr_io_timer.v (revision 2) +++ trunk/peripherals/avr_io_timer.v (nonexistent) @@ -1,95 +0,0 @@ -/*****************************************************************************/ -/* avr_io_timer.v */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* (c) 2019-2020; Andras Pal */ -/*****************************************************************************/ - -module avr_io_timer - ( input clk, - input rst, - - input io_re, - input io_we, - input [1:0] io_a, - output [7:0] io_do, - input [7:0] io_di, - output irq - ); - -reg [15:0] TCNT; -reg [7:0] TTMP; -reg [7:0] TCR; - -reg [11:0] prescaler; -reg [3:0] pre_prev; -reg overflow; - -wire [7:0] TSR = { overflow, 7'b0000000 }; - -assign irq = TSR[7] & TCR[7]; - -/* I/O read: */ -reg [7:0] io_do_data; -always @(*) begin - casex (io_a) - 2'b00: io_do_data = TCNT[7:0]; - 2'b01: io_do_data = TTMP[7:0]; - 2'b10: io_do_data = TCR; - 2'b11: io_do_data = TSR; - endcase -end -assign io_do = io_re ? io_do_data : 8'b00000000; - - -always @(posedge clk) begin - - if (io_we & ~io_re) begin - if ( io_a==2'b01 ) TTMP <= io_di; - if ( io_a==2'b10 ) TCR <= io_di; - end else if ( io_re ) begin - if ( io_a==2'b00 ) - TTMP <= TCNT[15:8]; - end - -end - -wire tcnt_write = io_we & (io_a==2'b00); -wire tcr_write = io_we & (io_a==2'b10); - -/* Note: the interrupt is cleared when the overflow flag is reset: therefore, any write -into the TNCT _or_ the TCR register would clear the interrupt: */ - -wire o = overflow & (~tcr_write); - -reg increment; - -always @(*) begin - casex (TCR[1:0]) - 2'b00: increment = 1; - 2'b01: increment = (~prescaler[ 3])&pre_prev[0]; - 2'b10: increment = (~prescaler[ 7])&pre_prev[1]; - 2'b11: increment = (~prescaler[11])&pre_prev[2]; - endcase -end - -always @(posedge clk) begin - if ( ! tcnt_write ) begin - prescaler <= prescaler + 1; - pre_prev <= { prescaler[11], prescaler[7], prescaler[3] }; - { overflow, TCNT } <= { o, 16'd0 } | ( { o, TCNT } + increment ); - end else begin - TCNT <= { TTMP, io_di }; - prescaler <= 0; - overflow <= 0; - end -end - -/*****************************************************************************/ -/* Debug section starts here */ - -/* end of debug section */ -/*****************************************************************************/ - -endmodule - -/*****************************************************************************/ Index: trunk/peripherals/avr_systick.v =================================================================== --- trunk/peripherals/avr_systick.v (revision 2) +++ trunk/peripherals/avr_systick.v (nonexistent) @@ -1,80 +0,0 @@ -/*****************************************************************************/ -/* avr_systick.v */ -/*****************************************************************************/ -/* Registers */ -/* STCNTL r BASE + 0x00 { CNT[7:0] } */ -/* STCNTH r BASE + 0x01 { OVERFLOW, CNT[14:8] } */ -/* STLOADL r+w BASE + 0x02 { CLOAD[7:0] } */ -/* STLOADH r+w BASE + 0x03 { IENABLE, CLOAD[14:8] } */ -/*****************************************************************************/ - -module avr_systick - ( input clk, - input rst, - - input io_re, - input io_we, - input [1:0] io_a, - output [7:0] io_do, - input [7:0] io_di, - output irq - ); - -reg IENABLE; -reg CLOAD[14:0]; -reg OVERFLOW; -reg [14:0] CNT; -reg [6:0] CTMP; - -assign irq = IENABLE & OVERFLOW; - -/* I/O read: */ -reg [7:0] io_do_data; -always @(*) begin - casex (io_a) - 2'b00: io_do_data = CNT[7:0]; - 2'b01: io_do_data = { OVERFLOW, CTMP }; - 2'b10: io_do_data = CLOAD[7:0]; - 2'b11: io_do_data = { IENABLE, CLOAD[14:8] } ; - endcase -end - -assign io_do = io_re ? io_do_data : 8'b00000000; - -wire reset_overflow_bit = (io_we & (io_a[1]==0)); - -always @(posedge clk) begin - - if (io_we & ~io_re) begin - if ( io_a==2'b10 ) begin - CLOAD[7:0] <= io_di; - end else if ( io_a==2'b11 ) begin - { IENABLE, CLOAD[14:8] } <= io_di; - end - end else if ( io_re ) begin - if ( io_a==2'b00 ) - CTMP <= CNT[15:8]; - end - -end - -always @(posedge clk) begin - if ( reset_overflow_bit ) begin - OVERFLOW <= 0; - end else if ( CNT[14:0]==0 ) begin - CNT <= CLOAD; - OVERFLOW <= 1; - end else begin - CNT <= CNT - 1; - end -end - -/*****************************************************************************/ -/* Debug section starts here */ - -/* end of debug section */ -/*****************************************************************************/ - -endmodule - -/*****************************************************************************/ Index: trunk/core/avr_core.v =================================================================== --- trunk/core/avr_core.v (revision 2) +++ trunk/core/avr_core.v (nonexistent) @@ -1,1378 +0,0 @@ -/*****************************************************************************/ -/* avr_core.v */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* (c) 2019-2020; Andras Pal */ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* Portions of the code got inspiration from the Navre project */ -/* (https://opencores.org/projects/navre) */ -/*****************************************************************************/ - -`define AVR_200 -//`define AVR_250 -//`define AVR_310 -//`define AVR_350 -//`define AVR_400 -//`define AVR_500 -//`define AVR_510 - -`define AVR_INITIAL - -/*****************************************************************************/ - -module avr_core -#( parameter pmem_width = 9, /* PMEM address bus width (16-bit instr) */ - parameter dmem_width = 9, /* RAM address bus width (bytes) */ - parameter interrupt = 1, - parameter intr_width = 2 /* number of interrupt vector bits */ - ) - ( input clk, - input rst, - - output pmem_ce, - output [pmem_width-1:0] pmem_a, - input [15:0] pmem_d, - - output dmem_re, - output dmem_we, - output [dmem_width-1:0] dmem_a, - input [7:0] dmem_di, - output [7:0] dmem_do, - - output io_re, - output io_we, - output [5:0] io_a, - input [7:0] io_di, - output [7:0] io_do, - - input in_iflag, - input [intr_width-1:0] in_ivect - ); - -/*****************************************************************************/ - -/****************************************************************************** - | avr2 avr25 avr31 avr35 avr4 avr5 avr51 --------------+----------------------------------------------------------------- -MOVW | X X X X X X -LPM Rd,Z(+) | X X X X X X -ELPM | X X -ELPM Rd,Z(+) | X -JMP/CALL | X X X X -SPM | X X X X X -MUL | X X X -******************************************************************************/ - -`ifdef AVR_250 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_SPM -`endif - -`ifdef AVR_310 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_ELPM -`define AVR_HAVE_22BITPC -`endif - -`ifdef AVR_350 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_22BITPC -`define AVR_HAVE_SPM -`endif - -`ifdef AVR_400 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_SPM -`define AVR_HAVE_MUL -`endif - -`ifdef AVR_500 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_22BITPC -`define AVR_HAVE_SPM -`define AVR_HAVE_MUL -`endif - -`ifdef AVR_510 -`define AVR_HAVE_MOVW -`define AVR_HAVE_LPMZ -`define AVR_HAVE_ELPM -`define AVR_HAVE_ELPMZ -`define AVR_HAVE_22BITPC -`define AVR_HAVE_SPM -`define AVR_HAVE_MUL -`endif - -/*****************************************************************************/ - -localparam MEM_OFFSET = 96; - -/*****************************************************************************/ - -`ifdef AVR_INITIAL -localparam STATE_INITIAL = 4'd0; -localparam STATE_STALL = 4'd1; -`else -localparam STATE_STALL = 4'd0; -`endif -localparam STATE_NORMAL = 4'd2; -localparam STATE_TWOWORD = 4'd3; -localparam STATE_SKIP = 4'd4; -localparam STATE_LD = 4'd5; -localparam STATE_CALL = 4'd6; -localparam STATE_RET = 4'd7; -localparam STATE_RET2 = 4'd8; -localparam STATE_LPM = 4'd9; -localparam STATE_LPM2 = 4'd10; -localparam STATE_ADIW = 4'd11; -localparam STATE_IO_BIT = 4'd12; -localparam STATE_MUL = 4'd13; -localparam STATE_IN = 4'd14; - -/*****************************************************************************/ - -/* CPU core state registers: */ -reg [pmem_width-1:0] PC; /* <= 0 */ -reg [3:0] state; /* <= 0: hence, STALL state should be zero! */ - -wire [15:0] INSTR; -reg [15:0] PREVI; - -reg [7:0] GPR[0:31]; - -`ifdef AVR_INITIAL -`ifdef SIMULATOR -localparam init_depth = 3; -`else -localparam init_depth = 8; -`endif -reg [init_depth-1:0] init_count; -`endif - -`ifdef SIMULATOR -integer i; -initial begin - for ( i=0;i<32;i=i+1) - GPR[i] <= 8'hA0 + i; -end -`endif - -wire [15:0] RX = { GPR[27], GPR[26] }; -wire [15:0] RY = { GPR[29], GPR[28] }; -wire [15:0] RZ = { GPR[31], GPR[30] }; - -reg I, T, H, S, V, N, Z, C; /* initialized as <= 0 */ - -wire [7:0] SREG = { I, T, H, S, V, N, Z, C }; - -reg [15:0] SP; /* initialized as <= 0 */ - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -reg nI, nT, nH, nS, nV, nN, nZ, nC; -wire [7:0] nSREG = { nI, nT, nH, nS, nV, nN, nZ, nC }; - -reg [7:0] R; /* generic result for writeback */ -reg [7:0] R_high; /* result for 1-word writeback - high byte */ - -wire [15:0] RX_inc_dec = (INSTR[0] ? RX + 1 : RX - 1); -wire [15:0] RY_inc_dec = (INSTR[0] ? RY + 1 : RY - 1); -wire [15:0] RZ_inc_dec = (INSTR[0] ? RZ + 1 : RZ - 1); -wire [15:0] RZ_inc = (INSTR[0] ? RZ + 1 : RZ ); - -/* arithmetic and logic operators, followed by an 8-bit immediate operand: */ -/* only these instruction imply destination registers r16 ... r31 */ -wire immediate = (INSTR[15:14] == 2'b01 ) | /* ANDI, ORI, SBCI, SUBI */ - (INSTR[15:12] == 4'b0011) | /* CPI */ - (INSTR[15:12] == 4'b1110); /* LDI */ - -wire [4:0] Rd_normal = { immediate | INSTR[8], INSTR[7:4] }; - -wire [4:0] Rd = Rd_normal; - -wire [4:0] Rd_prev = PREVI[8:4]; -wire [4:0] Rr = { INSTR[9], INSTR[3:0] }; -wire [1:0] Rd16 = INSTR[5:4]; -wire [1:0] Rp16 = PREVI[5:4]; -wire [7:0] GPR_Rd = GPR[Rd]; -wire [2:0] b = INSTR[2:0]; -wire GPR_Rd_b = GPR_Rd[b]; -wire [7:0] GPR_Rr = GPR[Rr]; -wire [3:0] RD16 = INSTR[7:4]; -wire [3:0] RR16 = INSTR[3:0]; - -/* used by: ANDI, ORI, SBCI, SUBI, CPI, LDI (i.e. where immediate == 1'b1): */ -wire [7:0] K = { INSTR[11:8], INSTR[3:0] }; -/* used by: LDD Rd, Y+q; LDD RD, Z+q; STD Y+q, Rd; STD Z+q, Rd: */ -wire [5:0] q = { INSTR[13], INSTR[11:10], INSTR[2:0] }; -/* used by: ADIW, SBIW: */ -wire [5:0] K16 = { INSTR[7:6], INSTR[3:0] }; - -wire two_word_lds_sts = ((INSTR[15:10]==6'b100100) & (INSTR[3:0]==4'b0000)); - -`ifdef AVR_HAVE_22BITPC -/* this is for avr3 (avr31, avr35) and avr5 (avr51): */ -wire two_word_jmp_call = ((INSTR[15:9]==7'b1001010) & (INSTR[3:2]==2'b11)); -wire two_word_instr = two_word_lds_sts | two_word_jmp_call; -`else -/* otherwise (avr2, avr25 and avr4): */ -wire two_word_instr = two_word_lds_sts; -`endif - -`ifdef AVR_HAVE_MUL -wire [4:0] Rd_mul = INSTR[15] ? INSTR[8:4] : ~INSTR[8] ? { 1'b1, INSTR[7:4] } : { 2'b10, INSTR[6:4] }; -wire [4:0] Rr_mul = INSTR[15] ? Rr : ~INSTR[8] ? { 1'b1, INSTR[3:0] } : { 2'b10, INSTR[2:0] }; -wire [7:0] GPR_Rd_mul = GPR[Rd_mul]; -wire [7:0] GPR_Rr_mul = GPR[Rr_mul]; -reg [7:0] mul_rd; -reg [7:0] mul_rr; -reg [15:0] product; -/* FMUL, FMULS, FMULSU: */ -wire fmulxx = ~INSTR[15] & (INSTR[3] | INSTR[7]); -/* MULS, FMULS: */ -wire xmulsx = ~INSTR[15] & (~INSTR[8] | ({INSTR[7],INSTR[3]} == 2'b10)); -/* MULS, MULSU, FMULS, FMULSU: */ -wire xmulsu = ~INSTR[15] & (~INSTR[8] | ({INSTR[7],INSTR[3]} != 2'b01)); -reg [2:0] mul_type; /* = { fmulxx, xmulsx, xmulsu }; */ -`endif - -/* stage2 temporary registers: */ - -reg [2:0] writeback; -reg change_z; -reg update_nsz; -reg [pmem_width-1:0] pc_next; -reg [15:0] sp_next; -reg sp_update; - -reg [4:0] Rd_ld_save; -reg lpm_z_low; - -localparam WRITEBACK_NONE = 3'd0; -localparam WRITEBACK_GPR = 3'd1; -localparam WRITEBACK_ZINC = 3'd4; -localparam WRITEBACK_ZY = 3'd5; -localparam WRITEBACK_X = 3'd6; - -reg [3:0] next_state; - -reg [15:0] pc_call_next; -reg [15:0] pc_call; - -wire [15:0] pc_full = { {(16-pmem_width){1'b0}}, PC }; -wire [15:0] pc_full_dec = { {(16-pmem_width){1'b0}}, PC - 1'b1 }; - -/* data memory interface: */ -reg [15:0] d_addr; -reg d_read; -reg d_write; -reg [7:0] d_out; - -/* interrupts: */ -wire is_tail_reti; -wire is_interrupt; - -reg iflag; -reg [intr_width-1:0] ivect; - -generate - if ( interrupt ) begin - assign is_tail_reti = INSTR[4] & iflag; - assign is_interrupt = I & iflag & (state==STATE_NORMAL); - end else begin - assign is_tail_reti = 0; - assign is_interrupt = 0; - end -endgenerate - -/* Instructions performing memory I/O via the dmem_* bus: */ - -// 16'b10q0_qq0d_dddd_0qqq LD Rd, Z+q -// 16'b10q0_qq0d_dddd_1qqq LD Rd, Y+q -// 16'b10q0_qq1d_dddd_0qqq ST Z+q, Rd -// 16'b10q0_qq1d_dddd_1qqq ST Y+q, Rd -// 16'b1001_000d_dddd_0001 LD Rd, Z++ -// 16'b1001_000d_dddd_1001 LD Rd, Y++ -// 16'b1001_001d_dddd_0001 ST Z++, Rd -// 16'b1001_001d_dddd_1001 ST Y++, Rd -// 16'b1001_000d_dddd_0010 LD Rd, --Z -// 16'b1001_000d_dddd_1010 LD Rd, --Y -// 16'b1001_001d_dddd_0010 ST --Z, Rd -// 16'b1001_001d_dddd_1010 ST --Y, Rd -// 16'b1001_000d_dddd_1100 LD Rd, X -// 16'b1001_000d_dddd_1101 LD Rd, X++ -// 16'b1001_000d_dddd_1110 LD Rd, --X -// 16'b1001_001d_dddd_1100 ST X, Rd -// 16'b1001_001d_dddd_1101 ST X++, Rd -// 16'b1001_001d_dddd_1110 ST --X, Rd -// 16'b1001_000d_dddd_1111 POP Rd == LD Rd, ++SP -// 16'b1001_001d_dddd_1111 PUSH Rd == ST SP--, Rd - -// 16'b1001_000d_dddd_1101 LD Rd, X++ -// 16'b1001_000d_dddd_1110 LD Rd, --X -// 16'b1001_001d_dddd_1101 ST X++, Rd -// 16'b1001_001d_dddd_1110 ST --X, Rd - -// 16'b1001_000d_dddd_1001 LD Rd, Y++ -// 16'b1001_000d_dddd_1010 LD Rd, --Y -// 16'b1001_001d_dddd_1001 ST Y++, Rd -// 16'b1001_001d_dddd_1010 ST --Y, Rd - -// 16'b1001_000d_dddd_0001 LD Rd, Z++ -// 16'b1001_000d_dddd_0010 LD Rd, --Z -// 16'b1001_001d_dddd_0001 ST Z++, Rd -// 16'b1001_001d_dddd_0010 ST --Z, Rd - -// 16'b1001_000d_dddd_01x1 LPM Rd, Z++ - -// INSTR[15:10] == 6'b100100 -// X increased/decreased: INSTR[3:2] == 2'b11 -// Y increased/decreased: INSTR[3:2] == 2'b10 -// Z increased/decreased: INSTR[3:2] == 2'b00 -// Z increased INSTR[3:2] == 2'b01 - -/* setting up memory interface lines (d_addr, d_out, d_read and d_write): */ - -always @(*) begin - - d_out = 0; - d_addr = 0; - d_read = 0; - d_write = 0; - - case (state) - - STATE_NORMAL: begin - - casex (INSTR) - - 16'b10x0_xx0x_xxxx_xxxx: begin - /* LD Rd, Z+q */ - /* LD Rd, Y+q */ - d_addr = (~INSTR[3]?RZ:RY) + q; - d_read = 1; - end - - 16'b10x0_xx1x_xxxx_xxxx: begin - /* ST Z+q, Rd */ - /* ST Y+q, Rd */ - d_addr = (~INSTR[3]?RZ:RY) + q; - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1001_000x_xxxx_x001: begin - /* LD Rd, Z++ */ - /* LD Rd, Y++ */ - d_addr = (~INSTR[3]?RZ:RY); - d_read = 1; - end - - 16'b1001_001x_xxxx_x001: begin - /* ST Z++, Rd */ - /* ST Y++, Rd */ - d_addr = (~INSTR[3]?RZ:RY); - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1001_000x_xxxx_x010: begin - /* LD Rd, --Z */ - /* LD Rd, --Y */ - d_addr = (~INSTR[3]?RZ:RY) - 1; - d_read = 1; - end - - 16'b1001_001x_xxxx_x010: begin - /* ST --Z, Rd */ - /* ST --Y, Rd */ - d_addr = (~INSTR[3]?RZ:RY) - 1; - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1001_000x_xxxx_110x: begin - /* LD Rd, X */ - /* LD Rd, X++ */ - d_addr = RX; - d_read = 1; - end - 16'b1001_000x_xxxx_1110: begin - /* LD Rd, --X */ - d_addr = RX - 1; - d_read = 1; - end - - 16'b1001_001x_xxxx_110x: begin - /* ST X, Rd */ - /* ST X++, Rd */ - d_addr = RX; - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1001_001x_xxxx_1110: begin - /* ST --X, Rd */ - d_addr = RX - 1; - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1001_000x_xxxx_1111: begin - /* POP Rd -- LD Rd, ++SP */ - d_addr = SP + 1; - d_read = 1; - end - - 16'b1001_001x_xxxx_1111: begin - /* PUSH Rd -- ST SP--, Rd */ - d_addr = SP; - d_out = GPR_Rd; - d_write = 1; - end - - 16'b1101_xxxx_xxxx_xxxx, - 16'b1001_0101_0000_1001: begin - /* RCALL */ - /* ICALL */ - d_addr = SP; - d_out = pc_full[15:8]; - d_write = 1; - end - - 16'b1001_0101_000x_1000: begin - /* RET, RETI */ - d_addr = SP + 1; - d_read = 1; - end - - endcase - - if (is_interrupt) begin - d_addr = SP; - d_out = pc_full_dec[15:8]; - d_write = 1; - end - - end - - STATE_TWOWORD: begin - casex(PREVI) - - 16'b1001_000x_xxxx_0000: begin - /* LDS Rd, 0xXXXX */ - d_addr = INSTR; - d_read = 1; - end - - 16'b1001_001x_xxxx_0000: begin - /* STS 0xXXXX, Rd */ - d_addr = INSTR; - d_out = GPR[Rd_prev]; - d_write = 1; - end - - `ifdef AVR_HAVE_22BITPC - 16'b1001_010x_xxxx_111x: begin - /* CALL k */ - d_addr = SP; - d_out = pc_full[15:8]; - d_write = 1; - end - `endif - - endcase - - end - - STATE_CALL: begin - /* RCALL */ - /* ICALL */ - d_addr = SP; - d_out = pc_full[7:0]; - d_write = 1; - end - - STATE_RET: begin - d_addr = SP + 1; - d_read = 1; - end - - endcase -end - -assign dmem_a = d_addr[dmem_width-1:0] - MEM_OFFSET; -assign dmem_re = d_read; -assign dmem_we = d_write; -assign dmem_do = d_out; - -/* IN/OUT assignments: */ - -/* used by: IN, OUT, SBIC, SBIS, CBI, SBI: */ -// 16'b1011_0aad_dddd_aaaa: /* IN */ -// 16'b1011_1aad_dddd_aaaa: /* OUT */ -// 16'b1001_1000_aaaa_abbb: /* CBI */ -// 16'b1001_1010_aaaa_abbb: /* SBI */ -// 16'b1001_1001_aaaa_abbb: /* SBIC */ -// 16'b1001_1011_aaaa_abbb: /* SBIS */ - -reg [7:0] Rio; - -wire [5:0] a = INSTR[13] ? {INSTR[10:9], INSTR[3:0]} : {1'b0, INSTR[7:3]}; -wire io_act = (INSTR[15:12]==4'b1011) & (state == STATE_NORMAL); -assign io_a = (state == STATE_IO_BIT ? {1'b0, PREVI[7:3]} : a); -assign io_do = (state == STATE_IO_BIT ? Rio : GPR_Rd); -assign io_re = (io_act & (INSTR[11]==1'b0)) | ((state == STATE_NORMAL) & (INSTR[15:10]==6'b100110)); -assign io_we = (io_act & (INSTR[11]==1'b1)) | (state == STATE_IO_BIT); - - -wire [7:0] Rin = (a==61?(SP[7:0]):(a==62?(SP[15:8]):(a==63?SREG:io_di))); - -/* -reg [7:0] Rin; -always @(*) begin - if (a==6'b111101) begin - Rin = SP[7:0]; - end else if (a==6'b111110) begin - Rin = SP[15:8]; - end else if (a==6'b111111) begin - Rin = SREG; - end else begin - Rin = io_di; - end -end -*/ - -/* CPU instruction pipeline, stage 1: */ - -assign pmem_ce = 1'b1; -assign pmem_a = PC; -/* always @(posedge clk) pmem_d <= FLASH[pmem_a]; */ -assign INSTR = pmem_d; - -always @(posedge clk) begin - - PREVI <= INSTR; - - iflag <= in_iflag; - ivect <= in_ivect; - -end /* always @(posedge clk) */ - -/* CPU instruction pipeline, stage 2: */ - -always @(*) begin - - R = 0; - R_high = 0; - - writeback = WRITEBACK_NONE ; - change_z = 1; - update_nsz = 0; - - next_state = STATE_NORMAL; - pc_next = PC; - sp_next = SP; - sp_update = 0; - - pc_call_next = 0; - - { nI, nT, nH, nS, nV, nN, nZ, nC } = SREG; - - case(state) - - STATE_NORMAL: begin - - casex(INSTR) - - `ifdef AVR_HAVE_MOVW - 16'b0000_0001_xxxx_xxxx: begin - R = GPR[2*RR16+0]; - R_high = GPR[2*RR16+1]; - pc_next = PC + 1; - end - `endif - - `ifdef AVR_HAVE_MUL - 16'b1001_11xx_xxxx_xxxx, - 16'b0000_001x_xxxx_xxxx: begin - /* MUL */ - /* MULS */ - /* MULSU */ - /* FMUL */ - /* FMULS */ - /* FMULSU */ - next_state = STATE_MUL; - end - `endif - - 16'b000x_10xx_xxxx_xxxx, /* subtract */ - 16'b000x_01xx_xxxx_xxxx: /* compare */ begin - /* SUB - SBC / CP - CPC */ - {nC, R} = GPR_Rd - GPR_Rr - (~INSTR[12] & C); - nH = (~GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & R[3])|(R[3] & ~GPR_Rd[3]); - nV = (GPR_Rd[7] & ~GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & GPR_Rr[7] & R[7]); - update_nsz = 1; - if (~INSTR[12]) - change_z = 1'b0; - if (INSTR[11]) - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b000x_11xx_xxxx_xxxx: begin - /* ADD - ADC */ - {nC, R} = GPR_Rd + GPR_Rr + (INSTR[12] & C); - nH = (GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & ~R[3])|(~R[3] & GPR_Rd[3]); - nV = (GPR_Rd[7] & GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & ~GPR_Rr[7] & R[7]); - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b010x_xxxx_xxxx_xxxx, /* subtract */ - 16'b0011_xxxx_xxxx_xxxx: /* compare */ begin - /* SUBI - SBCI / CPI */ - {nC, R} = GPR_Rd - K - (~INSTR[12] & C); - nH = (~GPR_Rd[3] & K[3])|(K[3] & R[3])|(R[3] & ~GPR_Rd[3]); - nV = (GPR_Rd[7] & ~K[7] & ~R[7])|(~GPR_Rd[7] & K[7] & R[7]); - update_nsz = 1; - if (~INSTR[12]) - change_z = 1'b0; - if (INSTR[14]) - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - - 16'b0111_xxxx_xxxx_xxxx: begin - /* ANDI Rd, K; */ - R = GPR_Rd & K; - nV = 1'b0; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - - 16'b0110_xxxx_xxxx_xxxx: begin - /* ORI Rd, K; */ - R = GPR_Rd | K; - nV = 1'b0; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - - 16'b0010_00xx_xxxx_xxxx: begin - /* AND */ - R = GPR_Rd & GPR_Rr; - nV = 1'b0; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b0010_01xx_xxxx_xxxx: begin - /* EOR */ - R = GPR_Rd ^ GPR_Rr; - nV = 1'b0; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b0010_10xx_xxxx_xxxx: begin - /* OR */ - R = GPR_Rd | GPR_Rr; - nV = 1'b0; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b0010_11xx_xxxx_xxxx: begin - /* MOV */ - R = GPR_Rr; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_0000: begin - /* COM */ - R = ~GPR_Rd; - nV = 1'b0; - nC = 1'b1; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_0001: begin - /* NEG */ - {nC, R} = 8'h00 - GPR_Rd; - nH = R[3] | GPR_Rd[3]; - nV = (R == 8'h80); - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_0011: begin - /* INC */ - R = GPR_Rd + 8'd1; - nV = (R == 8'h80); - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_1010: begin - /* DEC */ - R = GPR_Rd - 8'd1; - nV = (R == 8'h7f); - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_011x: begin - /* LSR - ROR */ - R = {INSTR[0] & C, GPR_Rd[7:1]}; - nC = GPR_Rd[0]; - nV = R[7] ^ GPR_Rd[0]; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_0101: begin - /* ASR */ - R = {GPR_Rd[7], GPR_Rd[7:1]}; - nC = GPR_Rd[0]; - nV = R[7] ^ GPR_Rd[0]; - update_nsz = 1; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_010x_xxxx_0010: begin - /* SWAP */ - R = {GPR_Rd[3:0], GPR_Rd[7:4]}; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1001_0100_xxxx_1000: begin - /* BSET - BCLR */ - case(INSTR[7:4]) - 4'b0000: nC = 1'b1; - 4'b0001: nZ = 1'b1; - 4'b0010: nN = 1'b1; - 4'b0011: nV = 1'b1; - 4'b0100: nS = 1'b1; - 4'b0101: nH = 1'b1; - 4'b0110: nT = 1'b1; - 4'b0111: nI = 1'b1; - 4'b1000: nC = 1'b0; - 4'b1001: nZ = 1'b0; - 4'b1010: nN = 1'b0; - 4'b1011: nV = 1'b0; - 4'b1100: nS = 1'b0; - 4'b1101: nH = 1'b0; - 4'b1110: nT = 1'b0; - 4'b1111: nI = 1'b0; - endcase - pc_next = PC + 1; - end - - 16'b1001_011x_xxxx_xxxx: begin - /* SBIW */ - /* ADIW */ - if(INSTR[8]) begin /* SBIW */ - {nC, R} = GPR[24+2*Rd16] - K16; - end else begin /* ADIW */ - {nC, R} = GPR[24+2*Rd16] + K16; - end - nZ = (R==0); - next_state = STATE_ADIW; - end - - 16'b1001_00xx_xxxx_0000: begin - /* LDS Rd, 0xXXXX */ - /* STS 0xXXXX, Rd */ - pc_next = PC + 1; - next_state = STATE_TWOWORD; - end - - `ifdef AVR_HAVE_22BITPC - 16'b1001_010x_xxxx_11xx: begin - /* JMP k */ - /* CALL k */ - pc_next = PC + 1; - next_state = STATE_TWOWORD; - end - `endif - - 16'b10x0_xx0x_xxxx_xxxx: begin - /* LD Rd, Z+q; */ - /* LD Rd, Y+q; */ - next_state = STATE_LD; - end - - 16'b10x0_xx1x_xxxx_xxxx: begin - /* ST Z+q, Rd */ - /* ST Y+q, Rd */ - pc_next = PC + 1; - end - - 16'b1001_000x_xxxx_x001: begin - /* LD Rd, Z++ */ - /* LD Rd, Y++ */ - next_state = STATE_LD; - /* save dest register for the next cycle: */ - writeback = WRITEBACK_ZY; - end - - 16'b1001_001x_xxxx_x001: begin - /* ST Z++, Rd */ - /* ST Y++, Rd */ - pc_next = PC + 1; - writeback = WRITEBACK_ZY; - end - - 16'b1001_000x_xxxx_x010: begin - /* LD Rd, --Z */ - /* LD Rd, --Y */ - next_state = STATE_LD; - /* save dest register for the next cycle: */ - writeback = WRITEBACK_ZY; - end - - 16'b1001_001x_xxxx_x010: begin - /* ST --Z, Rd */ - /* ST --Y, Rd */ - pc_next = PC + 1; - writeback = WRITEBACK_ZY; - end - - 16'b1001_000x_xxxx_1100: begin - /* LD Rd, X */ - next_state = STATE_LD; - end - - 16'b1001_001x_xxxx_1100: begin - /* ST X, Rd */ - pc_next = PC + 1; - end - - 16'b1001_000x_xxxx_1101: begin - /* LD Rd, X++ */ - writeback = WRITEBACK_X; - next_state = STATE_LD; - end - - 16'b1001_001x_xxxx_1101: begin - /* ST X++, Rd */ - writeback = WRITEBACK_X; - pc_next = PC + 1; - end - - 16'b1001_000x_xxxx_1110: begin - /* LD Rd, --X */ - writeback = WRITEBACK_X; - next_state = STATE_LD; - end - - 16'b1001_001x_xxxx_1110: begin - /* ST --X, Rd */ - writeback = WRITEBACK_X; - pc_next = PC + 1; - end - - 16'b1001_000x_xxxx_1111: begin - /* POP Rd */ /* LD Rd, ++SP */ - sp_next = SP + 1; - sp_update = 1; - next_state = STATE_LD; - end - - 16'b1001_001x_xxxx_1111: begin - /* PUSH Rd */ /* ST SP--, Rd */ - sp_next = SP - 1; - sp_update = 1; - next_state = STATE_STALL; - end - - 16'b1100_xxxx_xxxx_xxxx: begin - /* RJMP */ - next_state = STATE_STALL; - pc_next = PC + { {4{INSTR[11]}}, INSTR[11:0] }; - end - 16'b1001_0100_0000_1001: begin - /* IJMP */ - next_state = STATE_STALL; - pc_next = RZ; - end - - 16'b1101_xxxx_xxxx_xxxx: begin - /* RCALL */ - pc_call_next = pc_full + { {4{INSTR[11]}}, INSTR[11:0] }; - sp_next = SP - 1; - sp_update = 1; - next_state = STATE_CALL; - end - 16'b1001_0101_0000_1001: begin - /* ICALL */ - pc_call_next = RZ; - sp_next = SP - 1; - sp_update = 1; - next_state = STATE_CALL; - end - - 16'b1001_0101_0000_1000, /* INSTR: 0x9508 */ - 16'b1001_0101_0001_1000: begin /* INSTR: 0x9518 */ - /* RET */ - /* RETI */ - - if ( is_tail_reti ) begin - // `RETI` is equivalent to `JMP ivect` if - // there is a pending interrupt: - next_state = STATE_STALL; - pc_next = ivect; - end else begin - // Otherwise, RETI and RET is the same... - next_state = STATE_RET; - sp_next = SP + 1; - sp_update = 1; - // ... besides that RETI sets the I flag: - if (INSTR[4]) - nI = 1'b1; - - end - - end - - 16'b1001_0101_110x_1000: begin - /* LPM */ - /* ELPM */ - pc_call_next = PC; - pc_next = RZ[pmem_width:1]; - next_state = STATE_LPM; - end - -// `ifdef AVR_HAVE_SPM -// 16'b1001_0101_111x_1000: begin -// /* SPM Z */ -// /* SPM Z+ */ -// pc_call_next = PC; -// pc_next = RZ[pmem_width:1]; -// next_state = STATE_LPM; -// end -// `endif - - `ifdef AVR_HAVE_LPMZ - 16'b1001_000x_xxxx_01xx: begin - /* LPM Rd, Z */ - /* LPM Rd, Z++ */ - /* ELPM Rd, Z */ - /* ELPM Rd, Z++ */ - pc_call_next = PC; - pc_next = RZ[pmem_width:1]; - next_state = STATE_LPM; - writeback = WRITEBACK_ZINC; - end - `endif - - 16'b1111_0xxx_xxxx_xxxx: begin - /* BRxS - BRxC */ - if (SREG[b] ^ INSTR[10]) begin - next_state = STATE_STALL; - pc_next = PC + { {9{INSTR[9]}}, INSTR[9:3] }; - end else begin - pc_next = PC + 1; - end - end - 16'b1111_11xx_xxxx_0xxx: begin - /* SBRC */ - /* SBRS */ - if (GPR_Rd_b == INSTR[9]) begin - next_state = STATE_SKIP; - end - pc_next = PC + 1; - end - 16'b1001_10x0_xxxx_xxxx: begin - /* CBI */ - /* SBI */ - next_state = STATE_IO_BIT; - end - 16'b1001_10x1_xxxx_xxxx: begin - /* SBIC */ - /* SBIS */ - if (Rin[b]==INSTR[9]) begin - next_state = STATE_SKIP; - end - pc_next = PC + 1; - end - 16'b0001_00xx_xxxx_xxxx: begin - /* CPSE */ - if (GPR_Rd == GPR_Rr) begin - next_state = STATE_SKIP; - end - pc_next = PC + 1; - end - 16'b1110_xxxx_xxxx_xxxx: begin - /* LDI */ - R = K; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1111_10xx_xxxx_0xxx: begin - /* BST */ - /* BLD */ - if (INSTR[9]) begin /* BST */ - nT = GPR_Rd_b; - end else begin /* BLD */ - case (b) - 3'd0: R = { GPR_Rd[7:1], T }; - 3'd1: R = { GPR_Rd[7:2], T, GPR_Rd[0] }; - 3'd2: R = { GPR_Rd[7:3], T, GPR_Rd[1:0] }; - 3'd3: R = { GPR_Rd[7:4], T, GPR_Rd[2:0] }; - 3'd4: R = { GPR_Rd[7:5], T, GPR_Rd[3:0] }; - 3'd5: R = { GPR_Rd[7:6], T, GPR_Rd[4:0] }; - 3'd6: R = { GPR_Rd[7], T, GPR_Rd[5:0] }; - 3'd7: R = { T, GPR_Rd[6:0] }; - endcase - writeback = WRITEBACK_GPR; - end - pc_next = PC + 1; - end - 16'b1011_0xxx_xxxx_xxxx: begin - /* IN */ - R = Rin; - writeback = WRITEBACK_GPR; - pc_next = PC + 1; - end - 16'b1011_1xxx_xxxx_xxxx: begin - /* OUT */ - if (a==6'b111101) begin /* SPL */ - sp_next[7:0] = GPR_Rd; - sp_update = 1; - end else if (a==6'b111110) begin /* SPH */ - sp_next[15:8] = GPR_Rd; - sp_update = 1; - end else if (a==6'b111111) begin /* SREG */ - { nI, nT, nH, nS, nV, nN, nZ, nC } = GPR_Rd; - end - // in all other cases, the data flow is handled - // by the IN/OUT persistent assignments (see earlier) - pc_next = PC + 1; - end - - default: - pc_next = PC + 1; - endcase - - if (update_nsz) begin - nN = R[7]; - nS = nN ^ nV; - nZ = (R == 8'h00) & (change_z|Z); - end - -// `ifdef AVR_INTERRUPT - if (is_interrupt) begin - // An interrupt is equivalent to a CALL, however, - // the actual program counter needed to be saved, not - // the PC corresponding to the following instruction. - // Due to the two-stage pipeline, the current - // instruction is PC - 1, and not PC: - writeback = 0; - pc_call_next = ivect; - sp_next = SP - 1; - sp_update = 1; - next_state = STATE_CALL; - pc_next = PC - 1; - nI = 0; - end -// `endif - - end /* STATE_NORMAL */ - - STATE_TWOWORD: begin - casex(PREVI) - - 16'b1001_000x_xxxx_0000: begin - /* LDS Rd, 0xXXXX */ - next_state = STATE_LD; - end - - 16'b1001_001x_xxxx_0000: begin - /* STS 0xXXXX, Rd */ - pc_next = PC + 1; - end - - `ifdef AVR_HAVE_22BITPC - 16'b1001_010x_xxxx_110x: begin - /* JMP K */ - next_state = STATE_STALL; - pc_next = INSTR; - end - 16'b1001_010x_xxxx_111x: begin - /* CALL K */ - pc_call_next = INSTR; - sp_next = SP - 1; - sp_update = 1; - next_state = STATE_CALL; - end - `endif - - default: - pc_next = PC + 1; - - endcase - - end /* STATE_TWOWORD */ - - STATE_STALL: begin - pc_next = PC + 1; - next_state = STATE_NORMAL; - end /* STATE_STALL */ - - STATE_LD: begin - pc_next = PC + 1; - next_state = STATE_NORMAL; - end /* STATE_LD */ - - STATE_CALL: begin - sp_next = SP - 1; - sp_update = 1; - pc_next = pc_call; - next_state = STATE_STALL; - end /* STATE_CALL */ - - STATE_RET: begin - pc_call_next = { 8'h00, dmem_di }; - sp_next = SP + 1; - sp_update = 1; - next_state = STATE_RET2; - end /* STATE_RET2 */ - - STATE_RET2: begin - pc_next = { dmem_di, pc_call[7:0] }; - next_state = STATE_STALL; - end /* STATE_RET2 */ - - STATE_SKIP: begin - if (two_word_instr) next_state = STATE_STALL; - else next_state = STATE_NORMAL; - pc_next = PC + 1; - end /* STATE_SKIP */ - - STATE_LPM: begin - pc_next = pc_call; - next_state = STATE_LPM2; - end - - STATE_LPM2: begin - pc_next = PC + 1; - next_state = STATE_NORMAL; - end - - STATE_ADIW: begin - if (PREVI[8]) begin - /* SBIW */ - {nC, R_high} = GPR[24+2*Rp16+1] - C; - nV = GPR[24+2*Rp16+1][7] & ~R_high[7]; - end else begin - /* ADIW */ - {nC, R_high} = GPR[24+2*Rp16+1] + C; - nV = ~GPR[24+2*Rp16+1][7] & R_high[7]; - end - nN = R_high[7]; - nS = nN ^ nV; - nZ = (R_high==0) & Z; - pc_next = PC + 1; - next_state = STATE_NORMAL; - end - - STATE_IO_BIT: begin - pc_next = PC + 1; - next_state = STATE_NORMAL; - end - - - `ifdef AVR_INITIAL - STATE_INITIAL: begin - if (init_count[init_depth-1] == 1'b1) - next_state = STATE_STALL; - else - next_state = STATE_INITIAL; - end - `endif - - `ifdef AVR_HAVE_MUL - STATE_MUL: begin - - { R_high, R } = product; - if ( mul_type[0] & mul_rd[7] ) - R_high = R_high - mul_rr; - if ( mul_type[1] & mul_rr[7] ) - R_high = R_high - mul_rd; - - nZ = ( {R_high, R} == 16'h0000 ); - nC = R_high[7]; - - if ( mul_type[2] ) begin - { R_high, R } = { R_high[6:0], R, 1'b0 }; - end - - pc_next = PC + 1; - next_state = STATE_NORMAL; - end - `endif - - endcase - -end /* always @(*) */ - -// Note: if `interrupt` is 1, then after this point: -// - state is STATE_NORMAL, -// - writeback is 0, -// - next_state is STATE_CALL. - -`ifdef AVR_HAVE_MUL -always @(posedge clk) if (next_state==STATE_MUL) begin - product <= GPR_Rd_mul * GPR_Rr_mul; - mul_rd <= GPR_Rd_mul; - mul_rr <= GPR_Rr_mul; - mul_type <= { fmulxx, xmulsx, xmulsu }; -end -`endif - -always @(posedge clk) begin - - `ifdef AVR_HAVE_MUL - if (state==STATE_MUL) begin - /* writeback: after two-cycle MUL: */ - GPR[0] <= R; - GPR[1] <= R_high; - end else - `endif - - `ifdef AVR_HAVE_MOVW - /* writeback: after single cycle MOVW: */ - if (state==STATE_NORMAL && INSTR[15:8]==8'b0000_0001 && ~is_interrupt) begin - GPR[2*RD16+0] <= R; // GPR[2*RR16+0]; - GPR[2*RD16+1] <= R_high; // GPR[2*RR16+1]; - end else - `endif - - /* writeback: after the first and second cycle of ADIW and SUBW: */ - if (next_state==STATE_ADIW) - GPR[24+2*Rd16+0] <= R; - else if (state==STATE_ADIW) - GPR[24+2*Rp16+1] <= R_high; - /* writeback after LD: */ - else if ( state==STATE_LD ) - GPR[Rd_ld_save] <= dmem_di; - else if ( state==STATE_LPM2 ) begin - if (~lpm_z_low) GPR[Rd_ld_save] <= INSTR[7:0]; - else GPR[Rd_ld_save] <= INSTR[15:8]; - end else begin - - /* writeback: all of the another cases (ALU + X/Y/Z inc/dec): */ - case (writeback) - WRITEBACK_GPR: begin - GPR[Rd] <= R; - end - WRITEBACK_ZINC: begin - GPR[30] <= RZ_inc[7:0]; - GPR[31] <= RZ_inc[15:8]; - end - WRITEBACK_ZY: begin - if (~INSTR[3]) begin - GPR[30] <= RZ_inc_dec[7:0]; - GPR[31] <= RZ_inc_dec[15:8]; - end else begin - GPR[28] <= RY_inc_dec[7:0]; - GPR[29] <= RY_inc_dec[15:8]; - end - end - WRITEBACK_X: begin - GPR[26] <= RX_inc_dec[7:0]; - GPR[27] <= RX_inc_dec[15:8]; - end - endcase - - end - - { I, T, H, S, V, N, Z, C } <= nSREG; - - if (~INSTR[9]) Rio <= Rin & ~(8'h01 << b); - else Rio <= Rin | (8'h01 << b); - - pc_call <= pc_call_next; - - if (next_state == STATE_LD) - Rd_ld_save <= (state == STATE_NORMAL ? Rd : Rd_prev); - else if (next_state == STATE_LPM) begin - Rd_ld_save <= (INSTR[10] ? 5'b00000: Rd); - lpm_z_low <= RZ[0]; - end - - `ifdef AVR_INITIAL - if ( ~init_count[init_depth-1] ) - init_count <= init_count + 1; - `endif - - state <= next_state; - PC <= pc_next; - -// if ( sp_update ) - SP <= sp_next; - -end - -/*****************************************************************************/ - -/* Debug section starts here */ - -wire [pmem_width:0] PC_double = {PC,1'b0}; -wire [7:0] R0 = GPR[0]; -wire [7:0] R1 = GPR[1]; -wire [7:0] R2 = GPR[2]; -wire [7:0] R3 = GPR[3]; -wire [7:0] R4 = GPR[4]; -wire [7:0] R5 = GPR[5]; -wire [7:0] R6 = GPR[6]; -wire [7:0] R7 = GPR[7]; -wire [7:0] R8 = GPR[8]; -wire [7:0] R9 = GPR[9]; -wire [7:0] R10 = GPR[10]; -wire [7:0] R11 = GPR[11]; -wire [7:0] R12 = GPR[12]; -wire [7:0] R13 = GPR[13]; -wire [7:0] R14 = GPR[14]; -wire [7:0] R15 = GPR[15]; -wire [7:0] R16 = GPR[16]; -wire [7:0] R17 = GPR[17]; -wire [7:0] R18 = GPR[18]; -wire [7:0] R19 = GPR[19]; -wire [7:0] R20 = GPR[20]; -wire [7:0] R21 = GPR[21]; -wire [7:0] R22 = GPR[22]; -wire [7:0] R23 = GPR[23]; -wire [7:0] R24 = GPR[24]; -wire [7:0] R25 = GPR[25]; -wire [7:0] R26 = GPR[26]; -wire [7:0] R27 = GPR[27]; -wire [7:0] R28 = GPR[28]; -wire [7:0] R29 = GPR[29]; -wire [7:0] R30 = GPR[30]; -wire [7:0] R31 = GPR[31]; - -`ifdef SIMULATOR -initial begin - $dumpvars(1,PC,PC_double,INSTR,SP,SREG,state,pc_call,R); - $dumpvars(1,R0,R1,R16,R17,R18,R19,R20,R21,R22,R23,R24,R25,RX,RY,RZ); - $dumpvars(1,io_we,io_re,io_a,io_do,io_di,Rio); - $dumpvars(1,dmem_we,dmem_re,dmem_a,dmem_do,dmem_di); -end -`endif - -/* end of debug section */ -/*****************************************************************************/ - -endmodule - -/*****************************************************************************/ Index: trunk/Makefile =================================================================== --- trunk/Makefile (revision 2) +++ trunk/Makefile (nonexistent) @@ -1,12 +0,0 @@ -SHELL=/bin/sh - -.PHONY: all clean - -all: - $(MAKE) -C build - $(MAKE) -C synth - -clean: - $(MAKE) -C build clean - $(MAKE) -C synth clean -

powered by: WebSVN 2.1.0

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