From 0a96ce78f03a7b69facd040910c91fd1f5ac5f6e Mon Sep 17 00:00:00 2001 From: Matthias Blankertz Date: Wed, 19 Jun 2013 09:16:36 +0200 Subject: [PATCH] - New Wishbone master for CPU - WIP: New cache for CPU - Memory controller now supports modulu bursts and different burst lengths - WIP: Timing problems... --- Makefile | 11 +- constr/2d_display_engine.ucf | 6 + constr/2d_display_engine.xcf | 2 + firmware/main.c | 39 ++- firmware/spi.c | 8 +- firmware/standalone.ld | 7 +- firmware/test.s | 73 +---- firmware/uart.c | 4 +- mblite/config_Pkg.vhd | 2 +- mblite_cache_tb.wcfg | 376 +++++++++++++++++++++ src/mblite_cache.vhd | 493 ++++++++++++++++++++++++++++ src/mblite_cache_ram.vhd | 176 ++++++++++ src/mblite_wbm.vhd | 96 ++++++ src/mblite_wrapper.vhd | 123 +++++-- src/spi.vhd | 4 +- src/toplevel.vhd | 26 +- src/uart/uart_wbc.vhd | 2 +- src/wb_ddr_ctrl.vhd | 19 +- src/wb_ddr_ctrl_wb.vhd | 21 +- src/wb_ddr_ctrl_wb_sc.vhd | 137 ++++---- src/wb_ram.vhd | 4 +- src/wishbone.vhd | 8 +- tb/mblite_cache_tb.vhd | 201 ++++++++++++ tb/wb_ddr_ctrl_wb_sc_tb.vhd | 60 +++- toplevel_tb.wcfg | 616 +++++++---------------------------- wb_ddr_ctrl_wb_sc_tb.wcfg | 77 +++-- 26 files changed, 1854 insertions(+), 737 deletions(-) create mode 100644 mblite_cache_tb.wcfg create mode 100644 src/mblite_cache.vhd create mode 100644 src/mblite_cache_ram.vhd create mode 100644 src/mblite_wbm.vhd create mode 100644 tb/mblite_cache_tb.vhd diff --git a/Makefile b/Makefile index 4676ef3..10e113d 100755 --- a/Makefile +++ b/Makefile @@ -33,7 +33,8 @@ src/wb_ddr_ctrl_wb_sc.vhd src/vga_syncgen.vhd src/vga_pixelgen.vhd \ src/vga_pixelreader.vhd src/vga.vhd \ src/bresenham_dp.vhd \ src/rasterizer_l_fsm.vhd src/rasterizer_l.vhd \ -src/mblite_rom_data.vhd src/mblite_rom.vhd src/mblite_wrapper.vhd src/pio.vhd \ +src/mblite_rom_data.vhd src/mblite_rom.vhd src/mblite_wbm.vhd src/mblite_cache_ram.vhd src/mblite_cache.vhd \ +src/mblite_wrapper.vhd src/pio.vhd \ src/uart/fifo16x8.vhd src/uart/par2ser.vhd src/uart/pulsegen325.vhd src/uart/readctrl.vhd src/uart/ser2par.vhd \ src/uart/writectrl.vhd src/uart/uart.vhd src/uart/uart_wbc.vhd \ src/ram_16x64.vhd src/wb_mem_bridge.vhd \ @@ -248,9 +249,13 @@ isim/work/spi_tb.vdb: isim/work/intercon_package.vdb isim/work/spi.vdb isim/work/wb_mem_bridge_tb.vdb: isim/work/intercon_package.vdb isim/work/wb_ddr_ctrl_wb_sc.vdb isim/work/wb_mem_bridge.vdb +isim/work/mblite_cache_tb.vdb: isim/mblite/core_Pkg.vdb isim/work/intercon_package.vdb isim/work/mblite_cache.vdb + isim/work/toplevel.vdb: isim/work/mblite_wrapper.vdb isim/work/intercon_package.vdb isim/work/interconnect.vdb isim/work/clk_reset.vdb isim/work/wb_ddr_ctrl.vdb isim/work/vga.vdb isim/work/wb_ram.vdb isim/work/pio.vdb isim/work/uart_wbc.vdb isim/work/wb_mem_bridge.vdb isim/work/spi.vdb -isim/work/mblite_wrapper.vdb: isim/work/intercon_package.vdb isim/work/mblite_rom.vdb isim/mblite/core_wb.vdb +isim/work/mblite_wrapper.vdb: isim/work/intercon_package.vdb isim/mblite/core_Pkg.vdb isim/work/mblite_rom.vdb isim/work/mblite_wbm.vdb isim/mblite/core.vdb isim/work/mblite_cache.vdb + +isim/work/mblite_cache.vdb: isim/work/intercon_package.vdb isim/mblite/core_Pkg.vdb isim/work/mblite_cache_ram.vdb isim/work/mblite_rom.vdb: isim/work/intercon_package.vdb isim/work/mblite_rom_data_pkg_mblite_rom.vdb @@ -274,6 +279,8 @@ isim/mblite/execute.vdb: isim/mblite/config_Pkg.vdb isim/mblite/core_Pkg.vdb isi isim/mblite/mem.vdb: isim/mblite/config_Pkg.vdb isim/mblite/core_Pkg.vdb isim/mblite/std_Pkg.vdb +isim/work/mblite_wbm.vdb: isim/work/intercon_package.vdb isim/mblite/core_Pkg.vdb + isim/work/wb_ddr_ctrl.vdb: isim/work/intercon_package.vdb isim/work/wb_ddr_ctrl_ddrwrap.vdb isim/work/wb_ddr_ctrl_wb.vdb isim/work/wb_ddr_ctrl_ddrwrap.vdb: isim/work/vhdl_bl4_parameters_0.vdb isim/work/vhdl_bl4_infrastructure_top.vdb isim/work/vhdl_bl4_top_0.vdb diff --git a/constr/2d_display_engine.ucf b/constr/2d_display_engine.ucf index 2affd2d..4bd8a3e 100755 --- a/constr/2d_display_engine.ucf +++ b/constr/2d_display_engine.ucf @@ -5,6 +5,12 @@ TIMESPEC "TS_CLK_50" = PERIOD "CLK_50" 20.0 ns HIGH 50 %; TIMEGRP "vga" OFFSET = OUT 10ns AFTER "CLKIN_50MHZ" RISING; +TIMEGRP "cpu_wbm_adr_o"=FFS("cpu_inst/mblite_wbm_inst/wbm_o.adr_o_*"); +NET "uart_inst/ACK_O" TPTHRU = "uart_ack_o" ; +TIMEGRP "allff" = FFS("*"); + +TIMESPEC TSfalsewb1 = FROM "cpu_wbm_adr_o" THRU "uart_ack_o" TO FFS("*") TS_CLK_50*2; + # Location and I/O defs # Clocks NET "CLKIN_50MHZ" LOC = "E12"| IOSTANDARD = LVCMOS33 ; diff --git a/constr/2d_display_engine.xcf b/constr/2d_display_engine.xcf index eb9a8cf..ec8d8ca 100644 --- a/constr/2d_display_engine.xcf +++ b/constr/2d_display_engine.xcf @@ -2,6 +2,8 @@ NET "CLKIN_50MHZ" PERIOD = 20.0ns HIGH 40%; NET "CLKIN_133MHZ" PERIOD = 7.51ns HIGH 40%; +#TIMESPEC TSfalse1 = FROM FFS(cpu_inst_mblite_wbm_inst/wbm_o.adr_o*) + #MODEL wb_ddr_ctrl_ddrwrap keep_hierarchy = yes ; #MODEL vhdl_bl4_infrastructure_top keep_hierarchy = yes ; #MODEL vhdl_bl4_cal_top keep_hierarchy = yes; diff --git a/firmware/main.c b/firmware/main.c index cc9eecd..cf5d015 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -6,11 +6,11 @@ #include "spi.h" #include "sd.h" -static unsigned int * const pio = (unsigned int *)0x10000; +static unsigned int * const pio = (unsigned int *)0x08010000; void main() { *pio = 0x000000a5u; - /* uart_writes("Hello, World!\n"); */ + uart_writes("Hello, World!\n"); /* unsigned foo = 0xdeadbeef; */ /* const char *s = utox(foo); */ @@ -41,7 +41,7 @@ void main() { // Send CMD0 spi_set_ss(true); tmp = sd_cmd(0, 0); - spi_set_ss(false); + //spi_set_ss(false); if(tmp&0x80) { uart_writes("SD timeout (CMD0)\n"); return; @@ -52,34 +52,53 @@ void main() { unsigned rsp; spi_set_ss(true); tmp = sd_cmd_r7(8, 0x000001AA, &rsp); - spi_set_ss(false); + //spi_set_ss(false); if(tmp&0x80) { uart_writes("SD timeout (CMD8)\n"); return; } + // Sleep 1 ms + for(int i = 0;i < 16667;++i) {} unsigned char s_tmp = tmp; *pio = 0x5u; spi_set_ss(true); tmp = sd_cmd_r7(58, 0x0, &rsp); - spi_set_ss(false); + //spi_set_ss(false); if(tmp&0x80) { uart_writes("SD timeout (CMD58)\n"); return; } - const char *s = utox(tmp); - uart_writes("0x"); - uart_writes(s); - uart_writeb(' '); + const char *s; s = utox(rsp); uart_writes("0x"); uart_writes(s); uart_writeb('\n'); + *pio = 0x5u; + + // Sleep 1 ms + for(int i = 0;i < 16667;++i) {} + + spi_set_ss(true); + tmp = sd_cmd_r7(58, 0x0, &rsp); + //spi_set_ss(false); + if(tmp&0x80) { + uart_writes("SD timeout (CMD58)\n"); + return; + } + + s = utox(rsp); + uart_writes("0x"); + uart_writes(s); + uart_writeb('\n'); + + // Sleep 1 ms + for(int i = 0;i < 16667;++i) {} *pio = 0x6u; if(s_tmp&0x4) { // Illegal command, not SDCv2 @@ -88,7 +107,7 @@ void main() { spi_set_ss(true); tmp = sd_cmd(55, 0); tmp = sd_cmd(41, 0); - spi_set_ss(false); + //spi_set_ss(false); if(tmp&0x80) { uart_writes("SD timeout (ACMD41)\n"); return; diff --git a/firmware/spi.c b/firmware/spi.c index 7d52cc1..f4d8887 100644 --- a/firmware/spi.c +++ b/firmware/spi.c @@ -4,10 +4,10 @@ #include "spi.h" -static volatile unsigned char * const spi_data = (unsigned char *)0x10030; -static volatile unsigned char * const spi_status = (unsigned char *)0x10031; -static volatile unsigned char * const spi_config = (unsigned char *)0x10032; -static volatile unsigned char * const spi_ss = (unsigned char *)0x10033; +static volatile unsigned char * const spi_data = (unsigned char *)0x08010030; +static volatile unsigned char * const spi_status = (unsigned char *)0x08010031; +static volatile unsigned char * const spi_config = (unsigned char *)0x08010032; +static volatile unsigned char * const spi_ss = (unsigned char *)0x08010033; static bool _spi_rxempty() { return ((*spi_status&0x4)==0x4); diff --git a/firmware/standalone.ld b/firmware/standalone.ld index 04667c0..74342e9 100644 --- a/firmware/standalone.ld +++ b/firmware/standalone.ld @@ -4,8 +4,9 @@ STARTUP(objs/kcrt0.o) SECTIONS { .text 0x0 : ALIGN(4) { *(.text) + _text_end = .; } - .rodata : ALIGN(4) { + .rodata 0x08000000+_text_end : AT (_text_end) ALIGN(4) { *(.rodata) _rodata_end = .; } @@ -14,7 +15,7 @@ SECTIONS { } /* From here on in RAM */ - .data 0x8000 : AT ( _datald ) ALIGN(4) { + .data 0x08008000 : AT ( _datald ) ALIGN(4) { _data_start = .; *(.data) _data_end = .; @@ -26,5 +27,5 @@ SECTIONS { . = ALIGN(4); _bss_end = .; } - _stack = 0x8800; + _stack = 0x08008800; } diff --git a/firmware/test.s b/firmware/test.s index 939c4d5..428f6ff 100644 --- a/firmware/test.s +++ b/firmware/test.s @@ -1,72 +1 @@ -.global main -main: - lbui r3, r0, testdata+1 - swi r3, r0, 0x4000 - - addi r19, r0, helloworld -main_loop: - lbu r5, r19, r0 - beqi r5, fill - brlid r15, send_byte - addi r19, r19, 1 # delay slot - bri main_loop - -fill: - # Clear screen - addi r3, r0, 0x8000000 # r3 = address, load with FB base - addi r4, r0, 0 # r4 = y ctr - addi r7, r0, 0x0f000f00 # Upper/lower border - addi r8, r0, 0x0000000f # Left border - addi r9, r0, 0x00f00000 # Right border -fill_line: - addi r5, r0, 0 # r5 = x ctr -fill_loop: - beqi r4, border - addi r6, r4, -479 - beqi r6, border - beqi r5, lborder - addi r6, r5, -638 - beqi r6, rborder - brid fill_loop_end - sw r0, r3, r0 -border: - brid fill_loop_end - sw r7, r3, r0 -lborder: - brid fill_loop_end - sw r8, r3, r0 -rborder: - sw r9, r3, r0 -fill_loop_end: - addi r3, r3, 4 - addi r6, r5, -638 - beqi r6, fill_loop_nextline - brid fill_loop - addi r5, r5, 2 -fill_loop_nextline: - addi r6, r4, -479 - beqi r6, done - brid fill_line - addi r4, r4, 1 - -done: - swi r0, r0, 0x0BFFFFFF # Force mem_bridge buffer flush -idle: - bri idle - -send_byte: - lbui r3, r0, 0x4021 - andi r3, r3, 0x2 # writefull - bnei r3, send_byte - rtsd r15, 8 - sbi r5, r0, 0x4020 # delay slot - - - -.rodata -helloworld: - .asciz "Hello, World!(2)" - -.data -testdata: - .word 0xdeadbeef +brai 0x08000000 diff --git a/firmware/uart.c b/firmware/uart.c index caf75d3..a73fcea 100644 --- a/firmware/uart.c +++ b/firmware/uart.c @@ -4,8 +4,8 @@ #include "uart.h" -static volatile unsigned char *_uart_sreg = (unsigned char *)0x10021; -static volatile unsigned char *_uart_dreg = (unsigned char *)0x10020; +static volatile unsigned char *_uart_sreg = (unsigned char *)0x08010021; +static volatile unsigned char *_uart_dreg = (unsigned char *)0x08010020; static bool _uart_writefull() { return ((*_uart_sreg&0x2)==0x2); diff --git a/mblite/config_Pkg.vhd b/mblite/config_Pkg.vhd index 3bcd5f1..c44c2d6 100644 --- a/mblite/config_Pkg.vhd +++ b/mblite/config_Pkg.vhd @@ -36,7 +36,7 @@ package config_Pkg is -- Memory parameters constant CFG_DMEM_SIZE : positive := 28; -- Data memory bus size in 2LOG # elements - constant CFG_IMEM_SIZE : positive := 14; -- Instruction memory bus size in 2LOG # elements + constant CFG_IMEM_SIZE : positive := 28; -- Instruction memory bus size in 2LOG # elements constant CFG_BYTE_ORDER : boolean := true; -- Switch between MSB (1, default) and LSB (0) byte order policy -- Register parameters diff --git a/mblite_cache_tb.wcfg b/mblite_cache_tb.wcfg new file mode 100644 index 0000000..97e16d9 --- /dev/null +++ b/mblite_cache_tb.wcfg @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clk_i + clk_i + + + rst_i + rst_i + + + cpui_dat_i[31:0] + cpui_dat_i[31:0] + HEXRADIX + + + cpui_adr_o[25:2] + cpui_adr_o[25:2] + HEXRADIX + + + cpui_ena_o + cpui_ena_o + + + cpud_dat_i[31:0] + cpud_dat_i[31:0] + HEXRADIX + + + cpud_dat_o[31:0] + cpud_dat_o[31:0] + HEXRADIX + + + cpud_adr_o[25:2] + cpud_adr_o[25:2] + HEXRADIX + + + cpud_sel_o[3:0] + cpud_sel_o[3:0] + + + cpud_we_o + cpud_we_o + + + cpud_ena_o + cpud_ena_o + + + cpu_wait + cpu_wait + + + mem_rdrq + mem_rdrq + + + mem_wrrq + mem_wrrq + + + mem_adr[22:0] + mem_adr[22:0] + HEXRADIX + + + mem_dat_o[63:0] + mem_dat_o[63:0] + HEXRADIX + + + mem_sel[7:0] + mem_sel[7:0] + + + mem_ack + mem_ack + + + mem_dat_i[63:0] + mem_dat_i[63:0] + HEXRADIX + + + instr_reset + instr_reset + + + reset_ctr + reset_ctr + + + cram_adra[9:0] + cram_adra[9:0] + + + cram_adrb[9:0] + cram_adrb[9:0] + + + cram_doa[63:0] + cram_doa[63:0] + HEXRADIX + + + cram_dob[63:0] + cram_dob[63:0] + HEXRADIX + + + cram_dib[63:0] + cram_dib[63:0] + HEXRADIX + + + cram_bwe[7:0] + cram_bwe[7:0] + + + cc_tag[127:0] + cc_tag[127:0] + + + cc_lru[127:0] + cc_lru[127:0] + + + cc_valid[127:0] + cc_valid[127:0] + + + cc_dirty[127:0] + cc_dirty[127:0] + + + cc_we + cc_we + + + cc_adra[6:0] + cc_adra[6:0] + + + cc_adrb[6:0] + cc_adrb[6:0] + + + cc_lru_adr[6:0] + cc_lru_adr[6:0] + + + cc_tag_dib[27:0] + cc_tag_dib[27:0] + + + cc_tag_doa[27:0] + cc_tag_doa[27:0] + + + cc_tag_dob[27:0] + cc_tag_dob[27:0] + + + cc_lru_di[0:0] + cc_lru_di[0:0] + + + cc_lru_do[0:0] + cc_lru_do[0:0] + + + cc_valid_dib[1:0] + cc_valid_dib[1:0] + + + cc_valid_doa[1:0] + cc_valid_doa[1:0] + + + cc_valid_dob[1:0] + cc_valid_dob[1:0] + + + cc_dirty_dib[1:0] + cc_dirty_dib[1:0] + + + cc_dirty_dob[1:0] + cc_dirty_dob[1:0] + + + cpu_wait_int + cpu_wait_int + + + instr_wait + instr_wait + + + data_wait + data_wait + + + instr_hit[1:0] + instr_hit[1:0] + + + data_hit[1:0] + data_hit[1:0] + + + mem_active + mem_active + + + cc_adrb_dp[6:0] + cc_adrb_dp[6:0] + + + cc_adrb_mp[6:0] + cc_adrb_mp[6:0] + + + cc_dirty_dib_dp[1:0] + cc_dirty_dib_dp[1:0] + + + cc_dirty_dib_mp[1:0] + cc_dirty_dib_mp[1:0] + + + cc_we_dp + cc_we_dp + + + cc_we_mp + cc_we_mp + + + cc_lru_we + cc_lru_we + + + cram_adrb_dp[9:0] + cram_adrb_dp[9:0] + + + cram_adrb_mp[9:0] + cram_adrb_mp[9:0] + + + cram_dib_dp[63:0] + cram_dib_dp[63:0] + HEXRADIX + + + cram_dib_mp[63:0] + cram_dib_mp[63:0] + HEXRADIX + + + cram_bwe_dp[7:0] + cram_bwe_dp[7:0] + + + cram_bwe_mp[7:0] + cram_bwe_mp[7:0] + + + cc_lru_adr_lc[6:0] + cc_lru_adr_lc[6:0] + + + cc_lru_adr_mp[6:0] + cc_lru_adr_mp[6:0] + + + cpui_adr_o_reg[25:2] + cpui_adr_o_reg[25:2] + HEXRADIX + + + cpui_adr_o_mux[25:2] + cpui_adr_o_mux[25:2] + HEXRADIX + + + cpud_adr_o_reg[25:2] + cpud_adr_o_reg[25:2] + HEXRADIX + + + cpud_adr_o_mux[25:2] + cpud_adr_o_mux[25:2] + HEXRADIX + + + cpud_dat_o_reg[31:0] + cpud_dat_o_reg[31:0] + HEXRADIX + + + cpud_dat_o_mux[31:0] + cpud_dat_o_mux[31:0] + HEXRADIX + + + cpud_sel_o_reg[3:0] + cpud_sel_o_reg[3:0] + + + cpud_sel_o_mux[3:0] + cpud_sel_o_mux[3:0] + + + cpud_we_o_reg + cpud_we_o_reg + + + cpud_we_o_mux + cpud_we_o_mux + + + data_miss + data_miss + + + mem_state + mem_state + + + eject[0:0] + eject[0:0] + + + eject_dirty + eject_dirty + + + adr_reg[25:2] + adr_reg[25:2] + HEXRADIX + + + ctr + ctr + + diff --git a/src/mblite_cache.vhd b/src/mblite_cache.vhd new file mode 100644 index 0000000..929e2d1 --- /dev/null +++ b/src/mblite_cache.vhd @@ -0,0 +1,493 @@ +------------------------------------------------------------------------------- +-- Title : I/D Cache for MBlite CPU +-- Project : +------------------------------------------------------------------------------- +-- File : mblite_cache.vhd +-- Author : Matthias Blankertz +-- Company : +-- Created : 2013-06-08 +-- Last update: 2013-06-19 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: +------------------------------------------------------------------------------- +-- Copyright (c) 2013 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-06-08 1.0 matthias Created +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +use work.intercon_package.all; + +library mblite; +use mblite.core_Pkg.all; + +entity mblite_cache is + generic ( + dontcare : std_logic := '-' + ); + port ( + clk_i : in std_logic; + rst_i : in std_logic; + + cpui_dat_i : out std_logic_vector(31 downto 0); + cpui_adr_o : in std_logic_vector(25 downto 2); + cpui_ena_o : in std_logic; + + cpud_dat_i : out std_logic_vector(31 downto 0); + cpud_dat_o : in std_logic_vector(31 downto 0); + cpud_adr_o : in std_logic_vector(25 downto 2); + cpud_sel_o : in std_logic_vector(3 downto 0); + cpud_we_o : in std_logic; + cpud_ena_o : in std_logic; + + cpu_wait : out std_logic; + + mem_rdrq : out std_logic; + mem_wrrq : out std_logic; + mem_adr : out std_logic_vector(22 downto 0); + mem_dat_o : out std_logic_vector(63 downto 0); + mem_sel : out std_logic_vector(7 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(63 downto 0) + ); +end mblite_cache; + +architecture Mixed of mblite_cache is + attribute ram_style : string; + + constant lines : integer := 256; + constant lines_ln2 : integer := 8; + constant line_size : integer := 4; + constant line_size_ln2 : integer := 2; + + constant tag_width : integer := (24-(line_size_ln2+1)-(lines_ln2-1)); + + type reset_inst_arr is array(0 to 1) of std_logic_vector(31 downto 0); + -- brai 0x08000000 (Jump to ROM) + constant reset_instr : reset_inst_arr := (x"b0000800", x"b8080000"); + signal instr_reset, instr_reset_wait : std_logic := '1'; + signal reset_ctr : integer range 0 to 1 := 0; + + signal cram_adra, cram_adrb : std_logic_vector(lines_ln2+line_size_ln2-1 downto 0); + signal cram_doa, cram_dob, cram_dib : std_logic_vector(63 downto 0); + signal cram_bwe : std_logic_vector(7 downto 0) := (others => '0'); + + -- Cache control signals / memory + subtype tag_t is std_logic_vector(2*tag_width-1 downto 0); + subtype lru_t is unsigned(0 downto 0); + type cc_tag_a is array(lines/2-1 downto 0) of tag_t; + type cc_lru_a is array(lines/2-1 downto 0) of lru_t; + type cc_valid_a is array(lines/2-1 downto 0) of std_logic_vector(1 downto 0); + type cc_dirty_a is array(lines/2-1 downto 0) of std_logic_vector(1 downto 0); + signal cc_tag : cc_tag_a := (others => (others => dontcare)); + signal cc_lru : cc_lru_a := (others => (others => dontcare)); + signal cc_valid : cc_valid_a := (others => (others => '0')); + signal cc_dirty : cc_dirty_a := (others => (others => dontcare)); + attribute ram_style of cc_tag : signal is "distributed"; + attribute ram_style of cc_lru : signal is "distributed"; + attribute ram_style of cc_valid : signal is "distributed"; + attribute ram_style of cc_dirty : signal is "distributed"; + signal cc_we : std_logic := '0'; + signal cc_adra, cc_adrb, cc_lru_adr : unsigned(lines_ln2-2 downto 0) := (others => dontcare); + signal cc_tag_dib, cc_tag_doa, cc_tag_dob : tag_t := (others => dontcare); + signal cc_lru_di, cc_lru_do : lru_t := (others => dontcare); + signal cc_valid_dib, cc_valid_doa, cc_valid_dob : std_logic_vector(1 downto 0) := (others => '0'); + signal cc_dirty_dib, cc_dirty_dob : std_logic_vector(1 downto 0) := (others => dontcare); + + signal cpu_wait_int, instr_wait, data_wait : std_logic := '0'; + signal instr_hit, data_hit : std_logic_vector(1 downto 0); + signal mem_active : std_logic := '0'; + + -- Port B of cache RAM and control RAM is shared between data port (dp) and + -- memory interface (mp). mp has control when mem_active is '1' + signal cc_adrb_dp, cc_adrb_mp : unsigned(lines_ln2-2 downto 0); + signal cc_tag_dib_mp : tag_t := (others => dontcare); + signal cc_valid_dib_mp : std_logic_vector(1 downto 0) := (others => '0'); + signal cc_dirty_dib_dp, cc_dirty_dib_mp : std_logic_vector(1 downto 0); + signal cc_we_dp, cc_we_mp, cc_lru_we : std_logic := '0'; + signal cram_adrb_dp, cram_adrb_mp : std_logic_vector(lines_ln2+line_size_ln2-1 downto 0); + signal cram_dib_dp, cram_dib_mp : std_logic_vector(63 downto 0); + signal cram_bwe_dp, cram_bwe_mp : std_logic_vector(7 downto 0) := (others => '0'); + + -- LRU ram port is shared between lru controller (lc) and memory interface (mp) + signal cc_lru_adr_lc, cc_lru_adr_mp : unsigned(lines_ln2-2 downto 0); + + signal cpui_adr_o_reg, cpui_adr_o_mux : std_logic_vector(25 downto 2); + signal cpui_adr_o2_dly : std_logic; + + signal cpud_adr_o_reg, cpud_adr_o_mux : std_logic_vector(25 downto 2); + signal cpud_dat_o_reg, cpud_dat_o_mux : std_logic_vector(31 downto 0); + signal cpud_sel_o_reg, cpud_sel_o_mux : std_logic_vector(3 downto 0); + signal cpud_we_o_reg, cpud_we_o_mux : std_logic; + signal cpud_adr_o2_dly : std_logic; + + signal data_miss : std_logic := '0'; + + type mem_states is (S_IDLE, S_STARTDLY, S_START, S_READMEM); + signal mem_state : mem_states := S_IDLE; + signal eject, eject_reg : unsigned(0 downto 0); + signal eject_dirty : std_logic; + signal adr_reg : std_logic_vector(25 downto 2); + signal ctr : integer range 0 to 3; +begin + + cache_ram : entity work.mblite_cache_ram + generic map ( + lines => 256, + line_size => 4, + lines_ln2 => 8, + line_size_ln2 => 2 + ) + port map ( + clk_i => clk_i, + -- RO port + adra => cram_adra, + doa => cram_doa, + -- R/W port + adrb => cram_adrb, + dib => cram_dib, + dob => cram_dob, + bweb => cram_bwe + ); + + -- Syncronous write port for cache control + cc_mem_wr : process(clk_i) + begin + if rising_edge(clk_i) then + if cc_we = '1' then + cc_dirty(to_integer(cc_adrb)) <= cc_dirty_dib; + end if; + + if cc_we_mp = '1' and mem_active = '1' then + cc_tag(to_integer(cc_adrb)) <= cc_tag_dib; + cc_valid(to_integer(cc_adrb)) <= cc_valid_dib; + end if; + if cc_lru_we = '1' then + cc_lru(to_integer(cc_lru_adr)) <= cc_lru_di; + end if; + end if; + end process cc_mem_wr; + + -- Asynchronous read ports for cache control + cc_mem_rd : process(cc_tag, cc_valid, cc_dirty, cc_adra, cc_adrb, cc_lru, cc_lru_adr) + begin + cc_tag_doa <= cc_tag(to_integer(cc_adra)); + cc_valid_doa <= cc_valid(to_integer(cc_adra)); + + cc_tag_dob <= cc_tag(to_integer(cc_adrb)); + cc_lru_do <= cc_lru(to_integer(cc_lru_adr)); + cc_valid_dob <= cc_valid(to_integer(cc_adrb)); + cc_dirty_dob <= cc_dirty(to_integer(cc_adrb)); + end process cc_mem_rd; + + cc_adrb <= cc_adrb_dp when mem_active = '0' else + cc_adrb_mp; + cc_dirty_dib <= cc_dirty_dib_dp when mem_active = '0' else + cc_dirty_dib_mp; + cc_tag_dib <= --cc_tag_dob when mem_active = '0' else + cc_tag_dib_mp; + cc_valid_dib <= --cc_valid_dob when mem_active = '0' else + cc_valid_dib_mp; + cc_we <= cc_we_dp when mem_active = '0' else + cc_we_mp; + cram_dib <= cram_dib_dp when mem_active = '0' else + cram_dib_mp; + cram_adrb <= cram_adrb_dp when mem_active = '0' else + cram_adrb_mp; + cram_bwe <= cram_bwe_dp when mem_active = '0' else + cram_bwe_mp; + cc_lru_adr <= cc_lru_adr_lc when mem_active = '0' else + cc_lru_adr_mp; + + +------------------------------------------------------------------------------- +-- Instruction port +------------------------------------------------------------------------------- + + instr_regs : process(clk_i) + begin + if rising_edge(clk_i) then + if cpu_wait_int = '0' and cpui_ena_o = '1' then + cpui_adr_o_reg <= cpui_adr_o; + end if; + cpui_adr_o2_dly <= cpui_adr_o_mux(2); + end if; + end process instr_regs; + + cpui_adr_o_mux <= cpui_adr_o when cpu_wait_int = '0' else + cpui_adr_o_reg; + + cc_adra <= unsigned(cpui_adr_o_mux((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3)); + instr_hit(0) <= + cc_valid_doa(0) when cc_tag_doa(tag_width-1 downto 0) = cpui_adr_o_mux(25 downto (lines_ln2-1)+line_size_ln2+3) else + '0'; + instr_hit(1) <= + cc_valid_doa(1) when cc_tag_doa(2*tag_width-1 downto tag_width) = cpui_adr_o_mux(25 downto (lines_ln2-1)+line_size_ln2+3) else + '0'; + -- Index + cram_adra(lines_ln2+line_size_ln2-1 downto line_size_ln2+1) + <= cpui_adr_o_mux((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3); + -- Set + cram_adra(line_size_ln2) <= instr_hit(1); + -- Offset + cram_adra(line_size_ln2-1 downto 0) <= cpui_adr_o_mux(line_size_ln2+2 downto 3); + + cpui_dat_i <= reset_instr(reset_ctr) when instr_reset = '1' else + cram_doa(63 downto 32) when cpui_adr_o2_dly = '1' else + cram_doa(31 downto 0); + + instr_ctrl : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + instr_reset <= '1'; + instr_reset_wait <= '1'; + instr_wait <= '0'; + reset_ctr <= 0; + else + if cpu_wait_int = '0' and cpui_ena_o = '1' and instr_reset = '1' then + -- Send reset vector to CPU + instr_wait <= '0'; + if instr_reset_wait = '1' then + instr_reset_wait <= '0'; + else + if reset_ctr = 1 then + instr_reset <= '0'; + else + reset_ctr <= reset_ctr + 1; + end if; + end if; + elsif (cpui_ena_o = '1' or instr_wait = '1') and instr_hit /= "00" then +-- elsif ((cpu_wait_int = '0' and cpui_ena_o = '1') or instr_wait = '1') and instr_hit /= "00" then + -- Cache hit + instr_wait <= '0'; + elsif cpui_ena_o = '1' and instr_hit = "00" then + -- Cache miss + instr_wait <= '1'; + end if; + end if; + end if; + end process instr_ctrl; + + +------------------------------------------------------------------------------- +-- Data port +------------------------------------------------------------------------------- + + data_regs : process(clk_i) + begin + if rising_edge(clk_i) then + if cpu_wait_int = '0' and cpud_ena_o = '1' then + cpud_adr_o_reg <= cpud_adr_o; + cpud_dat_o_reg <= cpud_dat_o; + cpud_sel_o_reg <= cpud_sel_o; + cpud_we_o_reg <= cpud_we_o; + end if; + cpud_adr_o2_dly <= cpud_adr_o_mux(2); + end if; + end process data_regs; + + cpud_adr_o_mux <= cpud_adr_o when cpu_wait_int = '0' else + cpud_adr_o_reg; + cpud_dat_o_mux <= cpud_dat_o when cpu_wait_int = '0' else + cpud_dat_o_reg; + cpud_sel_o_mux <= cpud_sel_o when cpu_wait_int = '0' else + cpud_sel_o_reg; + cpud_we_o_mux <= cpud_we_o when cpu_wait_int = '0' else + cpud_we_o_reg; + + -- CC ram address + cc_adrb_dp <= unsigned(cpud_adr_o_mux((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3)); + data_hit(0) <= + cc_valid_dob(0) when cc_tag_dob(tag_width-1 downto 0) = cpud_adr_o_mux(25 downto (lines_ln2-1)+line_size_ln2+3) else + '0'; + data_hit(1) <= + cc_valid_dob(1) when cc_tag_dob(2*tag_width-1 downto tag_width) = cpud_adr_o_mux(25 downto (lines_ln2-1)+line_size_ln2+3) else + '0'; + -- Index + cram_adrb_dp(lines_ln2+line_size_ln2-1 downto line_size_ln2+1) + <= cpud_adr_o_mux((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3); + -- Set + cram_adrb_dp(line_size_ln2) <= data_hit(1); + -- Offset + cram_adrb_dp(line_size_ln2-1 downto 0) <= cpud_adr_o_mux(line_size_ln2+2 downto 3); + -- Write + cram_bwe_dp <= "0000" & cpud_sel_o_mux when (cpud_we_o_mux = '1' and cpud_adr_o_mux(2) = '0' and + (cpud_ena_o = '1' or data_wait = '1') and data_hit /= "00") else + cpud_sel_o_mux & "0000" when (cpud_we_o_mux = '1' and cpud_adr_o_mux(2) = '1' and + (cpud_ena_o = '1' or data_wait = '1') and data_hit /= "00") else + "00000000"; + cram_dib_dp <= cpud_dat_o_mux & cpud_dat_o_mux; + -- Read + cpud_dat_i <= cram_dob(63 downto 32) when cpud_adr_o2_dly = '1' else + cram_dob(31 downto 0); + + -- Update dirty on write + cc_dirty_dib_dp <= data_hit or cc_dirty_dob; + cc_we_dp <= cpud_we_o when (cpud_ena_o = '1' or data_wait = '1') and data_hit /= "00" else + '0'; + + data_ctrl : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + data_wait <= '0'; + data_miss <= '0'; + else + if (cpud_ena_o = '1' or data_miss = '1') and mem_active = '1' then + -- Can't access cache when memory controller is using port + data_wait <= '1'; + elsif (cpud_ena_o = '1' or data_wait = '1') and data_hit /= "00" then + -- Cache hit + data_miss <= '0'; + data_wait <= '0'; + elsif cpud_ena_o = '1' and data_hit = "00" then + -- Cache miss + data_miss <= '1'; + data_wait <= '1'; + end if; + end if; + end if; + end process data_ctrl; + + +------------------------------------------------------------------------------- +-- LRU tracker +------------------------------------------------------------------------------- + cc_lru_adr_lc <= cc_adrb_dp when cpu_wait_int = '0' and cpud_ena_o = '1' and data_hit /= "00" else + cc_adra; + cc_lru_di <= "1" when cpu_wait_int = '0' and cpud_ena_o = '1' and data_hit = "01" else + "0" when cpu_wait_int = '0' and cpud_ena_o = '1' and data_hit = "10" else + "1" when cpu_wait_int = '0' and cpui_ena_o = '1' and instr_hit = "01" else + "0" when cpu_wait_int = '0' and cpui_ena_o = '1' and instr_hit = "10" else + cc_lru_do; + cc_lru_we <= ((not cpu_wait_int and cpud_ena_o and (data_hit(0) or data_hit(1))) or + (not cpu_wait_int and cpui_ena_o and (instr_hit(0) or instr_hit(1)))) and + not mem_active; + + + +------------------------------------------------------------------------------- +-- Memory interface +------------------------------------------------------------------------------- + + eject <= "-" when mem_active = '0' else + "0" when cc_valid_dob(0) = '0' else + "1" when cc_valid_dob(1) = '0' else + cc_lru_do; + eject_dirty <= '-' when mem_active = '0' else + cc_dirty_dob(to_integer(eject)) and cc_valid_dob(to_integer(eject)); + + mem_active <= '0' when mem_state = S_IDLE else + '1'; + + cc_adrb_mp <= unsigned(adr_reg((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3)); + cc_lru_adr_mp <= unsigned(adr_reg((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3)); + + cc_upd : process(clk_i) --process(cc_valid_dob, cc_dirty_dob, cc_tag_dob, eject, adr_reg) + begin + if rising_edge(clk_i) then + cc_valid_dib_mp <= cc_valid_dob; + cc_dirty_dib_mp <= cc_dirty_dob; + cc_tag_dib_mp <= cc_tag_dob; + + if eject = 0 then + cc_valid_dib_mp(0) <= '1'; + cc_dirty_dib_mp(0) <= '0'; + cc_tag_dib_mp(tag_width-1 downto 0) <= adr_reg(25 downto (lines_ln2-1)+line_size_ln2+3); + else + cc_valid_dib_mp(1) <= '1'; + cc_dirty_dib_mp(1) <= '0'; + cc_tag_dib_mp(2*tag_width-1 downto tag_width) <= adr_reg(25 downto (lines_ln2-1)+line_size_ln2+3); + end if; + end if; + end process cc_upd; + + cc_we_mp <= '1' when mem_ack = '1' and ctr = 3 and mem_state = S_READMEM else + '0'; + + cram_dib_mp <= mem_dat_i; + cram_bwe_mp <= x"ff" when mem_ack = '1' else + x"00"; + -- Index + cram_adrb_mp(lines_ln2+line_size_ln2-1 downto line_size_ln2+1) + <= adr_reg((lines_ln2-1)+line_size_ln2+2 downto line_size_ln2+3); + -- Set + cram_adrb_mp(line_size_ln2 downto line_size_ln2) <= std_logic_vector(eject_reg); + -- Offset + cram_adrb_mp(line_size_ln2-1 downto 0) + <= std_logic_vector(unsigned(adr_reg(line_size_ln2+2 downto 3))+to_unsigned(ctr, 2)); + + mem_ctrl : process(clk_i) + begin + if rising_edge(clk_i) then + mem_rdrq <= '0'; + mem_wrrq <= '0'; + mem_adr <= (others => dontcare); + + if rst_i = '1' then + mem_state <= S_IDLE; + else + case mem_state is + when S_IDLE => + if (cpui_ena_o = '1' or instr_wait = '1') and instr_hit = "00" and instr_reset = '0' then + -- Instruction read miss + adr_reg <= cpui_adr_o_mux; + mem_state <= S_STARTDLY; + elsif (cpud_ena_o = '1' or data_miss = '1') and data_hit = "00" then + -- Data miss + adr_reg <= cpud_adr_o_mux; + mem_state <= S_STARTDLY; + end if; + when S_STARTDLY => + mem_state <= S_START; + when S_START => + if eject_dirty = '1' then + -- Flush line + --mem_wrrq <= '1'; + --mem_adr <= + null; + else + -- Fetch new line + mem_rdrq <= '1'; + mem_adr <= adr_reg(25 downto line_size_ln2+1); + ctr <= 0; + mem_state <= S_READMEM; + end if; + when S_READMEM => + if mem_ack = '1' then + if ctr = 3 then + -- Fetch complete + mem_state <= S_IDLE; + else + ctr <= ctr + 1; + end if; + end if; + end case; + end if; + + --eject_dirty <= cc_dirty_dob(to_integer(eject)) and cc_valid_dob(to_integer(eject)); + eject_reg <= eject; + end if; + end process mem_ctrl; + + + cpu_wait_int <= instr_wait or data_wait; + cpu_wait <= cpu_wait_int; + +end Mixed; diff --git a/src/mblite_cache_ram.vhd b/src/mblite_cache_ram.vhd new file mode 100644 index 0000000..91dfab9 --- /dev/null +++ b/src/mblite_cache_ram.vhd @@ -0,0 +1,176 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 11/06/2012 03:04:35 PM +-- Design Name: +-- Module Name: mblite_cache_ram - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: Memory controller - system clock domain - Cache front-end - +-- RAM +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +library UNISIM; +use UNISIM.VComponents.all; + +entity mblite_cache_ram is + + generic ( + lines : integer; + line_size : integer; + lines_ln2 : integer; + line_size_ln2 : integer); + + port ( + clk_i : in std_logic; + adra : in std_logic_vector(lines_ln2+line_size_ln2-1 downto 0); + doa : out std_logic_vector(63 downto 0); + adrb : in std_logic_vector(lines_ln2+line_size_ln2-1 downto 0); + dib : in std_logic_vector(63 downto 0); + dob : out std_logic_vector(63 downto 0); + bweb : in std_logic_vector(7 downto 0)); + +end mblite_cache_ram; + +architecture Behavioral of mblite_cache_ram is + --attribute ram_style : string; + + --type cache_arr is array(lines*line_size-1 downto 0) of std_logic_vector(31 downto 0); + --signal cache_hi, cache_lo : cache_arr := (others => (others => '-')); + --attribute ram_style of cache_hi : signal is "block"; + --attribute ram_style of cache_lo : signal is "block"; + + --signal di7, di6, di5, di4, di3, di2, di1, di0 : std_logic_vector(7 downto 0); + + --signal dib_hi, dib_lo, doa_hi, doa_lo, dob_hi, dob_lo : std_logic_vector(31 downto 0); + --signal bwe_hi, bwe_lo : std_logic_vector(3 downto 0); + +begin + + ram_gen : for i in 0 to 3 generate + ram_inst : RAMB16BWE_S18_S18 + port map ( + CLKA => clk_i, + CLKB => clk_i, + + DOA => doa(16*i+15 downto 16*i), + DOPA => open, + DIA => x"0000", + DIPA => "00", + ADDRA => adra, + WEA => "00", + ENA => '1', + SSRA => '0', + + DOB => dob(16*i+15 downto 16*i), + DOPB => open, + DIB => dib(16*i+15 downto 16*i), + DIPB => "00", + ADDRB => adrb, + WEB => bweb(2*i+1 downto 2*i), + ENB => '1', + SSRB => '0' + ); + end generate; + + + +-- dib_hi <= dib(63 downto 32); +-- dib_lo <= dib(31 downto 0); +-- dob <= dob_hi & dob_lo; +-- doa <= doa_hi & doa_lo; +-- bwe_hi <= bweb(7 downto 4); +-- bwe_lo <= bweb(3 downto 0); + +-- cache_hi_din : process(dib_hi, adrb, bwe_hi) +-- begin +-- if bwe_hi(3) = '1' then +-- di7 <= dib_hi(31 downto 24); +-- else +-- di7 <= cache_hi(to_integer(adrb))(31 downto 24); +-- end if; + +-- if bwe_hi(2) = '1' then +-- di6 <= dib_hi(23 downto 16); +-- else +-- di6 <= cache_hi(to_integer(adrb))(23 downto 16); +-- end if; + +-- if bwe_hi(1) = '1' then +-- di5 <= dib_hi(15 downto 8); +-- else +-- di5 <= cache_hi(to_integer(adrb))(15 downto 8); +-- end if; + +-- if bwe_hi(0) = '1' then +-- di4 <= dib_hi(7 downto 0); +-- else +-- di4 <= cache_hi(to_integer(adrb))(7 downto 0); +-- end if; +-- end process cache_hi_din; + +-- cache_lo_din : process(dib_lo, adrb, bwe_lo) +-- begin +-- if bwe_lo(3) = '1' then +-- di3 <= dib_lo(31 downto 24); +-- else +-- di3 <= cache_lo(to_integer(adrb))(31 downto 24); +-- end if; + +-- if bwe_lo(2) = '1' then +-- di2 <= dib_lo(23 downto 16); +-- else +-- di2 <= cache_lo(to_integer(adrb))(23 downto 16); +-- end if; + +-- if bwe_lo(1) = '1' then +-- di1 <= dib_lo(15 downto 8); +-- else +-- di1 <= cache_lo(to_integer(adrb))(15 downto 8); +-- end if; + +-- if bwe_lo(0) = '1' then +-- di0 <= dib_lo(7 downto 0); +-- else +-- di0 <= cache_lo(to_integer(adrb))(7 downto 0); +-- end if; +-- end process cache_lo_din; + +-- -- Memory for cache data +-- cache_mem_hi : process(clk_i) +-- begin +-- if rising_edge(clk_i) then +-- cache_hi(to_integer(adrb)) <= di7 & di6 & di5 & di4; +-- dob_hi <= cache_hi(to_integer(adrb)); +-- doa_hi <= cache_hi(to_integer(adra)); +-- end if; +-- end process cache_mem_hi; + +-- cache_mem_lo : process(clk_i) +-- begin +-- if rising_edge(clk_i) then +-- cache_lo(to_integer(adrb)) <= di3 & di2 & di1 & di0; +-- dob_lo <= cache_lo(to_integer(adrb)); +-- doa_lo <= cache_lo(to_integer(adra)); +-- end if; +-- end process cache_mem_lo; +end Behavioral; diff --git a/src/mblite_wbm.vhd b/src/mblite_wbm.vhd new file mode 100644 index 0000000..66f99ba --- /dev/null +++ b/src/mblite_wbm.vhd @@ -0,0 +1,96 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone master for MBlite CPU +-- Project : +------------------------------------------------------------------------------- +-- File : mblite_wbm.vhd +-- Author : Matthias Blankertz +-- Company : +-- Created : 2013-06-08 +-- Last update: 2013-06-08 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: +------------------------------------------------------------------------------- +-- Copyright (c) 2013 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-06-08 1.0 matthias Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library mblite; +use mblite.core_Pkg.all; + +use work.intercon_package.all; + +entity mblite_wbm is + port ( + clk_i : std_logic; + rst_i : std_logic; + + cpu_dat_i : out std_logic_vector(31 downto 0); + cpu_dat_o : in std_logic_vector(31 downto 0); + cpu_adr_o : in std_logic_vector(26 downto 0); + cpu_sel_o : in std_logic_vector(3 downto 0); + cpu_we_o : in std_logic; + cpu_ena_o : in std_logic; + + cpu_wait : out std_logic; + + wbm_i : in cpu_wbm_i_type; + wbm_o : out cpu_wbm_o_type + ); +end mblite_wbm; + +architecture Behavioral of mblite_wbm is + signal wb_in_cyc, cpu_wait_int : std_logic := '0'; + signal q_adr_o : std_logic_vector(26 downto 0); + signal q_dat_o : std_logic_vector(31 downto 0); + signal q_sel_o : std_logic_vector(3 downto 0); + signal q_we_o : std_logic; + signal queued : std_logic := '0'; +begin + + wbm : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + wb_in_cyc <= '0'; + queued <= '0'; + else + if wb_in_cyc = '1' and wbm_i.ack_i = '1' then + -- Wishbone cycle complete + wb_in_cyc <= '0'; + elsif cpu_ena_o = '1' and wbm_i.ack_i = '1' then + -- CPU request, but WB bus not free + null; + elsif wb_in_cyc = '1' and cpu_ena_o = '1' then + -- back-to-back requests + queued <= '1'; + elsif cpu_ena_o = '1' and wb_in_cyc = '0' and wbm_i.ack_i = '0' then + -- new request + wbm_o.adr_o <= cpu_adr_o; + wbm_o.we_o <= cpu_we_o; + wbm_o.sel_o <= cpu_sel_o; + wbm_o.dat_o <= cpu_dat_o; + wb_in_cyc <= '1'; + queued <= '0'; + end if; + end if; + end if; + end process wbm; + + wbm_o.cyc_o <= wb_in_cyc or wbm_i.ack_i; + wbm_o.stb_o <= wb_in_cyc; + + cpu_wait_int <= (not wb_in_cyc and wbm_i.ack_i and cpu_ena_o) or (wb_in_cyc and not wbm_i.ack_i) or (wb_in_cyc and cpu_ena_o); + cpu_wait <= cpu_wait_int;-- or queued; + cpu_dat_i <= wbm_i.dat_i; + + +end Behavioral; diff --git a/src/mblite_wrapper.vhd b/src/mblite_wrapper.vhd index 7989190..32a9705 100644 --- a/src/mblite_wrapper.vhd +++ b/src/mblite_wrapper.vhd @@ -6,7 +6,7 @@ -- Author : Matthias Blankertz -- Company : -- Created : 2013-06-02 --- Last update: 2013-06-07 +-- Last update: 2013-06-08 -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- @@ -45,53 +45,120 @@ entity mblite_wrapper is wbm_o : out cpu_wbm_o_type; rom_wbs_i : in mblite_rom_wbs_i_type; - rom_wbs_o : out mblite_rom_wbs_o_type + rom_wbs_o : out mblite_rom_wbs_o_type; + + mem_rdrq : out std_logic; + mem_wrrq : out std_logic; + mem_adr : out std_logic_vector(22 downto 0); + mem_dat_o : out std_logic_vector(63 downto 0); + mem_sel : out std_logic_vector(7 downto 0); + mem_ack : in std_logic; + mem_dat_i : in std_logic_vector(63 downto 0) ); end mblite_wrapper; architecture Mixed of mblite_wrapper is signal mb_imem_o : imem_out_type; signal mb_imem_i : imem_in_type; - signal mb_wb_o : wb_mst_out_type; - signal mb_wb_i : wb_mst_in_type; -begin + signal mb_dmem_o : dmem_out_type; + signal mb_dmem_i : dmem_in_type; + signal mb_int_i : std_logic := '0'; - mb_wb_i.clk_i <= clk_i; - mb_wb_i.rst_i <= rst_i; - - mblite_inst : entity mblite.core_wb + signal wb_dat_i, cd_dat_i : std_logic_vector(31 downto 0); + signal ci_dat_i, rom_dat_i : std_logic_vector(31 downto 0); + signal wb_ena_o, cd_ena_o, ci_ena_o, rom_ena_o : std_logic; + signal wb_cpu_wait, c_cpu_wait : std_logic := '0'; + + signal mb_adr_o27_dly, mb_iadr_o27_dly : std_logic; +begin + dly : process(clk_i) + begin + if rising_edge(clk_i) then + if mb_dmem_i.ena_i = '1' then + mb_adr_o27_dly <= mb_dmem_o.adr_o(27); + mb_iadr_o27_dly <= mb_imem_o.adr_o(27); + end if; + end if; + end process dly; + + mblite_inst : entity mblite.core port map ( imem_o => mb_imem_o, imem_i => mb_imem_i, - wb_o => mb_wb_o, - wb_i => mb_wb_i + dmem_o => mb_dmem_o, + dmem_i => mb_dmem_i, + int_i => mb_int_i, + rst_i => rst_i, + clk_i => clk_i ); + mb_dmem_i.dat_i <= wb_dat_i when mb_adr_o27_dly = '1' else + cd_dat_i; + mb_dmem_i.ena_i <= not (wb_cpu_wait or c_cpu_wait); + + mb_imem_i.dat_i <= rom_dat_i when mb_iadr_o27_dly = '1' else + ci_dat_i; + + ci_ena_o <= mb_imem_o.ena_o and not mb_imem_o.adr_o(27); + cd_ena_o <= mb_dmem_o.ena_o and not mb_dmem_o.adr_o(27); + + mblite_cache_inst : entity work.mblite_cache + port map ( + clk_i => clk_i, + rst_i => rst_i, + + cpui_dat_i => ci_dat_i, + cpui_adr_o => mb_imem_o.adr_o(25 downto 2), + cpui_ena_o => ci_ena_o, + + cpud_dat_i => cd_dat_i, + cpud_dat_o => mb_dmem_o.dat_o, + cpud_adr_o => mb_dmem_o.adr_o(25 downto 2), + cpud_sel_o => mb_dmem_o.sel_o, + cpud_we_o => mb_dmem_o.we_o, + cpud_ena_o => cd_ena_o, + + cpu_wait => c_cpu_wait, + + mem_rdrq => mem_rdrq, + mem_wrrq => mem_wrrq, + mem_adr => mem_adr, + mem_dat_o => mem_dat_o, + mem_sel => mem_sel, + mem_ack => mem_ack, + mem_dat_i => mem_dat_i + ); + + rom_ena_o <= mb_imem_o.ena_o and mb_imem_o.adr_o(27); + mblite_rom_inst : entity work.mblite_rom port map ( clka => clk_i, - ena => mb_imem_o.ena_o, + ena => rom_ena_o, addra => mb_imem_o.adr_o(13 downto 2), - douta => mb_imem_i.dat_i, + douta => rom_dat_i, wbs_i => rom_wbs_i, wbs_o => rom_wbs_o ); - wb_reg : process(clk_i) - begin - if rising_edge(clk_i) then - wbm_o.adr_o <= mb_wb_o.adr_o; - wbm_o.we_o <= mb_wb_o.we_o; - wbm_o.sel_o <= mb_wb_o.sel_o; - end if; - end process wb_reg; - - wbm_o.dat_o <= mb_wb_o.dat_o; - wbm_o.stb_o <= mb_wb_o.stb_o; - wbm_o.cyc_o <= mb_wb_o.cyc_o; + wb_ena_o <= mb_dmem_o.ena_o and mb_dmem_o.adr_o(27); - mb_wb_i.dat_i <= wbm_i.dat_i; - mb_wb_i.ack_i <= wbm_i.ack_i; - mb_wb_i.int_i <= '0'; + mblite_wbm_inst : entity work.mblite_wbm + port map ( + clk_i => clk_i, + rst_i => rst_i, + + cpu_dat_i => wb_dat_i, + cpu_dat_o => mb_dmem_o.dat_o, + cpu_adr_o => mb_dmem_o.adr_o(26 downto 0), + cpu_sel_o => mb_dmem_o.sel_o, + cpu_we_o => mb_dmem_o.we_o, + cpu_ena_o => wb_ena_o, + + cpu_wait => wb_cpu_wait, + + wbm_i => wbm_i, + wbm_o => wbm_o + ); end Mixed; diff --git a/src/spi.vhd b/src/spi.vhd index 2308872..d1bb794 100644 --- a/src/spi.vhd +++ b/src/spi.vhd @@ -6,7 +6,7 @@ -- Author : Matthias Blankertz -- Company : -- Created : 2013-06-05 --- Last update: 2013-06-07 +-- Last update: 2013-06-19 -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- @@ -313,6 +313,6 @@ begin end if; end if; end process wb; - wbs_o.ack_o <= (ack_o_int or wbs_i.we_i) and wbs_i.stb_i; + wbs_o.ack_o <= ack_o_int; -- or wbs_i.we_i) and wbs_i.stb_i; end Behavioral; diff --git a/src/toplevel.vhd b/src/toplevel.vhd index afb2260..617210a 100755 --- a/src/toplevel.vhd +++ b/src/toplevel.vhd @@ -113,6 +113,14 @@ architecture Mixed of toplevel is signal wb_mem_sel : std_logic_vector(7 downto 0); signal wb_mem_ack : std_logic; signal wb_mem_dat_i : std_logic_vector(63 downto 0); + + signal cpu_mem_rdrq : std_logic := '0'; + signal cpu_mem_wrrq : std_logic := '0'; + signal cpu_mem_adr : std_logic_vector(22 downto 0); + signal cpu_mem_dat_o : std_logic_vector(63 downto 0); + signal cpu_mem_sel : std_logic_vector(7 downto 0); + signal cpu_mem_ack : std_logic; + signal cpu_mem_dat_i : std_logic_vector(63 downto 0); signal reset_int : std_logic; @@ -166,6 +174,14 @@ ddr_ctrl0 : entity work.wb_ddr_ctrl vga_mem_ack => vga_mem_ack, vga_mem_dat_i => vga_mem_dat_i, + cpu_mem_rdrq => cpu_mem_rdrq, + cpu_mem_wrrq => cpu_mem_wrrq, + cpu_mem_adr => cpu_mem_adr, + cpu_mem_dat_o => cpu_mem_dat_o, + cpu_mem_sel => cpu_mem_sel, + cpu_mem_ack => cpu_mem_ack, + cpu_mem_dat_i => cpu_mem_dat_i, + wb_mem_rdrq => wb_mem_rdrq, wb_mem_wrrq => wb_mem_wrrq, wb_mem_adr => wb_mem_adr, @@ -296,7 +312,15 @@ cpu_inst : entity work.mblite_wrapper wbm_o => cpu_wbm_o, rom_wbs_i => rom_wbs_i, - rom_wbs_o => rom_wbs_o + rom_wbs_o => rom_wbs_o, + + mem_rdrq => cpu_mem_rdrq, + mem_wrrq => cpu_mem_wrrq, + mem_adr => cpu_mem_adr, + mem_dat_o => cpu_mem_dat_o, + mem_sel => cpu_mem_sel, + mem_ack => cpu_mem_ack, + mem_dat_i => cpu_mem_dat_i ); fb_flip <= '0'; diff --git a/src/uart/uart_wbc.vhd b/src/uart/uart_wbc.vhd index 68e5eff..a598868 100755 --- a/src/uart/uart_wbc.vhd +++ b/src/uart/uart_wbc.vhd @@ -114,7 +114,7 @@ begin end if; end process wb; -ACK_O <= ACK_O_int and STB_I; +ACK_O <= ACK_O_int;-- and STB_I; uart_datain <= DAT_I; SERIALOUT <= serialout_o; diff --git a/src/wb_ddr_ctrl.vhd b/src/wb_ddr_ctrl.vhd index aabb11c..2d8e31b 100755 --- a/src/wb_ddr_ctrl.vhd +++ b/src/wb_ddr_ctrl.vhd @@ -71,8 +71,17 @@ entity wb_ddr_ctrl is vga_mem_adr : in std_logic_vector(19 downto 0); vga_mem_ack : out std_logic; vga_mem_dat_i : out std_logic_vector(63 downto 0); + + -- Port 1: RW, Prio 1 - CPU cache (BL4, MOD) + cpu_mem_rdrq : in std_logic; + cpu_mem_wrrq : in std_logic; + cpu_mem_adr : in std_logic_vector(22 downto 0); + cpu_mem_dat_o : in std_logic_vector(63 downto 0); + cpu_mem_sel : in std_logic_vector(7 downto 0); + cpu_mem_ack : out std_logic; + cpu_mem_dat_i : out std_logic_vector(63 downto 0); - -- Port 1: RW, Prio 1 - WB bridge + -- Port 2: RW, Prio 2 - WB bridge wb_mem_rdrq : in std_logic; wb_mem_wrrq : in std_logic; wb_mem_adr : in std_logic_vector(19 downto 0); @@ -167,6 +176,14 @@ wb_0 : entity work.wb_ddr_ctrl_wb vga_mem_ack => vga_mem_ack, vga_mem_dat_i => vga_mem_dat_i, + cpu_mem_rdrq => cpu_mem_rdrq, + cpu_mem_wrrq => cpu_mem_wrrq, + cpu_mem_adr => cpu_mem_adr, + cpu_mem_dat_o => cpu_mem_dat_o, + cpu_mem_sel => cpu_mem_sel, + cpu_mem_ack => cpu_mem_ack, + cpu_mem_dat_i => cpu_mem_dat_i, + wb_mem_rdrq => wb_mem_rdrq, wb_mem_wrrq => wb_mem_wrrq, wb_mem_adr => wb_mem_adr, diff --git a/src/wb_ddr_ctrl_wb.vhd b/src/wb_ddr_ctrl_wb.vhd index c24d74d..cbefc91 100755 --- a/src/wb_ddr_ctrl_wb.vhd +++ b/src/wb_ddr_ctrl_wb.vhd @@ -60,14 +60,23 @@ entity wb_ddr_ctrl_wb is clk_i : in std_ulogic; rst_i : in std_ulogic; --- Memory ports + -- Memory ports -- Port 0: RO, Prio 0 - VGA controller vga_mem_rdrq : in std_logic; vga_mem_adr : in std_logic_vector(19 downto 0); vga_mem_ack : out std_logic; vga_mem_dat_i : out std_logic_vector(63 downto 0); + + -- Port 1: RW, Prio 1 - CPU cache (BL4, MOD) + cpu_mem_rdrq : in std_logic; + cpu_mem_wrrq : in std_logic; + cpu_mem_adr : in std_logic_vector(22 downto 0); + cpu_mem_dat_o : in std_logic_vector(63 downto 0); + cpu_mem_sel : in std_logic_vector(7 downto 0); + cpu_mem_ack : out std_logic; + cpu_mem_dat_i : out std_logic_vector(63 downto 0); - -- Port 1: RW, Prio 1 - WB bridge + -- Port 2: RW, Prio 2 - WB bridge wb_mem_rdrq : in std_logic; wb_mem_wrrq : in std_logic; wb_mem_adr : in std_logic_vector(19 downto 0); @@ -133,6 +142,14 @@ system_cd_inst : entity work.wb_ddr_ctrl_wb_sc vga_mem_ack => vga_mem_ack, vga_mem_dat_i => vga_mem_dat_i, + cpu_mem_rdrq => cpu_mem_rdrq, + cpu_mem_wrrq => cpu_mem_wrrq, + cpu_mem_adr => cpu_mem_adr, + cpu_mem_dat_o => cpu_mem_dat_o, + cpu_mem_sel => cpu_mem_sel, + cpu_mem_ack => cpu_mem_ack, + cpu_mem_dat_i => cpu_mem_dat_i, + wb_mem_rdrq => wb_mem_rdrq, wb_mem_wrrq => wb_mem_wrrq, wb_mem_adr => wb_mem_adr, diff --git a/src/wb_ddr_ctrl_wb_sc.vhd b/src/wb_ddr_ctrl_wb_sc.vhd index 2559240..774c09f 100755 --- a/src/wb_ddr_ctrl_wb_sc.vhd +++ b/src/wb_ddr_ctrl_wb_sc.vhd @@ -33,8 +33,6 @@ use IEEE.NUMERIC_STD.ALL; entity wb_ddr_ctrl_wb_sc is generic ( - burst_length : integer := 8; - burst_length_ln2 : integer := 3; dontcare : std_logic := '-' ); port ( @@ -42,13 +40,22 @@ entity wb_ddr_ctrl_wb_sc is rst_i : in std_ulogic; -- Memory ports - -- Port 0: RO, Prio 0 - VGA controller + -- Port 0: RO, Prio 0 - VGA controller (BL8) vga_mem_rdrq : in std_logic; vga_mem_adr : in std_logic_vector(19 downto 0); vga_mem_ack : out std_logic; vga_mem_dat_i : out std_logic_vector(63 downto 0); + + -- Port 1: RW, Prio 1 - CPU cache (BL4, MOD) + cpu_mem_rdrq : in std_logic; + cpu_mem_wrrq : in std_logic; + cpu_mem_adr : in std_logic_vector(22 downto 0); + cpu_mem_dat_o : in std_logic_vector(63 downto 0); + cpu_mem_sel : in std_logic_vector(7 downto 0); + cpu_mem_ack : out std_logic; + cpu_mem_dat_i : out std_logic_vector(63 downto 0); - -- Port 1: RW, Prio 1 - WB bridge + -- Port 2: RW, Prio 2 - WB bridge (BL8) wb_mem_rdrq : in std_logic; wb_mem_wrrq : in std_logic; wb_mem_adr : in std_logic_vector(19 downto 0); @@ -74,27 +81,32 @@ end wb_ddr_ctrl_wb_sc; architecture Behavioral of wb_ddr_ctrl_wb_sc is -- Memory access controller configuration - constant num_ports : integer := 2; + constant num_ports : integer := 3; + constant max_burst_length : integer := 8; type port_mode_enum is (M_RO, M_WO, M_RW); type port_modes_arr is array(0 to num_ports-1) of port_mode_enum; - constant port_modes : port_modes_arr := (M_RO, M_RW); + type port_bl_arr is array(0 to num_ports-1) of integer range 1 to max_burst_length; + type port_modburst_arr is array(0 to num_ports-1) of boolean; + constant port_modes : port_modes_arr := (M_RO, M_RW, M_RW); + constant port_bl : port_bl_arr := (8, 4, 8); -- Only powers of 2 are valid. + constant port_modburst : port_modburst_arr := (false, true, false); -- Configuration-dependant types type p_slv8_arr is array(num_ports-1 downto 0) of std_logic_vector(7 downto 0); - type p_slv20_arr is array(num_ports-1 downto 0) of std_logic_vector(19 downto 0); + type p_slv23_arr is array(num_ports-1 downto 0) of std_logic_vector(22 downto 0); type p_slv64_arr is array(num_ports-1 downto 0) of std_logic_vector(63 downto 0); -- Configuration-dependant signals : Memory ports signal p_rdrq, p_wrrq : std_logic_vector(num_ports-1 downto 0); signal p_ack : std_logic_vector(num_ports-1 downto 0) := (others => '0'); - signal p_adr : p_slv20_arr; + signal p_adr : p_slv23_arr; signal p_dat_o, p_dat_i : p_slv64_arr; signal p_sel : p_slv8_arr; -- Internal signals signal rdrq_reg, wrrq_reg : std_logic_vector(num_ports-1 downto 0) := (others => '0'); - signal adr_reg : p_slv20_arr; + signal adr_reg : p_slv23_arr; signal rq_complete : std_logic_vector(num_ports-1 downto 0) := (others => '0'); signal dout_data_valid : std_logic := '0'; @@ -102,7 +114,7 @@ architecture Behavioral of wb_ddr_ctrl_wb_sc is constant BUS_IDLE : integer := num_ports; signal bus_owner, bus_owner_reg : integer range 0 to num_ports := BUS_IDLE; - signal out_ctr, in_ctr : integer range 0 to burst_length-1 := 0; + signal out_ctr, in_ctr : integer range 0 to max_burst_length-1 := 0; signal out_complete, in_complete : std_logic := '0'; signal in_read, in_write : std_logic := '0'; @@ -124,20 +136,31 @@ begin -- Port 0: RO, Prio 0 - VGA controller p_rdrq(0) <= vga_mem_rdrq; p_wrrq(0) <= '0'; - p_adr(0) <= vga_mem_adr; + p_adr(0)(22 downto 3) <= vga_mem_adr; + p_adr(0)(2 downto 0) <= (others => '0'); p_dat_o(0) <= (others => dontcare); p_sel(0) <= (others => dontcare); vga_mem_ack <= p_ack(0); vga_mem_dat_i <= p_dat_i(0); - -- Port 1: RW, Prio 1 - WB bridge - p_rdrq(1) <= wb_mem_rdrq; - p_wrrq(1) <= wb_mem_wrrq; - p_adr(1) <= wb_mem_adr; - p_dat_o(1) <= wb_mem_dat_o; - p_sel(1) <= wb_mem_sel; - wb_mem_ack <= p_ack(1); - wb_mem_dat_i <= p_dat_i(1); + -- Port 1: RW, Prio 1 - CPU + p_rdrq(1) <= cpu_mem_rdrq; + p_wrrq(1) <= cpu_mem_wrrq; + p_adr(1) <= cpu_mem_adr; + p_dat_o(1) <= cpu_mem_dat_o; + p_sel(1) <= cpu_mem_sel; + cpu_mem_ack <= p_ack(1); + cpu_mem_dat_i <= p_dat_i(1); + + -- Port 2: RW, Prio 2 - WB bridge + p_rdrq(2) <= wb_mem_rdrq; + p_wrrq(2) <= wb_mem_wrrq; + p_adr(2)(22 downto 3) <= wb_mem_adr; + p_adr(2)(2 downto 0) <= (others => '0'); + p_dat_o(2) <= wb_mem_dat_o; + p_sel(2) <= wb_mem_sel; + wb_mem_ack <= p_ack(2); + wb_mem_dat_i <= p_dat_i(2); -- Everything from here on is configured by the constant parameters. @@ -186,7 +209,6 @@ begin begin ddr_din <= (others => dontcare); ddr_be <= (others => '1'); -- ddr_be is low-active - ddr_adr(22 downto 3) <= (others => dontcare); ddr_we <= dontcare; fifo_to_ddr_write <= '0'; for i in 0 to num_ports-1 loop @@ -209,46 +231,36 @@ begin end if; if bus_owner = i then -- Signal always relevant - ddr_adr(22 downto 3) <= adr_reg(i); ddr_we <= wrrq_reg(i); end if; end loop; end process ddr_din_gen; - ddr_adr(2 downto 0) <= std_logic_vector(to_unsigned(out_ctr, 3)); - - --ddr_adr <= ddr_adr_int when in_read = '1' else - -- ddr_adr_dly(write_delay-1);-- when in_write = '1' else - -- --(others => dontcare); - --ddr_we <= ddr_we_int when in_read = '1' else - -- ddr_we_dly(write_delay-1);-- when in_write = '1' else - -- --dontcare; - --fifo_to_ddr_write <= fifo_to_ddr_write_int when in_read = '1' else - -- fifo_to_ddr_write_dly(write_delay-1) and not fifo_to_ddr_full when in_write = '1' else - -- '0'; - - --write_dly : process(clk_i) - --begin - -- if rising_edge(clk_i) then - -- if in_write = '1' then - -- if fifo_to_ddr_full = '0' then - -- if write_delay > 1 then - -- ddr_adr_dly(write_delay-1 downto 1) <= ddr_adr_dly(write_delay-2 downto 0); - -- ddr_we_dly(write_delay-1 downto 1) <= ddr_we_dly(write_delay-2 downto 0); - -- fifo_to_ddr_write_dly(write_delay-1 downto 1) <= fifo_to_ddr_write_dly(write_delay-2 downto 0); - -- out_complete_dly(write_delay-1 downto 1) <= out_complete_dly(write_delay-2 downto 0); - -- end if; - -- ddr_adr_dly(0) <= ddr_adr_int; - -- ddr_we_dly(0) <= ddr_we_int; - -- fifo_to_ddr_write_dly(0) <= fifo_to_ddr_write_int; - -- out_complete_dly(0) <= out_complete; - -- end if; - -- else - -- fifo_to_ddr_write_dly <= (others => '0'); - -- out_complete_dly <= (others => '0'); - -- end if; - -- end if; - --end process write_dly; + -- Address generation (depending on burst length and modburst flag of active + -- port) + ddr_adr_gen : process(bus_owner, out_ctr, adr_reg) + begin + ddr_adr <= (others => dontcare); + for i in 0 to num_ports-1 loop + if bus_owner = i then + if port_bl(i) = 8 then + ddr_adr(22 downto 3) <= adr_reg(i)(22 downto 3); + if port_modburst(i) then + ddr_adr(2 downto 0) <= std_logic_vector(to_unsigned(out_ctr, 3)+unsigned(adr_reg(i)(2 downto 0))); + else + ddr_adr(2 downto 0) <= std_logic_vector(to_unsigned(out_ctr, 3)); + end if; + else -- if port_bl(i) = 4 then + ddr_adr(22 downto 2) <= adr_reg(i)(22 downto 2); + if port_modburst(i) then + ddr_adr(1 downto 0) <= std_logic_vector(to_unsigned(out_ctr, 2)+unsigned(adr_reg(i)(1 downto 0))); + else + ddr_adr(1 downto 0) <= std_logic_vector(to_unsigned(out_ctr, 2)); + end if; + end if; + end if; + end loop; + end process ddr_adr_gen; -- Request registers rq_regs_gen : for i in 0 to num_ports-1 generate @@ -367,7 +379,7 @@ begin begin if rising_edge(clk_i) then if (bus_owner /= BUS_IDLE and out_complete = '0' and fifo_to_ddr_full = '0') then - if out_ctr = burst_length-1 then + if out_ctr = port_bl(bus_owner)-1 then out_complete <= '1'; else out_ctr <= out_ctr + 1; @@ -383,7 +395,7 @@ begin begin if rising_edge(clk_i) then if bus_owner /= BUS_IDLE and in_complete = '0' and fifo_from_ddr_empty = '0' then - if in_ctr = burst_length-1 then + if in_ctr = port_bl(bus_owner)-1 then in_complete <= '1'; else in_ctr <= in_ctr + 1; @@ -394,16 +406,5 @@ begin end if; end if; end process in_ctr_p; - - - --vga_rq_complete <= '1' when in_complete = '1' and out_complete = '1' and bus_owner_reg = B_VGA else - -- '0'; - --cfe_rq_complete <= '1' when (in_complete = '1' and out_complete = '1' and - -- cfe_rdrq_reg = '1' and bus_owner_reg = B_CFE) else - -- '1' when (out_complete_dly(write_delay-1) = '1' and fifo_to_ddr_full_last = '0' and - -- cfe_wrrq_reg = '1' and bus_owner_reg = B_CFE) else - -- '0'; - - end Behavioral; diff --git a/src/wb_ram.vhd b/src/wb_ram.vhd index 150ac2c..79c485e 100644 --- a/src/wb_ram.vhd +++ b/src/wb_ram.vhd @@ -103,7 +103,7 @@ begin ack_o_int <= wbs_i.stb_i and wbs_i.cyc_i; end if; end process ack; - wbs_o.ack_o <= (ack_o_int or wbs_i.we_i) and wbs_i.stb_i; - --wbs_o.ack_o <= ack_o_int; + --wbs_o.ack_o <= (ack_o_int or wbs_i.we_i) and wbs_i.stb_i; + wbs_o.ack_o <= ack_o_int; end Behavioral; diff --git a/src/wishbone.vhd b/src/wishbone.vhd index 256279f..c6e3bb9 100644 --- a/src/wishbone.vhd +++ b/src/wishbone.vhd @@ -6,7 +6,7 @@ -- Author : Matthias Blankertz -- Company : -- Created : 2013-06-03 --- Last update: 2013-06-07 +-- Last update: 2013-06-08 -- Platform : -- Standard : VHDL'93/02 ------------------------------------------------------------------------------- @@ -33,7 +33,7 @@ use IEEE.STD_LOGIC_1164.ALL; package intercon_package is - constant wb_addr_width : integer := 28; + constant wb_addr_width : integer := 27; type cpu_wbm_i_type is record dat_i : std_logic_vector(31 downto 0); @@ -228,7 +228,7 @@ begin pio_led_ss <= '1' when unsigned(buss_adr_o((wb_addr_width-1) downto 2) & "00") = 16#00010000# else '0'; uart_ss <= '1' when unsigned(buss_adr_o((wb_addr_width-1) downto 1) & "0") = 16#00010020# else '0'; spi_sd_ss <= '1' when unsigned(buss_adr_o((wb_addr_width-1) downto 2) & "00") = 16#00010030# else '0'; - mem_bridge_ss <= '1' when unsigned(buss_adr_o((wb_addr_width-1) downto 26) & "00" & x"000000") = 16#08000000# else '0'; + mem_bridge_ss <= '1' when unsigned(buss_adr_o((wb_addr_width-1) downto 26) & "00" & x"000000") = 16#04000000# else '0'; byte_sel <= to_integer(unsigned(buss_adr_o(1 downto 0))); hword_sel <= to_integer(unsigned(buss_adr_o(1 downto 1))); @@ -301,7 +301,7 @@ begin spi_sd_wbs_i.dat_i <= buss_dat_o(8*(3-byte_sel)+7 downto 8*(3-byte_sel)); spi_sd_wbs_i.adr_i <= buss_adr_o(1 downto 0); - -- mem_bridge (32bit, 0x08000000 - 0x0C000000) + -- mem_bridge (32bit, 0x04000000 - 0x08000000) mem_bridge_wbs_i.sel_i <= buss_sel_o; mem_bridge_wbs_i.adr_i <= buss_adr_o(25 downto 2); mem_bridge_wbs_i.cyc_i <= buss_cyc_o and mem_bridge_ss; diff --git a/tb/mblite_cache_tb.vhd b/tb/mblite_cache_tb.vhd new file mode 100644 index 0000000..4f90153 --- /dev/null +++ b/tb/mblite_cache_tb.vhd @@ -0,0 +1,201 @@ +------------------------------------------------------------------------------- +-- Title : Testbench for design "mblite_cache" +-- Project : +------------------------------------------------------------------------------- +-- File : mblite_cache_tb.vhd +-- Author : Matthias Blankertz +-- Company : +-- Created : 2013-06-08 +-- Last update: 2013-06-08 +-- Platform : +-- Standard : VHDL'93/02 +------------------------------------------------------------------------------- +-- Description: +------------------------------------------------------------------------------- +-- Copyright (c) 2013 +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2013-06-08 1.0 matthias Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.intercon_package.all; +------------------------------------------------------------------------------- + +entity mblite_cache_tb is + +end entity mblite_cache_tb; + +------------------------------------------------------------------------------- + +architecture testbench of mblite_cache_tb is + + -- component generics + constant dontcare : std_logic := '0'; + + -- component ports + signal clk_i : std_logic := '0'; + signal rst_i : std_logic := '1'; + signal cpui_dat_i : std_logic_vector(31 downto 0); + signal cpui_adr_o : std_logic_vector(25 downto 2); + signal cpui_ena_o : std_logic := '0'; + signal cpud_dat_i : std_logic_vector(31 downto 0); + signal cpud_dat_o : std_logic_vector(31 downto 0); + signal cpud_adr_o : std_logic_vector(25 downto 2); + signal cpud_sel_o : std_logic_vector(3 downto 0); + signal cpud_we_o : std_logic := '0'; + signal cpud_ena_o : std_logic := '0'; + signal cpu_wait : std_logic; + signal mem_rdrq : std_logic; + signal mem_wrrq : std_logic; + signal mem_adr : std_logic_vector(22 downto 0); + signal mem_dat_o : std_logic_vector(63 downto 0); + signal mem_sel : std_logic_vector(7 downto 0); + signal mem_ack : std_logic := '0'; + signal mem_dat_i : std_logic_vector(63 downto 0); + + type mem_arr is array(2047 downto 0) of std_logic_vector(63 downto 0); + signal mem : mem_arr; + +begin -- architecture testbench + + -- component instantiation + DUT: entity work.mblite_cache + generic map ( + dontcare => dontcare) + port map ( + clk_i => clk_i, + rst_i => rst_i, + cpui_dat_i => cpui_dat_i, + cpui_adr_o => cpui_adr_o, + cpui_ena_o => cpui_ena_o, + cpud_dat_i => cpud_dat_i, + cpud_dat_o => cpud_dat_o, + cpud_adr_o => cpud_adr_o, + cpud_sel_o => cpud_sel_o, + cpud_we_o => cpud_we_o, + cpud_ena_o => cpud_ena_o, + cpu_wait => cpu_wait, + mem_rdrq => mem_rdrq, + mem_wrrq => mem_wrrq, + mem_adr => mem_adr, + mem_dat_o => mem_dat_o, + mem_sel => mem_sel, + mem_ack => mem_ack, + mem_dat_i => mem_dat_i); + + -- clock generation + clk_i <= not clk_i after 10 ns; + + mem_gen : process + variable base_adr, adr : unsigned(22 downto 0); + begin + for i in 0 to 2047 loop + mem(i)(63 downto 32) <= std_logic_vector(to_unsigned(i*2+1,32)); + mem(i)(31 downto 0) <= std_logic_vector(to_unsigned(i*2,32)); + end loop; + + wait until rst_i = '0'; + wait until rising_edge(clk_i); + + while True loop + if mem_rdrq = '1' then + base_adr := unsigned(mem_adr); + wait until rising_edge(clk_i); + for i in 0 to 3 loop + adr(22 downto 2) := base_adr(22 downto 2); + adr(1 downto 0) := base_adr(1 downto 0) + to_unsigned(i, 2); + mem_dat_i <= mem(to_integer(adr)); + mem_ack <= '1'; + wait until rising_edge(clk_i); + end loop; + mem_ack <= '0'; + elsif mem_wrrq = '1' then + null; + end if; + wait until rising_edge(clk_i); + end loop; + end process mem_gen; + + cpu_gen : process + variable adr : unsigned(23 downto 0) := to_unsigned(0, 24); + begin + wait for 100 ns; + rst_i <= '0'; + wait until rising_edge(clk_i); + + cpui_adr_o <= std_logic_vector(adr); + cpui_ena_o <= '1'; + while adr < 16 loop + wait until rising_edge(clk_i); + if cpu_wait = '0' then + adr := adr + 1; + end if; + cpui_adr_o <= std_logic_vector(adr); + cpui_ena_o <= '1'; + --wait until rising_edge(clk_i); + end loop; + cpui_ena_o <= '0'; + while cpu_wait = '1' loop + wait until rising_edge(clk_i); + end loop; + + adr := to_unsigned(64, 24); + cpud_adr_o <= std_logic_vector(adr); + cpud_ena_o <= '1'; + while adr < 80 loop + wait until rising_edge(clk_i); + if cpu_wait = '0' then + adr := adr + 1; + end if; + cpud_adr_o <= std_logic_vector(adr); + cpud_ena_o <= '1'; + --wait until rising_edge(clk_i); + end loop; + cpud_ena_o <= '0'; + while cpu_wait = '1' loop + wait until rising_edge(clk_i); + end loop; + wait until rising_edge(clk_i); + + cpud_we_o <= '1'; + cpud_adr_o <= x"000000"; + cpud_dat_o <= x"deadbeef"; + cpud_sel_o <= "1111"; + cpud_ena_o <= '1'; + wait until rising_edge(clk_i); + cpud_ena_o <= '0'; + while cpu_wait = '1' loop + wait until rising_edge(clk_i); + end loop; + wait until rising_edge(clk_i); + + cpud_we_o <= '1'; + cpud_adr_o <= x"000080"; + cpud_dat_o <= x"deadbef2"; + cpud_ena_o <= '1'; + wait until rising_edge(clk_i); + cpud_ena_o <= '0'; + while cpu_wait = '1' loop + wait until rising_edge(clk_i); + end loop; + + wait; + end process cpu_gen; + + + +end architecture testbench; + +------------------------------------------------------------------------------- + +configuration mblite_cache_tb_testbench_cfg of mblite_cache_tb is + for testbench + end for; +end mblite_cache_tb_testbench_cfg; + +------------------------------------------------------------------------------- diff --git a/tb/wb_ddr_ctrl_wb_sc_tb.vhd b/tb/wb_ddr_ctrl_wb_sc_tb.vhd index 8c57560..fbd2417 100644 --- a/tb/wb_ddr_ctrl_wb_sc_tb.vhd +++ b/tb/wb_ddr_ctrl_wb_sc_tb.vhd @@ -6,7 +6,7 @@ -- Author : -- Company : -- Created : 2013-03-08 --- Last update: 2013-06-04 +-- Last update: 2013-06-08 -- Platform : -- Standard : VHDL'87 ------------------------------------------------------------------------------- @@ -37,8 +37,6 @@ end wb_ddr_ctrl_wb_sc_tb; architecture testbench of wb_ddr_ctrl_wb_sc_tb is -- component generics - constant burst_length : integer := 8; - constant burst_length_ln2 : integer := 3; constant dontcare : std_logic := '0'; -- component ports @@ -55,6 +53,13 @@ architecture testbench of wb_ddr_ctrl_wb_sc_tb is signal wb_mem_sel : std_logic_vector(7 downto 0); signal wb_mem_ack : std_logic; signal wb_mem_dat_i : std_logic_vector(63 downto 0); + signal cpu_mem_rdrq : std_logic := '0'; + signal cpu_mem_wrrq : std_logic := '0'; + signal cpu_mem_adr : std_logic_vector(22 downto 0); + signal cpu_mem_dat_o : std_logic_vector(63 downto 0); + signal cpu_mem_sel : std_logic_vector(7 downto 0); + signal cpu_mem_ack : std_logic; + signal cpu_mem_dat_i : std_logic_vector(63 downto 0); signal ddr_din : std_logic_vector(63 downto 0); signal ddr_dout : std_logic_vector(63 downto 0); signal ddr_adr : std_logic_vector(22 downto 0); @@ -76,14 +81,14 @@ architecture testbench of wb_ddr_ctrl_wb_sc_tb is type wrptr_dly_a is array(maxdelay downto 0) of integer range 0 to 127; signal wrptr_dly : wrptr_dly_a := (others => 0); + + constant burst_length : integer := 8; begin -- testbench -- component instantiation DUT: entity work.wb_ddr_ctrl_wb_sc generic map ( - burst_length => burst_length, - burst_length_ln2 => burst_length_ln2, dontcare => dontcare) port map ( clk_i => clk_i, @@ -99,6 +104,13 @@ begin -- testbench wb_mem_sel => wb_mem_sel, wb_mem_ack => wb_mem_ack, wb_mem_dat_i => wb_mem_dat_i, + cpu_mem_rdrq => cpu_mem_rdrq, + cpu_mem_wrrq => cpu_mem_wrrq, + cpu_mem_adr => cpu_mem_adr, + cpu_mem_dat_o => cpu_mem_dat_o, + cpu_mem_sel => cpu_mem_sel, + cpu_mem_ack => cpu_mem_ack, + cpu_mem_dat_i => cpu_mem_dat_i, ddr_din => ddr_din, ddr_dout => ddr_dout, ddr_adr => ddr_adr, @@ -220,6 +232,44 @@ begin -- testbench wait until rising_edge(clk_i); wb_mem_wrrq <= '0'; end loop; + + -- Test cpu read port + + cpu_mem_rdrq <= '1'; + cpu_mem_adr <= x"00010" & "001"; + wait until rising_edge(clk_i); + cpu_mem_rdrq <= '0'; + + ctr := 0; + while ctr < 4 loop + if cpu_mem_ack = '1' then + expected_data := (others => '0'); + expected_data(22 downto 2) := x"00010" & "0"; + expected_data(1 downto 0) := std_logic_vector(to_unsigned(ctr, 2)+1); + assert cpu_mem_dat_i = expected_data report "Incorrect read data (CPU)" severity failure; + ctr := ctr + 1; + end if; + + wait until rising_edge(clk_i); + end loop; + + -- Test cpu write port + cpu_mem_wrrq <= '1'; + cpu_mem_adr <= x"10010" & "111" ; + cpu_mem_dat_o <= x"de00ad00be00ef00"; + --wait until rising_edge(clk_i); + + + ctr := 0; + while ctr < 4 loop + if cpu_mem_ack = '1' then + ctr := ctr + 1; + cpu_mem_dat_o(7 downto 0) <= std_logic_vector(to_unsigned(ctr, 8)); + end if; + + wait until rising_edge(clk_i); + cpu_mem_wrrq <= '0'; + end loop; sim_done <= true; wait; diff --git a/toplevel_tb.wcfg b/toplevel_tb.wcfg index 83c1532..2fc5577 100644 --- a/toplevel_tb.wcfg +++ b/toplevel_tb.wcfg @@ -396,531 +396,135 @@ HEXRADIX - - mb_wb_o - mb_wb_o - - .adr_o - mb_wb_o.adr_o - HEXRADIX - - + + mb_dmem_o + mb_dmem_o + .dat_o - mb_wb_o.dat_o + mb_dmem_o.dat_o HEXRADIX - - .we_o - mb_wb_o.we_o + + .adr_o + mb_dmem_o.adr_o + HEXRADIX - - .stb_o - mb_wb_o.stb_o - - + .sel_o - mb_wb_o.sel_o + mb_dmem_o.sel_o - - .cyc_o - mb_wb_o.cyc_o + + .we_o + mb_dmem_o.we_o + + + .ena_o + mb_dmem_o.ena_o - - mb_wb_i - mb_wb_i - - .clk_i - mb_wb_i.clk_i - - - .rst_i - mb_wb_i.rst_i - - + + mb_dmem_i + mb_dmem_i + .dat_i - mb_wb_i.dat_i + mb_dmem_i.dat_i HEXRADIX - + + .ena_i + mb_dmem_i.ena_i + + + + + wbm + label + + cpu_dat_i[31:0] + cpu_dat_i[31:0] + HEXRADIX + + + cpu_dat_o[31:0] + cpu_dat_o[31:0] + HEXRADIX + + + cpu_adr_o[26:0] + cpu_adr_o[26:0] + HEXRADIX + + + cpu_sel_o[3:0] + cpu_sel_o[3:0] + + + cpu_we_o + cpu_we_o + + + cpu_ena_o + cpu_ena_o + + + cpu_wait + cpu_wait + + + wbm_i + wbm_i + + .dat_i + wbm_i.dat_i + HEXRADIX + + .ack_i - mb_wb_i.ack_i + wbm_i.ack_i - - .int_i - mb_wb_i.int_i + + + wbm_o + wbm_o + + .dat_o + wbm_o.dat_o + HEXRADIX + + .we_o + wbm_o.we_o + + + .sel_o + wbm_o.sel_o + + + .adr_o + wbm_o.adr_o + HEXRADIX + + + .cyc_o + wbm_o.cyc_o + + + .stb_o + wbm_o.stb_o + + + + wb_in_cyc + wb_in_cyc + + + queued + queued cpu label - - dmem_o - dmem_o - - .dat_o - dmem_o.dat_o - HEXRADIX - - - .adr_o - dmem_o.adr_o - HEXRADIX - - - .sel_o - dmem_o.sel_o - - - .we_o - dmem_o.we_o - - - .ena_o - dmem_o.ena_o - - - - dmem_i - dmem_i - - .dat_i - dmem_i.dat_i - HEXRADIX - - - .ena_i - dmem_i.ena_i - - - - fetch_i - fetch_i - - .hazard - fetch_i.hazard - - - .branch - fetch_i.branch - - - .branch_target - fetch_i.branch_target - HEXRADIX - - - - fetch_o - fetch_o - HEXRADIX - - .program_counter - fetch_o.program_counter - HEXRADIX - - - - decode_i - decode_i - - .program_counter - decode_i.program_counter - HEXRADIX - - - .instruction - decode_i.instruction - HEXRADIX - - - .ctrl_wrb - decode_i.ctrl_wrb - - .reg_d - decode_i.ctrl_wrb.reg_d - UNSIGNEDDECRADIX - - - .reg_write - decode_i.ctrl_wrb.reg_write - - - - .ctrl_mem_wrb - decode_i.ctrl_mem_wrb - - - .mem_result - decode_i.mem_result - HEXRADIX - - - .alu_result - decode_i.alu_result - HEXRADIX - - - .interrupt - decode_i.interrupt - - - .flush_id - decode_i.flush_id - - - - decode_o - decode_o - - - gprf_o - gprf_o - - - exec_i - exec_i - - - exec_o - exec_o - - .alu_result - exec_o.alu_result - HEXRADIX - - - .dat_d - exec_o.dat_d - - - .branch - exec_o.branch - - - .program_counter - exec_o.program_counter - - - .flush_id - exec_o.flush_id - - - .ctrl_mem - exec_o.ctrl_mem - - - .ctrl_wrb - exec_o.ctrl_wrb - - - - mem_i - mem_i - - .dat_d - mem_i.dat_d - HEXRADIX - - - .alu_result - mem_i.alu_result - HEXRADIX - - - .mem_result - mem_i.mem_result - HEXRADIX - - - .program_counter - mem_i.program_counter - - - .branch - mem_i.branch - - - .ctrl_mem - mem_i.ctrl_mem - - - .ctrl_wrb - mem_i.ctrl_wrb - - .reg_d - mem_i.ctrl_wrb.reg_d - UNSIGNEDDECRADIX - - - .reg_write - mem_i.ctrl_wrb.reg_write - - - - - mem_o - mem_o - - .alu_result - mem_o.alu_result - HEXRADIX - - - .ctrl_wrb - mem_o.ctrl_wrb - - .reg_d - mem_o.ctrl_wrb.reg_d - UNSIGNEDDECRADIX - - - .reg_write - mem_o.ctrl_wrb.reg_write - - - - .ctrl_mem_wrb - mem_o.ctrl_mem_wrb - - - - ena_i - ena_i - - - r - r - - - rin - rin - - - r - r - - - rin - rin - - - reg - reg - - - regin - regin - - - wb_dat_d[31:0] - wb_dat_d[31:0] - - - r - r - - - rin - rin - - - reg - reg - - - regin - regin - - - r - r - - - rin - rin - - - mem_result[31:0] - mem_result[31:0] - HEXRADIX - - - ram[31:0] - ram[31:0] - HEXRADIX - - [31] - ram[31] - HEXRADIX - - - [30] - ram[30] - HEXRADIX - - - [29] - ram[29] - HEXRADIX - - - [28] - ram[28] - HEXRADIX - - - [27] - ram[27] - HEXRADIX - - - [26] - ram[26] - HEXRADIX - - - [25] - ram[25] - HEXRADIX - - - [24] - ram[24] - HEXRADIX - - - [23] - ram[23] - HEXRADIX - - - [22] - ram[22] - HEXRADIX - - - [21] - ram[21] - HEXRADIX - - - [20] - ram[20] - HEXRADIX - - - [19] - ram[19] - HEXRADIX - - - [18] - ram[18] - HEXRADIX - - - [17] - ram[17] - HEXRADIX - - - [16] - ram[16] - HEXRADIX - - - [15] - ram[15] - HEXRADIX - - - [14] - ram[14] - HEXRADIX - - - [13] - ram[13] - HEXRADIX - - - [12] - ram[12] - HEXRADIX - - - [11] - ram[11] - HEXRADIX - - - [10] - ram[10] - HEXRADIX - - - [9] - ram[9] - HEXRADIX - - - [8] - ram[8] - HEXRADIX - - - [7] - ram[7] - HEXRADIX - - - [6] - ram[6] - HEXRADIX - - - [5] - ram[5] - HEXRADIX - - - [4] - ram[4] - HEXRADIX - - - [3] - ram[3] - HEXRADIX - - - [2] - ram[2] - HEXRADIX - - - [1] - ram[1] - HEXRADIX - - - [0] - ram[0] - HEXRADIX - - - - ram[31:0] - ram[31:0] - HEXRADIX - - - ram[31:0] - ram[31:0] - HEXRADIX - diff --git a/wb_ddr_ctrl_wb_sc_tb.wcfg b/wb_ddr_ctrl_wb_sc_tb.wcfg index 4494e97..ab9d4cb 100644 --- a/wb_ddr_ctrl_wb_sc_tb.wcfg +++ b/wb_ddr_ctrl_wb_sc_tb.wcfg @@ -13,7 +13,7 @@ - + sim_done sim_done @@ -99,6 +99,37 @@ wb_mem_dat_i[63:0] HEXRADIX + + cpu_mem_rdrq + cpu_mem_rdrq + + + cpu_mem_wrrq + cpu_mem_wrrq + + + cpu_mem_adr[22:0] + cpu_mem_adr[22:0] + HEXRADIX + + + cpu_mem_dat_o[63:0] + cpu_mem_dat_o[63:0] + HEXRADIX + + + cpu_mem_sel[7:0] + cpu_mem_sel[7:0] + + + cpu_mem_ack + cpu_mem_ack + + + cpu_mem_dat_i[63:0] + cpu_mem_dat_i[63:0] + HEXRADIX + ddr_din[63:0] ddr_din[63:0] @@ -139,52 +170,52 @@ fifo_from_ddr_empty - p_rdrq[1:0] - p_rdrq[1:0] + p_rdrq[2:0] + p_rdrq[2:0] - p_wrrq[1:0] - p_wrrq[1:0] + p_wrrq[2:0] + p_wrrq[2:0] - p_ack[1:0] - p_ack[1:0] + p_ack[2:0] + p_ack[2:0] - p_adr[1:0] - p_adr[1:0] + p_adr[2:0] + p_adr[2:0] HEXRADIX - p_dat_o[1:0] - p_dat_o[1:0] + p_dat_o[2:0] + p_dat_o[2:0] HEXRADIX - p_dat_i[1:0] - p_dat_i[1:0] + p_dat_i[2:0] + p_dat_i[2:0] HEXRADIX - p_sel[1:0] - p_sel[1:0] + p_sel[2:0] + p_sel[2:0] - rdrq_reg[1:0] - rdrq_reg[1:0] + rdrq_reg[2:0] + rdrq_reg[2:0] - wrrq_reg[1:0] - wrrq_reg[1:0] + wrrq_reg[2:0] + wrrq_reg[2:0] - adr_reg[1:0] - adr_reg[1:0] + adr_reg[2:0] + adr_reg[2:0] HEXRADIX - rq_complete[1:0] - rq_complete[1:0] + rq_complete[2:0] + rq_complete[2:0] dout_data_valid