Base Design Import Base design passed from internal simulation. Now to see how the tools handle things!
diff --git a/LICENSE b/LICENSE index 261eeb9..d0a4662 100644 --- a/LICENSE +++ b/LICENSE
@@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [Ryan M Price] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
diff --git a/Makefile b/Makefile index b8cb5c7..a343216 100644 --- a/Makefile +++ b/Makefile
@@ -24,8 +24,8 @@ CARAVEL_LITE?=1 # PDK switch varient -export PDK?=sky130B -#export PDK?=gf180mcuC +#export PDK?=sky130B +export PDK?=gf180mcuC export PDKPATH?=$(PDK_ROOT)/$(PDK)
diff --git a/README.md b/README.md index 34b9a05..2aa0193 100644 --- a/README.md +++ b/README.md
@@ -5,8 +5,17 @@ | :exclamation: Important Note | |-----------------------------------------| -## Please fill in your project documentation in this README.md file - Refer to [README](docs/source/index.rst#section-quickstart) for a quickstart of how to use caravel_user_project - Refer to [README](docs/source/index.rst) for this sample project documentation. + +| :exclamation: Important MAKE! | +|-----------------------------------------| + +This design uses design rules for the gf180mcuC PDK. + +This project implements a 16 bit RISC themed processor for educational purposes. + +Since the number of IO pins are limited the Address/Databus are merged into a single external bus. + +More documentation to come in the following days! +
diff --git a/openlane/user_Minx16/config.json b/openlane/user_Minx16/config.json new file mode 100644 index 0000000..055b66d --- /dev/null +++ b/openlane/user_Minx16/config.json
@@ -0,0 +1,49 @@ +{ + "DESIGN_NAME": "Minx16Top", + "DESIGN_IS_CORE": 0, + "VERILOG_FILES": ["dir::../../verilog/rtl/defines.v", "dir::../../verilog/rtl/Minx16/*"], + "MACRO_PLACEMENT_CFG": "dir::macro.cfg", + "VERILOG_FILES_BLACKBOX": ["dir::../../verilog/rtl/gf180mcu_fd_ip_sram/gf180mcu_fd_ip_sram__sram512x8m8wm1.v"], + "EXTRA_LEFS": "dir::../../lef/gf180mcu_fd_ip_sram__sram512x8m8wm1.lef", + "EXTRA_GDS_FILES": "dir::../../gds/gf180mcu_fd_ip_sram__sram512x8m8wm1.gds", + "CLOCK_PERIOD": 100, + "CLOCK_PORT": "clk_i", + "CLOCK_NET": "Minx16Top.clk_i", + "FP_SIZING": "absolute", + "DIE_AREA": "0 0 2000 2000", + "FP_PIN_ORDER_CFG": "dir::pin_order.cfg", + "PL_BASIC_PLACEMENT": 0, + "PL_TARGET_DENSITY": 0.50, + "VDD_NETS": ["vccd1"], + "GND_NETS": ["vssd1"], + "DIODE_INSERTION_STRATEGY": 4, + "RUN_CVC": 1, + "pdk::sky130*": { + "FP_CORE_UTIL": 45, + "RT_MAX_LAYER": "met4", + "scl::sky130_fd_sc_hd": { + "CLOCK_PERIOD": 10 + }, + "scl::sky130_fd_sc_hdll": { + "CLOCK_PERIOD": 10 + }, + "scl::sky130_fd_sc_hs": { + "CLOCK_PERIOD": 8 + }, + "scl::sky130_fd_sc_ls": { + "CLOCK_PERIOD": 10, + "SYNTH_MAX_FANOUT": 5 + }, + "scl::sky130_fd_sc_ms": { + "CLOCK_PERIOD": 10 + } + }, + "pdk::gf180mcuC": { + "STD_CELL_LIBRARY": "gf180mcu_fd_sc_mcu7t5v0", + "CLOCK_PERIOD": 50.0, + "FP_CORE_UTIL": 40, + "RT_MAX_LAYER": "Metal4", + "SYNTH_MAX_FANOUT": 4, + "PL_TARGET_DENSITY": 0.45 + } +} \ No newline at end of file
diff --git a/openlane/user_Minx16/macro.cfg b/openlane/user_Minx16/macro.cfg new file mode 100644 index 0000000..d1567a8 --- /dev/null +++ b/openlane/user_Minx16/macro.cfg
@@ -0,0 +1,4 @@ +oddMemHigh 250.0000 250.00 N +oddMemLow 250.0000 1000.00 N +evenMemHigh 1000.0000 250.00 N +evenMemLow 1000.0000 1000.00 N
diff --git a/openlane/user_Minx16/pin_order.cfg b/openlane/user_Minx16/pin_order.cfg new file mode 100644 index 0000000..603257a --- /dev/null +++ b/openlane/user_Minx16/pin_order.cfg
@@ -0,0 +1,76 @@ +#BUS_SORT + +#N +dbus_ADBus_i\[7\] +dbus_ADBus_o\[7\] +dbus_ADBus_e\[7\] +dbus_ADBus_i\[6\] +dbus_ADBus_o\[6\] +dbus_ADBus_e\[6\] +dbus_ADBus_i\[5\] +dbus_ADBus_o\[5\] +dbus_ADBus_e\[5\] +dbus_ADBus_i\[4\] +dbus_ADBus_o\[4\] +dbus_ADBus_e\[4\] +dbus_ADBus_i\[3\] +dbus_ADBus_o\[3\] +dbus_ADBus_e\[3\] +dbus_ADBus_i\[2\] +dbus_ADBus_o\[2\] +dbus_ADBus_e\[2\] +dbus_ADBus_i\[1\] +dbus_ADBus_o\[1\] +dbus_ADBus_e\[1\] +dbus_ADBus_i\[0\] +dbus_ADBus_o\[0\] +dbus_ADBus_e\[0\] +dbus_ale_o +dbus_ale_e + +#W +dbus_dle_o +dbus_dle_e +dbus_stb_o\[1\] +dbus_stb_e\[1\] +dbus_stb_o\[0\] +dbus_stb_e\[0\] +dbus_rd_o +dbus_rd_e +dbus_wr_o +dbus_wr_e +dbus_rdy_i +dbus_req_i +dbus_ack_o +intr_i +inta_o + +#E +dbus_ADBus_i\[8\] +dbus_ADBus_o\[8\] +dbus_ADBus_e\[8\] +dbus_ADBus_i\[9\] +dbus_ADBus_o\[9\] +dbus_ADBus_e\[9\] +dbus_ADBus_i\[10\] +dbus_ADBus_o\[10\] +dbus_ADBus_e\[10\] +dbus_ADBus_i\[11\] +dbus_ADBus_o\[11\] +dbus_ADBus_e\[11\] +dbus_ADBus_i\[12\] +dbus_ADBus_o\[12\] +dbus_ADBus_e\[12\] +dbus_ADBus_i\[13\] +dbus_ADBus_o\[13\] +dbus_ADBus_e\[13\] +dbus_ADBus_i\[14\] +dbus_ADBus_o\[14\] +dbus_ADBus_e\[14\] +dbus_ADBus_i\[15\] +dbus_ADBus_o\[15\] +dbus_ADBus_e\[15\] +rst_i +clk_i +nmir_i +nmia_o
diff --git a/verilog/rtl/Minx16/Alu.v b/verilog/rtl/Minx16/Alu.v new file mode 100644 index 0000000..07455e9 --- /dev/null +++ b/verilog/rtl/Minx16/Alu.v
@@ -0,0 +1,54 @@ + +module Alu ( + input [ 3:0] op +, input [15:0] dba +, input [15:0] dbb +, input ci +, input op8 + +, output reg [15:0] Y + +, output wire Co +, output wire Zo +, output wire Vo +, output wire No +); + + reg C; + assign C8 = (( dba[7] & dbb[7]) & Y[7] ) | + (( dba[7] ^ dbb[7]) & ~Y[7] ) | + ((~dba[7] & ~dbb[7]) & Y[7] ) ; + assign C16 = C; + assign Z16 = Y == 0; + assign Z8 = Y[7:0] == 0; + assign N16 = Y[15]; + assign N8 = Y[7]; + assign V16 = (~Y[15]&dba[15]&dbb[15]) | (Y[15]&(~dba[15])&(~dbb[15])); + assign V8 = (~Y[7] &dba[7] &dbb[7]) | (Y[7] &(~dba[7]) &(~dbb[7])); + + assign Co = (op8) ? C8 : C16; + assign Zo = (op8) ? Z8 : Z16; + assign No = (op8) ? N8 : N16; + assign Vo = (op8) ? V8 : V16; + + always @* + case(op) + 4'b0000 : {C, Y} = {1'b0, 16'd0}; + 4'b0001 : {C, Y} = {1'b0, dba}; + 4'b0010 : {C, Y} = dba + 1'b1; + 4'b0011 : {C, Y} = dba - 1'b1; + 4'b0100 : {C, Y} = dba + dbb + 1'b0; + 4'b0101 : {C, Y} = dba + dbb + ci; + 4'b0110 : {C, Y} = dba - dbb - 1'b0; + 4'b0111 : {C, Y} = dba - dbb - ci; + 4'b1000 : {C, Y} = {1'b0, ~dba}; + 4'b1001 : {C, Y} = {1'b0, dba & dbb}; + 4'b1010 : {C, Y} = {1'b0, dba | dbb}; + 4'b1011 : {C, Y} = {1'b0, dba ^ dbb}; + 4'b1100 : {C, Y} = {dba, 1'b0}; + 4'b1101 : {C, Y} = {dba[0], 1'b0, dba[15:1]}; + 4'b1110 : {C, Y} = {dba, ci}; + 4'b1111 : {C, Y} = {dba[0], ci, dba[15:1]}; + endcase + +endmodule
diff --git a/verilog/rtl/Minx16/Biu16.v b/verilog/rtl/Minx16/Biu16.v new file mode 100644 index 0000000..360130f --- /dev/null +++ b/verilog/rtl/Minx16/Biu16.v
@@ -0,0 +1,249 @@ + +module Biu1616 ( + input clk +, input rst + +, input [A-1:0] core_Addr_i +, input [D-1:0] core_Data_i +, output reg [D-1:0] core_Data_o +, input core_rd16 +, input core_rd8 +, input [ 1:0] core_wr +, output reg core_rdy +, output reg core_done + +, output reg [A-1:0] bus_Addr_o +, output reg [A-1:0] bus_Addr_e +, input [D-1:0] bus_Data_i +, output reg [D-1:0] bus_Data_o +, output reg [D-1:0] bus_Data_e +, output reg [B-1:0] bus_stb_o +, output reg [B-1:0] bus_stb_e +, output reg bus_rd_o +, output reg bus_rd_e +, output reg bus_wr_o +, output reg bus_wr_e +, input bus_rdy_i + +, input bus_req_i +, output reg bus_ack_o +); + + localparam A = 16; + localparam ADRENABLE = {A{1'b1}}; + localparam ADRDISABLE = {A{1'b0}}; + + localparam D = 16; + localparam B = D / 8; + localparam BUSENABLE = {D{1'b0}}; + localparam BUSDISABLE = {D{1'b1}}; + localparam STBENABLE = {B{1'b0}}; + localparam STBDISABLE = {B{1'b1}}; + localparam STBACTIVE = 1'b1; + localparam STBINACTIVE = 1'b0; + + localparam RDACTIVE = 1'b0; + localparam RDINACTIVE = 1'b1; + localparam RDENABLE = 1'b0; + localparam RDDISABLE = 1'b1; + + localparam WRACTIVE = 1'b0; + localparam WRINACTIVE = 1'b1; + localparam WRENABLE = 1'b0; + localparam WRDISABLE = 1'b1; + + localparam STATE_RESET = 3'b000; // + localparam STATE_IDLE = 3'b001; // + localparam STATE_16A = 3'b010; // + localparam STATE_16B = 3'b011; // + localparam STATE_16C = 3'b100; // + localparam STATE_16D = 3'b101; // + localparam STATE_BUSR = 3'b110; // Bus access was requested given + + wire core_wr16 = core_wr[0] & core_wr[1]; + wire core_wr8 = core_wr[0] ^ core_wr[1]; + + wire core_wrs = (core_wr[0] | core_wr[1]); + wire core_rds = (core_rd16 | core_rd8 ); + wire core16 = (core_rd16 | core_wr16 ); + wire core8 = (core_rd8 | core_wr8 ); + wire unaligned = core_Addr_i[0] & core16; + + reg [A-1:0] tAddr; + + reg [2:0] pstate, nstate; + + always @ (posedge clk or negedge rst) + if( rst == 1'b0 ) + pstate = STATE_RESET; + else + pstate = nstate; + + always @* + begin + bus_Data_o = bus_Data_o; + bus_Data_e = bus_Data_e; + bus_Addr_o = bus_Addr_o; + bus_Addr_e = ADRENABLE; + bus_ack_o = 1'b0; + bus_rd_o = RDINACTIVE; + bus_rd_e = RDENABLE; + bus_wr_o = WRINACTIVE; + bus_wr_e = WRENABLE; + core_rdy = 1'b0; + core_done = 1'b0; + case(pstate) + STATE_RESET : begin + tAddr = 16'h0000; + bus_Addr_o = 16'h0000; + bus_Data_o = 16'h0000; + bus_Data_e = BUSDISABLE; + core_Data_o = 16'h0000; + bus_stb_o = {B{STBINACTIVE}}; + bus_stb_e = STBENABLE; + nstate = STATE_IDLE; + end + STATE_IDLE : begin + tAddr = 16'h0000; + bus_Addr_o = 16'h0000; + bus_Data_o = 16'h0000; + bus_Data_e = BUSDISABLE; + core_Data_o = 16'h0000; + core_rdy = 1'b1; + bus_stb_o = {B{STBINACTIVE}}; + bus_stb_e = STBENABLE; + if( bus_req_i == 1'b1 ) + nstate = STATE_BUSR; + else if( core16 | core8 ) + begin + if( core_wr16 == 1'b1 & core_wr8 == 1'b0 & core_Addr_i[0] == 1'b0 ) + begin + tAddr = {core_Addr_i[A-1:1], 1'b0}; + bus_Data_o = (core_wrs) ? core_Data_i : 16'h0000; + bus_Data_e = BUSENABLE; + nstate = STATE_16A; + end + else if( core_wr16 == 1'b1 & core_wr8 == 1'b0 & core_Addr_i[0] == 1'b1) + begin + tAddr = core_Addr_i; + bus_Data_o = (core_wrs) ? {core_Data_i[7:0], core_Data_i[7:0]} : 16'h0000; + bus_Data_e = BUSENABLE; + nstate = STATE_16A; + end + else if( core_wr16 == 1'b0 & core_wr[1] == 1'b0 & core_wr[0] == 1'b1 ) + begin + tAddr = core_Addr_i; + bus_Data_o = (core_wrs) ? {core_Data_i[7:0], core_Data_i[7:0]} : 16'h0000; + bus_Data_e = BUSENABLE; + nstate = STATE_16A; + end + else if( core_wr16 == 1'b0 & core_wr[1] == 1'b1 & core_wr[0] == 1'b0 ) + begin + tAddr = core_Addr_i; + bus_Data_o = (core_wrs) ? {core_Data_i[15:8], core_Data_i[15:8]} : 16'h0000; + bus_Data_e = BUSENABLE; + nstate = STATE_16A; + end + else + begin + tAddr = core_Addr_i; + bus_Data_o = 0; + bus_Data_e = BUSENABLE; + nstate = STATE_16A; + end + end + else + nstate = STATE_IDLE; + end + STATE_16A : begin + if( core16 & core_Addr_i[0] == 1'b0) + bus_stb_o = {B{STBACTIVE}}; + else + bus_stb_o = { ( tAddr[0]) ? STBACTIVE : STBINACTIVE, + (~tAddr[0]) ? STBACTIVE : STBINACTIVE}; + bus_stb_e = STBENABLE; + bus_Addr_o = tAddr; + bus_rd_o = (core_rds) ? RDACTIVE : RDINACTIVE; + bus_wr_o = (core_wrs) ? WRACTIVE : WRINACTIVE; + nstate = STATE_16B; + end + STATE_16B : begin + if( core_rd16 == 1'b1 & core_Addr_i[0] == 1'b0 ) + core_Data_o = bus_Data_i; + else if( bus_stb_o[1] ) + core_Data_o = bus_Data_i[15:8]; + else + core_Data_o = bus_Data_i[7:0]; + bus_stb_o = bus_stb_o; + bus_stb_e = STBENABLE; + bus_rd_o = (core_rds) ? RDACTIVE : RDINACTIVE; + bus_wr_o = (core_wrs) ? WRACTIVE : WRINACTIVE; + if( bus_rdy_i == 1'b1 & unaligned == 1'b1 ) + begin + tAddr = tAddr + 1; + nstate = STATE_16C; + core_done = 1'b0; + end + else if( bus_rdy_i == 1'b1 & unaligned == 1'b0 ) + begin + nstate = STATE_IDLE; + core_done = 1'b1; + end + else + begin + nstate = STATE_16B; + core_done = 1'b0; + end + end + STATE_16C : begin + if( core_wrs ) + begin + bus_Data_o = {8'h00, core_Data_i[15:8]}; + bus_Data_e = BUSENABLE; + end + else + begin + bus_Data_o = 0; + bus_Data_e = BUSDISABLE; + end + bus_Addr_o = tAddr; + bus_stb_o = {STBINACTIVE, STBACTIVE}; + bus_stb_e = STBENABLE; + bus_rd_o = (core_rds) ? RDACTIVE : RDINACTIVE; + bus_wr_o = (core_wrs) ? WRACTIVE : WRINACTIVE; + nstate = STATE_16D; + end + STATE_16D : begin + core_Data_o[15:8] = bus_Data_i[7:0]; + bus_stb_o = bus_stb_o; + bus_stb_e = STBENABLE; + bus_rd_o = (core_rds) ? RDACTIVE : RDINACTIVE; + bus_wr_o = (core_wrs) ? WRACTIVE : WRINACTIVE; + core_done = bus_rdy_i; + if( bus_rdy_i == 1'b1 ) + nstate = STATE_IDLE; + else + nstate = STATE_16D; + end + STATE_BUSR : begin + bus_Addr_e = ADRDISABLE; + bus_Data_e = BUSDISABLE; + bus_stb_o = STBINACTIVE; + bus_stb_o = STBDISABLE; + bus_rd_o = RDINACTIVE; + bus_rd_e = RDDISABLE; + bus_wr_o = WRINACTIVE; + bus_wr_e = WRDISABLE; + bus_ack_o = 1'b1; + if( bus_req_i == 1'b1 ) + nstate = STATE_BUSR; + else + nstate = STATE_IDLE; + end + default : begin + nstate = STATE_RESET; + end + endcase + end + +endmodule
diff --git a/verilog/rtl/Minx16/Controller.v b/verilog/rtl/Minx16/Controller.v new file mode 100644 index 0000000..6a190e1 --- /dev/null +++ b/verilog/rtl/Minx16/Controller.v
@@ -0,0 +1,537 @@ + +module Controller ( + input clk +, input rst + +, input intr_i +, output reg inta +, input nmir +, output reg nmia +, input trap +, output reg trapa + +, input [15:0] ir +, input status +, input done + +, output reg ldIr +, output reg ldSp +, output reg incSp +, output reg decSp +, output reg ldPc +, output reg incPc + +, output reg rd16 +, output reg rd8 +, output reg [ 1:0] wr + +, output reg [ 2:0] addrSel +, output reg [ 2:0] dataSel +, output reg [ 2:0] trapSel +, output reg [ 2:0] ra +, output reg [ 2:0] rb +, output reg [ 2:0] rd +, output reg [ 2:0] wd +, output reg [ 3:0] aluop +, output reg [ 3:0] flagCond +, output reg flagSave +, output reg flagRest +, output reg op8 +); + + reg irqA = 0; + wire intr = intr_i & irqA; + reg dbg_invalidop = 0; + + // [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b000? alu 16 bit + // [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b001? alu 8h bit + // [15:13] [12:9][8:6][5:3][2:0] ALU16 with top bits == 3'b010? alu 8l bit + // [15:13] [12:9][8:6][5:3][2:0] MEMORY with top bits == 3'b011? alu slot can diff read/write, 16 or 8 bit + // [15:13] [12:9][8:6][5:3][2:0] JUMP with top bits == 3'b100? alu slot can diff conditions + // [15:13] [12:9][8:6][5:3][2:0] FREE with top bits == 3'b1xx? + + wire [2:0] majorOp = ir[15:13]; + wire [3:0] minorOp = ir[12: 9]; + + reg [3:0] pstate, nstate; + always @ (posedge clk or negedge rst) + if( rst == 1'b0 ) + pstate = 0; + else + pstate = nstate; + + always @* + begin + if( rst == 1'b0 ) + irqA = 0; + dbg_invalidop = 1'b0; + inta = 1'b0; + nmia = 1'b0; + trapa = 1'b0; + trapSel = 3'b000; + + ldIr = 1'b0; + ldSp = 1'b0; + incSp = 1'b0; + decSp = 1'b0; + ldPc = 1'b0; + incPc = 1'b0; + op8 = 1'b0; + + rd16 = 1'b0; + rd8 = 1'b0; + wr = 2'b00; + + addrSel = 3'b000; + dataSel = 3'b000; + ra = 3'b000; + rb = 3'b000; + rd = 3'b000; + wd = 3'b000; + aluop = 4'b0000; + flagCond = 1'b0; + flagSave = 1'b0; + flagRest = 1'b0; + case(pstate) + 4'b0000 : begin + addrSel = 3'b000; + rd16 = 1'b1; + ldIr = 1'b1; + incPc = done; + if( done == 1'b1 ) + nstate = 4'b0001; + else + nstate = 4'b0000; + end + 4'b0001 : begin + nstate = 4'b1111; + case(majorOp) + 3'b000 : begin //Alu 16 bit + flagSave = 1'b1; + dataSel = 3'b001; + aluop = minorOp; + ra = ir[ 8:6]; + rb = ir[ 5:3]; + rd = ir[ 2:0]; + wd = 3'b011; + nstate = 4'b1111; + end + 3'b001 : begin //Alu 8 bit high + flagSave = 1'b1; + dataSel = 3'b001; + aluop = minorOp; + ra = ir[ 8:6]; + rb = ir[ 5:3]; + rd = ir[ 2:0]; + wd = 3'b010; + nstate = 4'b1111; + end + 3'b010 : begin //Alu 8 bit low + flagSave = 1'b1; + dataSel = 3'b001; + aluop = minorOp; + ra = ir[ 8:6]; + rb = ir[ 5:3]; + rd = ir[ 2:0]; + wd = 3'b001; + op8 = 1'b1; + nstate = 4'b1111; + end + 3'b011 : begin //Memory operations + nstate = 4'b1111; + case(minorOp) + 4'b0000 : begin //16 bit read + rd16 = 1'b1; + ra = ir[8:6]; + rb = ir[5:3]; + rd = ir[2:0]; + wd = 3'b011; + dataSel = 3'b000; + addrSel = ir[5:3]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0001 : begin //16 bit write + wr = 2'b11; + rb = ir[5:3]; + ra = ir[2:0]; + dataSel = 3'b011; + addrSel = ir[8:6]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0010 : begin //8 bit read low + rd8 = 1'b1; + ra = ir[8:6]; + rb = ir[5:3]; + rd = ir[2:0]; + wd = 3'b001; + dataSel = 3'b000; + addrSel = ir[5:3]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0011 : begin //8 bit write low + wr = 2'b01; + rb = ir[5:3]; + ra = ir[2:0]; + dataSel = 3'b011; + addrSel = ir[8:6]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0100 : begin //8 bit read high + rd8 = 1'b1; + ra = ir[8:6]; + rb = ir[5:3]; + rd = ir[2:0]; + wd = 3'b110; + dataSel = 3'b000; + addrSel = ir[5:3]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0101 : begin //8 bit write high + wr = 2'b10; + rb = ir[5:3]; + ra = ir[2:0]; + dataSel = 3'b011; + addrSel = ir[8:6]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0110 : begin //8 Bit read and save sign extend + rd8 = 1'b1; + ra = ir[8:6]; + rb = ir[5:3]; + rd = ir[2:0]; + wd = 3'b011; + dataSel = 3'b101; + addrSel = ir[5:3]; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + 4'b0111 : begin //Load 8 bit sign extended immediate into register + rd = {2'b00, ir[8]}; + wd = 3'b011; + dataSel = 3'b111; + nstate = 4'b1111; + end + 4'b1000 : begin //8 Bit immediate load + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1001 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1010 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1011 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1100 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1101 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1110 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + 4'b1111 : begin + rd = ir[10:8]; + wd = {1'b0, ir[11], ~ir[11]}; + dataSel = 3'b110; + nstate = 4'b1111; + end + endcase + end + 3'b100 : begin //Jump and Call + flagCond = minorOp; + if( ir[8] ) //Call instruction + begin + if( status ) + begin + //Save PC + wr = 2'b11; + if( ~(minorOp == 4'b1111) ) + trapSel = 3'b111; + else + trapSel = 3'b000; + dataSel = 3'b010; + addrSel = 3'b101; + decSp = done; + if( done ) + nstate = 4'b1000; + else + nstate = 4'b0001; + end + else + nstate = 4'b1111; + end + else //Jump instruction + begin + if( status & ~(minorOp == 4'b1111)) + begin + rd16 = 1'b1; + dataSel = 3'b000; + addrSel = 3'b000; + ldPc = done; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + else if( status & (minorOp == 4'b1111)) + begin + ra = ir[7:5]; + dataSel = 3'b011; + ldPc = 1'b1; + nstate = 4'b1111; + end + else + begin + incPc = 1'b1; + nstate = 4'b1111; + end + end + end + 3'b101 : begin //Call + nstate = 4'b1111; + end + 3'b110 : begin //Free + nstate = 4'b1111; + end + 3'b111 : begin //Special Operations + nstate = 4'b1111; + case(minorOp) + 4'b0000 : begin //Load SP + if( ir[8] == 1'b1 ) + begin + ldSp = 1'b1; + dataSel = 3'b111; + nstate = 4'b1111; + end + else + begin + rd16 = 1'b1; + dataSel = 3'b000; + addrSel = 3'b000; + ldSp = 1'b1; + incPc = done; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b0001; + end + end + 4'b0001 : begin //Set Flag + if( ir[8] == 1'b1 ) + irqA = 1'b1; + else + irqA = 1'b0; + nstate = 4'b1111; + end + 4'b1110 : begin //return from interrupt + flagCond = ir[7:4]; + if( status ) + begin + incSp = 1'b1; + nstate = 4'b1010; //Load Flags from stack then PC + end + else + begin + nstate = 4'b1111; + end + end + 4'b1111 : begin //return + flagCond = ir[7:4]; + if( status ) + begin + incSp = 1'b1; + nstate = 4'b1001; //Load PC from stack + end + else + begin + nstate = 4'b1111; + end + end + default : nstate = 4'b1111; + endcase + end + endcase + end + 4'b0010 : begin // jump operation + nstate = 4'b1111; + end + 4'b0011 : begin + nstate = 4'b1111; + end + 4'b0100 : begin + nstate = 4'b1111; + end + 4'b0101 : begin + nstate = 4'b1111; + end + 4'b0110 : begin + nstate = 4'b1111; + end + 4'b1000 : begin // Finish Call by loading PC from selected destination + if( ~(minorOp == 4'b1111)) + begin + rd16 = 1'b1; + dataSel = 3'b000; + addrSel = 3'b000; + ldPc = done; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b1000; + end + else if(minorOp == 4'b1111) + begin + ra = ir[7:5]; + dataSel = 3'b011; + ldPc = 1'b1; + nstate = 4'b1111; + end + else + begin + incPc = 1'b1; + nstate = 4'b1111; + end + end + 4'b1001 : begin //Read from stack PC + rd16 = 1'b1; + ldPc = 1'b1; + addrSel = 3'b101; + dataSel = 3'b000; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b1001; + end + 4'b1010 : begin //Read from stack PC + rd16 = 1'b1; + ldPc = 1'b1; + addrSel = 3'b101; + dataSel = 3'b000; + if( done ) + nstate = 4'b1011; + else + nstate = 4'b1010; + end + 4'b1011 : begin //Read from stack Flags + rd16 = 1'b1; + flagRest = 1'b1; + addrSel = 3'b101; + dataSel = 3'b000; + incSp = done; + if( done ) + nstate = 4'b1111; + else + nstate = 4'b1011; + end + 4'b1100 : begin //Interrupts! Save PC + trapSel = 3'b000; + wr = 2'b11; + dataSel = 3'b010; + addrSel = 3'b101; + decSp = done; + if( done ) + nstate = 4'b1101; + else + nstate = 4'b1100; + end + 4'b1101 : begin //Load PC + dataSel = 3'b010; + addrSel = 3'b101; + if ( trap == 1'b1 ) + trapSel = 3'b001; + else if( nmir == 1'b1 ) + trapSel = 3'b010; + else if( intr == 1'b1 ) + trapSel = 3'b011; + else + trapSel = 3'b000; + nstate = 4'b1110; + end + 4'b1110 : begin //Load PC + ldPc = 1'b1; + dataSel = 3'b010; + addrSel = 3'b101; + if ( trap == 1'b1 ) + begin + trapSel = 3'b001; + trapa = 1'b1; + end + else if( nmir == 1'b1 ) + begin + trapSel = 3'b010; + nmia = 1'b1; + end + else if( intr == 1'b1 ) + begin + trapSel = 3'b011; + inta = 1'b1; + end + else + trapSel = 3'b000; + nstate = 4'b0000; + end + 4'b1111 : begin //Int ack + if( trap == 1'b1 | nmir == 1'b1 | intr == 1'b1 ) + begin + wr = 2'b11; + trapSel = 3'b000; + dataSel = 3'b100; + addrSel = 3'b101; + decSp = done; + if( done ) + nstate = 4'b1100; + else + nstate = 4'b1111; + end + else + nstate = 4'b0000; + end + default : nstate = 4'b0000; + endcase + end + +endmodule
diff --git a/verilog/rtl/Minx16/FlagRegister.v b/verilog/rtl/Minx16/FlagRegister.v new file mode 100644 index 0000000..e231dee --- /dev/null +++ b/verilog/rtl/Minx16/FlagRegister.v
@@ -0,0 +1,99 @@ + +module FlagRegister ( + input clk +, input rst + +, input [3:0] flagCond +, output reg status + +, input LD +, input flagRest + +, input Ci +, input Ni +, input Zi +, input Vi + +, input Cbk +, input Nbk +, input Zbk +, input Vbk + +, output reg Co +, output reg No +, output reg Zo +, output reg Vo +); + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Co <= 1'b0; + else if (LD == 1'b1) + Co <= Ci; + else if (flagRest == 1'b1) + Co <= Cbk; + else + Co <= Co; + end + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Vo <= 1'b0; + else if (LD == 1'b1) + Vo <= Vi; + else if (flagRest == 1'b1) + Vo <= Vbk; + else + Vo <= Vo; + end + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + No <= 1'b0; + else if (LD == 1'b1) + No <= Ni; + else if (flagRest == 1'b1) + No <= Nbk; + else + No <= No; + end + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Zo <= 1'b0; + else if (LD == 1'b1) + Zo <= Zi; + else if (flagRest == 1'b1) + Zo <= Zbk; + else + Zo <= Zo; + end + + // 7 5 3 1 + //({C16, C8, Z16, Z8, V16, V8, N16, N8}) + always @* + case(flagCond) + 4'b0000 : status = 1'b0; + 4'b0001 : status = 1'b1; + 4'b0010 : status = Zo; // Zero + 4'b0011 : status = ~Zo; //~Zero + 4'b0100 : status = Co; // Carry + 4'b0101 : status = ~Co; //~Carry + 4'b0110 : status = Vo; // Overflow + 4'b0111 : status = ~Vo; //~Overflow + 4'b1000 : status = No; // minus + 4'b1001 : status = ~No; // plus + 4'b1010 : status = (~No & ~Vo) | ( No & Vo); //greather than or equal + 4'b1011 : status = ( No & ~Vo) | (~No & Vo); //Less than + 4'b1100 : status = ~Zo & ((~No & ~Vo) | ( No & Vo)); // greather than + 4'b1101 : status = Zo & (( No & ~Vo) | (~No & Vo)); // less than or equal + 4'b1110 : status = 1'b0; + 4'b1111 : status = 1'b1; + endcase + + +endmodule
diff --git a/verilog/rtl/Minx16/Minx16Cpu.v b/verilog/rtl/Minx16/Minx16Cpu.v new file mode 100644 index 0000000..25ee9d4 --- /dev/null +++ b/verilog/rtl/Minx16/Minx16Cpu.v
@@ -0,0 +1,246 @@ + +module Minx16Cpu ( + input clk_i +, input rst_i + +, output wire [15:0] dbus_Addr_o +, output wire [15:0] dbus_Addr_e +, input [15:0] dbus_Data_i +, output wire [15:0] dbus_Data_o +, output wire [15:0] dbus_Data_e +, output wire [ 1:0] dbus_stb_o +, output wire [ 1:0] dbus_stb_e +, output wire dbus_rd_o +, output wire dbus_rd_e +, output wire dbus_wr_o +, output wire dbus_wr_e +, input dbus_rdy_i + +, input dbus_req_i +, output wire dbus_ack_o + +, input intr_i +, output wire inta_o +, input nmir_i +, output wire nmia_o +); + + wire clk = clk_i; + wire rst = rst_i; + + reg [15:0] databus; + reg [15:0] core_Addr; + wire [15:0] core_Data_o; + wire core_rd16; + wire core_rd8; + wire [ 1:0] core_wr; + wire core_rdy; + wire core_done; + + wire [15:0] wpc, pc, sp, ir; + wire [15:0] alu; + wire ldIr; + wire ldSp; + wire incSp; + wire decSp; + wire ldPc; + wire incPc; + wire [ 2:0] addrSel; + wire [ 2:0] dataSel; + wire [ 2:0] ra, rb; + wire [15:0] da, db; + wire [ 2:0] rd, wd; + wire [ 3:0] aluOp; + wire [ 3:0] flagCond; + wire flagSave; + wire [ 2:0] trapSel; + wire Ci, Co, Zo, No, Vo, op8, status; + + //Nothing trapping this build iteration + wire trap = 1'b0; + wire trapa; + + Biu1616 busUnit ( + .clk(clk) + , .rst(rst) + + , .core_Addr_i(core_Addr ) + , .core_Data_i(databus ) + , .core_Data_o(core_Data_o) + , .core_rd16 (core_rd16 ) + , .core_rd8 (core_rd8 ) + , .core_wr (core_wr ) + , .core_rdy (core_rdy ) + , .core_done (core_done ) + + , .bus_Addr_o (dbus_Addr_o) + , .bus_Addr_e (dbus_Addr_e) + , .bus_Data_i (dbus_Data_i) + , .bus_Data_o (dbus_Data_o) + , .bus_Data_e (dbus_Data_e) + , .bus_stb_o (dbus_stb_o ) + , .bus_stb_e (dbus_stb_e ) + , .bus_rd_o (dbus_rd_o ) + , .bus_rd_e (dbus_rd_e ) + , .bus_wr_o (dbus_wr_o ) + , .bus_wr_e (dbus_wr_e ) + , .bus_rdy_i (dbus_rdy_i ) + + , .bus_req_i (dbus_req_i ) + , .bus_ack_o (dbus_ack_o ) + ); + + Alu computationCenter ( + .op (aluOp) + , .dba(da) + , .dbb(db) + , .ci (Ci) + , .op8(op8) + , .Y (alu) + , .Co (Co) + , .Zo (Zo) + , .Vo (Vo) + , .No (No) + ); + + RegFile16 #(3) cpuRegs ( + .clk(clk) + , .rst(rst) + + , .ra(ra) + , .da(da) + + , .rb(rb) + , .db(db) + + , .rd(rd) + , .dd(databus) + , .wd(wd) + ); + + StackPointer #(16) spReg ( + .clk(clk) + , .rst(rst) + + , .LD(ldSp) + , .INC(incSp) + , .DEC(decSp) + , .D(databus) + , .Q(sp) + ); + + ProgramCounter #(16) pcReg ( + .clk(clk) + , .rst(rst) + + , .LD(ldPc) + , .INC(incPc) + , .D(databus) + , .Q(pc) + ); + + Register #(16) irReg ( + .clk(clk) + , .rst(rst) + + , .LD(ldIr) + , .D(databus) + , .Q(ir) + ); + + FlagRegister frReg ( + .clk(clk) + , .rst(rst) + + , .flagCond(flagCond) + , .status (status) + , .LD (flagSave) + , .flagRest(flagRest) + , .Ci (Co) + , .Ni (No) + , .Vi (Vo) + , .Zi (Zo) + + , .Cbk (databus[3]) + , .Zbk (databus[2]) + , .Nbk (databus[1]) + , .Vbk (databus[0]) + , .Co (Ci) + , .Zo (Zi) + , .No (Ni) + , .Vo (Vi) + ); + + Controller brain ( + .clk(clk) + , .rst(rst) + + , .trap (trap) + , .trapa (trapa) + , .intr_i (intr_i) + , .inta (inta_o) + , .nmir (nmir_i) + , .nmia (nmia_o) + + , .ir(ir) + , .status(status) + , .done(core_done | 1'b0 ) // Combinatorial (misinterpretation) of icarus verilog.. seems to break all if two fsms + // communcate with each other. this shouldn't fix it but it does.. LOL + + , .ldIr (ldIr) + , .ldSp (ldSp) + , .incSp(incSp) + , .decSp(decSp) + , .ldPc (ldPc) + , .incPc(incPc) + + , .rd16 (core_rd16) + , .rd8 (core_rd8 ) + , .wr (core_wr ) + + , .addrSel (addrSel) + , .dataSel (dataSel) + , .ra (ra) + , .rb (rb) + , .rd (rd) + , .wd (wd) + , .aluop (aluOp) + , .op8 (op8) + , .flagCond(flagCond) + , .flagRest(flagRest) + , .flagSave(flagSave) + , .trapSel (trapSel ) + ); + + always @* + case(addrSel) + 3'b000 : core_Addr = pc; + 3'b001 : core_Addr = pc; + 3'b010 : core_Addr = da; //Register? + 3'b011 : core_Addr = db; + 3'b100 : core_Addr = pc + da; + 3'b101 : core_Addr = sp; + 3'b110 : core_Addr = 16'h0001; + 3'b111 : core_Addr = 16'h0000; + endcase + + trapAddr trapHandles( + .trapSel(trapSel) + , .pc(pc) + , .cpc(wpc) + ); + + //dataMux datMux(databus, dataSel, core_Data_o, alu, pc, da); + always @* + case(dataSel) + 3'b000 : databus = core_Data_o; + 3'b001 : databus = alu; + 3'b010 : databus = wpc; + 3'b011 : databus = da; + 3'b100 : databus = {12'h000, Ci, Zi, Ni, Vi}; + 3'b101 : databus = {{8{core_Data_o[7]}}, core_Data_o[7:0] }; + 3'b110 : databus = { ir[7:0], ir[7:0]}; + 3'b111 : databus = {{8{ir[7]}}, ir[7:0]}; //Sign extend + endcase + +endmodule
diff --git a/verilog/rtl/Minx16/Minx16Top.v b/verilog/rtl/Minx16/Minx16Top.v new file mode 100644 index 0000000..e844260 --- /dev/null +++ b/verilog/rtl/Minx16/Minx16Top.v
@@ -0,0 +1,128 @@ + +module Minx16Top ( + input clk_i +, input rst_i + +, input [15:0] dbus_ADBus_i +, output wire [15:0] dbus_ADBus_o +, output wire [15:0] dbus_ADBus_e +, output wire dbus_ale_o +, output wire dbus_ale_e +, output wire dbus_dle_o +, output wire dbus_dle_e +, output wire [ 1:0] dbus_stb_o +, output wire [ 1:0] dbus_stb_e +, output wire dbus_rd_o +, output wire dbus_rd_e +, output wire dbus_wr_o +, output wire dbus_wr_e +, input dbus_rdy_i + +, input dbus_req_i +, output wire dbus_ack_o + +, input intr_i +, output wire inta_o +, input nmir_i +, output wire nmia_o +); + + wire [15:0] core_Addr_i; + wire [15:0] core_Data_i; + wire [15:0] core_Data_o; + wire [ 1:0] core_stb_o; + wire core_rd_o; + wire core_wr_o; + wire core_rdy_i; + + wire [15:0] scb_Addr_o; + wire [15:0] scb_Data_i; + wire [15:0] scb_Data_o; + wire [ 1:0] scb_stb_o; + wire scb_ce_o; + wire scb_rd_o; + wire scb_wr_o; + wire scb_rdy_i; + + Minx16Cpu cpu ( + .clk_i (clk_i) + , .rst_i (rst_i) + + , .intr_i (intr_i) + , .inta_o (inta_o) + , .nmir_i (nmir_i) + , .nmia_o (nmia_o) + + , .dbus_Addr_o (core_Addr_i) + , .dbus_Addr_e () + , .dbus_Data_i (core_Data_o) + , .dbus_Data_o (core_Data_i) + , .dbus_Data_e () + , .dbus_stb_o (core_stb_o) + , .dbus_stb_e () + , .dbus_rd_o (core_rd_o) + , .dbus_rd_e () + , .dbus_wr_o (core_wr_o) + , .dbus_wr_e () + , .dbus_rdy_i (core_rdy_i | 1'b0) + + , .dbus_req_i (dbus_req_i) + , .dbus_ack_o () + ); + + MinxFoldedBus1616 biu ( + .clk_i(clk_i) + , .rst_i(rst_i) + + , .core_Addr_i(core_Addr_i) + , .core_Data_i(core_Data_i) + , .core_Data_o(core_Data_o) + , .core_stb_i(core_stb_o) + , .core_rd_i(core_rd_o) + , .core_wr_i(core_wr_o) + , .core_rdy_o(core_rdy_i) + + , .scb_Addr_o(scb_Addr_o) + , .scb_Data_i(scb_Data_o) + , .scb_Data_o(scb_Data_i) + , .scb_stb_o (scb_stb_o) + , .scb_ce_o (scb_ce_o) + , .scb_rd_o (scb_rd_o) + , .scb_wr_o (scb_wr_o) + , .scb_rdy_i (scb_rdy_i) + + , .dbus_ADBus_i(dbus_ADBus_i) + , .dbus_ADBus_o(dbus_ADBus_o) + , .dbus_ADBus_e(dbus_ADBus_e) + , .dbus_ale_o (dbus_ale_o) + , .dbus_ale_e (dbus_ale_e) + , .dbus_dle_o (dbus_dle_o) + , .dbus_dle_e (dbus_dle_e) + , .dbus_stb_o (dbus_stb_o) + , .dbus_stb_e (dbus_stb_e) + , .dbus_rd_o (dbus_rd_o) + , .dbus_rd_e (dbus_rd_e) + , .dbus_wr_o (dbus_wr_o) + , .dbus_wr_e (dbus_wr_e) + , .dbus_rdy_i (dbus_rdy_i) + + , .dbus_req_i (dbus_req_i) + , .dbus_ack_o (dbus_ack_o) + ); + + //Block of fast memory + SCB_memory scratchPad ( + .clk_i (clk_i) + , .rst_i (rst_i) + + , .scb_Addr_i(scb_Addr_o) + , .scb_Data_i(scb_Data_i) + , .scb_Data_o(scb_Data_o) + , .scb_stb_i (scb_stb_o) + , .scb_ce_i (scb_ce_o) + , .scb_rd_i (scb_rd_o) + , .scb_wr_i (scb_wr_o) + , .scb_rdy_o (scb_rdy_i) + ); + +endmodule
diff --git a/verilog/rtl/Minx16/MinxFoldedBus1616.v b/verilog/rtl/Minx16/MinxFoldedBus1616.v new file mode 100644 index 0000000..83a387a --- /dev/null +++ b/verilog/rtl/Minx16/MinxFoldedBus1616.v
@@ -0,0 +1,231 @@ + +module MinxFoldedBus1616 ( + input clk_i +, input rst_i + +//Core side +, input [A-1:0] core_Addr_i +, input [D-1:0] core_Data_i +, output reg [D-1:0] core_Data_o +, input [B-1:0] core_stb_i +, input core_rd_i +, input core_wr_i +, output reg core_rdy_o + +//Scratchpad Memory +, output reg [A-1:0] scb_Addr_o +, input [D-1:0] scb_Data_i +, output reg [D-1:0] scb_Data_o +, output reg [B-1:0] scb_stb_o +, output reg scb_ce_o +, output reg scb_rd_o +, output reg scb_wr_o +, input scb_rdy_i + +//Bus side with multiplexed bus +, input [A-1:0] dbus_ADBus_i +, output reg [D-1:0] dbus_ADBus_o +, output reg [D-1:0] dbus_ADBus_e +, output reg dbus_ale_o +, output reg dbus_ale_e +, output reg dbus_dle_o +, output reg dbus_dle_e +, output reg [B-1:0] dbus_stb_o +, output reg [B-1:0] dbus_stb_e +, output reg dbus_rd_o +, output reg dbus_rd_e +, output reg dbus_wr_o +, output reg dbus_wr_e +, input dbus_rdy_i + +, input dbus_req_i +, output reg dbus_ack_o +); + + localparam SCBBASE = 16'hF800; + + localparam A = 16; + localparam D = 16; + localparam B = 2; + localparam BUSENABLE = {D{1'b0}}; + localparam BUSDISABLE = {D{1'b1}}; + + localparam STBENABLE = {B{1'b0}}; + localparam STBDISABLE = {B{1'b1}}; + localparam STBACTIVE = 1'b1; + localparam STBINACTIVE = 1'b0; + + localparam ALEACTIVE = 1'b1; + localparam ALEINACTIVE = 1'b0; + localparam ALEENABLE = 1'b0; + localparam ALEDISABLE = 1'b1; + + localparam DLEACTIVE = 1'b1; + localparam DLEINACTIVE = 1'b0; + localparam DLEENABLE = 1'b0; + localparam DLEDISABLE = 1'b1; + + localparam RDACTIVE = 1'b0; + localparam RDINACTIVE = 1'b1; + localparam RDENABLE = 1'b0; + localparam RDDISABLE = 1'b1; + + localparam WRACTIVE = 1'b0; + localparam WRINACTIVE = 1'b1; + localparam WRENABLE = 1'b0; + localparam WRDISABLE = 1'b1; + + wire rdActive = core_rd_i == RDACTIVE; + wire wrActive = core_wr_i == WRACTIVE; + wire scb_cen = (core_Addr_i >= SCBBASE && core_Addr_i < SCBBASE + 2**(9+2)); + + reg [3:0] pstate, nstate; + always @ (posedge clk_i or negedge rst_i) + if( rst_i == 1'b0 ) + pstate <= 0; + else + pstate <= nstate; + + always @* + begin + dbus_ADBus_o = 0; + dbus_ADBus_e = BUSENABLE; + dbus_ale_o = ALEINACTIVE; + dbus_ale_e = ALEENABLE; + dbus_dle_o = DLEINACTIVE; + dbus_dle_e = DLEENABLE; + dbus_stb_o = STBINACTIVE; + dbus_stb_e = STBENABLE; + dbus_rd_o = RDINACTIVE; + dbus_rd_e = RDENABLE; + dbus_wr_o = WRINACTIVE; + dbus_wr_e = WRENABLE; + dbus_ack_o = 1'b0; + core_rdy_o = 1'b0; + + scb_Addr_o = {A{1'b0}}; + scb_Data_o = {D{1'b0}}; + scb_ce_o = 1'b0; + scb_stb_o = {B{STBINACTIVE}}; + scb_rd_o = RDINACTIVE; + scb_wr_o = WRINACTIVE; + + case(pstate) + 4'b0000 : begin + core_Data_o = 0; + end + 4'b0001 : begin + dbus_ADBus_e = BUSDISABLE; + dbus_ale_e = ALEDISABLE; + dbus_dle_e = DLEDISABLE; + dbus_stb_e = STBDISABLE; + dbus_rd_e = RDDISABLE; + dbus_wr_e = WRDISABLE; + dbus_ack_o = 1'b1; + end + 4'b0010 : begin + dbus_ADBus_o = core_Addr_i; + dbus_stb_o = {B{STBACTIVE}}; + dbus_ale_o = ALEINACTIVE; + end + 4'b0011 : begin + dbus_ADBus_o = core_Addr_i; + dbus_stb_o = {B{STBACTIVE}}; + dbus_ale_o = ALEACTIVE; + end + 4'b0100 : begin + dbus_ADBus_o = core_Addr_i; + dbus_stb_o = {B{STBACTIVE}}; + dbus_ale_o = ALEINACTIVE; + end + 4'b0101 : begin + dbus_ADBus_o = core_Data_i; + if(~wrActive) + dbus_ADBus_e = BUSDISABLE; + dbus_dle_o = DLEACTIVE; + dbus_stb_o = core_stb_i; + dbus_rd_o = RDINACTIVE; + dbus_wr_o = WRINACTIVE; + end + 4'b0110 : begin + core_Data_o = dbus_ADBus_i; + dbus_ADBus_o = core_Data_i; + if(~wrActive) + dbus_ADBus_e = BUSDISABLE; + dbus_dle_o = DLEACTIVE; + dbus_stb_o = core_stb_i; + dbus_rd_o = core_rd_i; + dbus_wr_o = WRINACTIVE; + end + 4'b0111 : begin + core_Data_o = dbus_ADBus_i; + dbus_ADBus_o = core_Data_i; + if(~wrActive) + dbus_ADBus_e = BUSDISABLE; + dbus_dle_o = DLEACTIVE; + dbus_stb_o = core_stb_i; + dbus_rd_o = core_rd_i; + dbus_wr_o = core_wr_i; + core_rdy_o = dbus_rdy_i; + end + 4'b1000 : begin + scb_Addr_o = core_Addr_i; + scb_Data_o = core_Data_i; + scb_ce_o = 1'b1; + core_Data_o = scb_Data_i; + scb_stb_o = core_stb_i; + scb_rd_o = core_rd_i; + scb_wr_o = core_wr_i; + end + 4'b1001 : begin + scb_Addr_o = core_Addr_i; + scb_Data_o = core_Data_i; + scb_ce_o = 1'b1; + core_Data_o = scb_Data_i; + scb_stb_o = core_stb_i; + scb_rd_o = core_rd_i; + scb_wr_o = core_wr_i; + end + 4'b1010 : begin + scb_Addr_o = core_Addr_i; + scb_Data_o = core_Data_i; + scb_ce_o = 1'b1; + core_Data_o = scb_Data_i; + scb_stb_o = core_stb_i; + scb_rd_o = core_rd_i; + scb_wr_o = core_wr_i; + core_rdy_o = scb_rdy_i; + end + endcase + end + + always @* + begin + nstate = 4'b0000; + case(pstate) + 4'b0000 : begin + if(scb_cen & (rdActive || wrActive)) + nstate = 4'b1000; + if(~scb_cen & (rdActive || wrActive)) + nstate = 4'b0010; + else if( dbus_req_i ) + nstate = 4'b0001; + end + 4'b0001 : if( dbus_req_i ) + nstate = 4'b0001; + 4'b0010 : nstate = 4'b0011; + 4'b0011 : nstate = 4'b0100; + 4'b0100 : nstate = 4'b0101; + 4'b0101 : nstate = 4'b0110; + 4'b0110 : nstate = 4'b0111; + 4'b0111 : if( dbus_rdy_i ) + nstate = 4'b0000; + else + nstate = 4'b0111; + 4'b1000 : nstate = 4'b1001; + 4'b1001 : nstate = 4'b1010; + 4'b1010 : nstate = 4'b0000; + endcase + end + +endmodule
diff --git a/verilog/rtl/Minx16/ParametricRegister.v b/verilog/rtl/Minx16/ParametricRegister.v new file mode 100644 index 0000000..dd6a9c6 --- /dev/null +++ b/verilog/rtl/Minx16/ParametricRegister.v
@@ -0,0 +1,25 @@ + +module Register #( + parameter W = 8 +) ( + input clk +, input rst + +, input LD +, input [W-1:0] D +, output reg [W-1:0] Q +); + + initial Q = 0; + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Q <= 0; + else if (LD == 1'b1) + Q <= D; + else + Q <= Q; + end + +endmodule
diff --git a/verilog/rtl/Minx16/ProgramCounter.v b/verilog/rtl/Minx16/ProgramCounter.v new file mode 100644 index 0000000..e1ebbd6 --- /dev/null +++ b/verilog/rtl/Minx16/ProgramCounter.v
@@ -0,0 +1,28 @@ + +module ProgramCounter #( + parameter W = 8 +) ( + input clk +, input rst + +, input LD +, input INC +, input [W-1:0] D +, output reg [W-1:0] Q +); + + initial Q = 0; + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Q <= 0; + else if (LD == 1'b1) + Q <= D; + else if (INC == 1'b1) + Q <= Q + (W/8); + else + Q <= Q; + end + +endmodule
diff --git a/verilog/rtl/Minx16/RegFile.v b/verilog/rtl/Minx16/RegFile.v new file mode 100644 index 0000000..1b00c80 --- /dev/null +++ b/verilog/rtl/Minx16/RegFile.v
@@ -0,0 +1,49 @@ + +module RegFile16 #( + parameter A = 3 +) ( + input clk +, input rst + +, input [A-1:0] ra +, output reg [ 15:0] da +, input [A-1:0] rb +, output reg [ 15:0] db + +, input [A-1:0] rd +, input [ 15:0] dd +, input [ 2:0] wd +); + + localparam N = 2 ** A; + reg [15:0] file [N-1:0]; + + wire [15:0] dv = file[rd]; + reg [15:0] df; + always @* + case(wd) + 3'b000 : df = dv; + 3'b001 : df = {dv[15:8], dd[ 7:0]}; + 3'b010 : df = {dd[15:8], dv[ 7:0]}; + 3'b011 : df = dd; + 3'b100 : df = {dv[ 7:0], dv[15:8]}; + 3'b101 : df = {dv[ 7:0], dd[15:8]}; + 3'b110 : df = {dd[ 7:0], dv[15:8]}; + 3'b111 : df = {dd[ 7:0], dd[15:8]}; + endcase + + integer ii; + always @ (posedge clk or negedge rst) + if( rst == 1'b0 ) + for(ii = 0; ii < N; ii = ii + 1) + file[ii] = 16'h0000; + else + file[rd] = df; + + always @ (negedge clk) + da = file[ra]; + + always @ (negedge clk) + db = file[rb]; + +endmodule
diff --git a/verilog/rtl/Minx16/StackPointer.v b/verilog/rtl/Minx16/StackPointer.v new file mode 100644 index 0000000..dd3b9f1 --- /dev/null +++ b/verilog/rtl/Minx16/StackPointer.v
@@ -0,0 +1,31 @@ + +module StackPointer #( + parameter W = 8 +) ( + input clk +, input rst + +, input LD +, input INC +, input DEC +, input [W-1:0] D +, output reg [W-1:0] Q +); + + initial Q = 0; + + always @ (posedge clk or negedge rst) + begin + if( rst == 1'b0 ) + Q <= 0; + else if (LD == 1'b1) + Q <= D; + else if (INC == 1'b1) + Q <= Q + (W/8); + else if (DEC == 1'b1) + Q <= Q - (W/8); + else + Q <= Q; + end + +endmodule
diff --git a/verilog/rtl/Minx16/scb.v b/verilog/rtl/Minx16/scb.v new file mode 100644 index 0000000..0327be0 --- /dev/null +++ b/verilog/rtl/Minx16/scb.v
@@ -0,0 +1,76 @@ +//Design for 1024x16 or 2kb of onboard memory scratchpad +module SCB_memory ( + input clk_i +, input rst_i + +, input [A-1:0] scb_Addr_i +, input [D-1:0] scb_Data_i +, output wire [D-1:0] scb_Data_o +, input [B-1:0] scb_stb_i +, input scb_ce_i +, input scb_rd_i +, input scb_wr_i +, output wire scb_rdy_o +); + + localparam A = 11; + localparam D = 16; + localparam B = 2; + + wire highSelect = scb_ce_i & scb_Addr_i[10]; + wire lowSelect = scb_ce_i & ~scb_Addr_i[10]; + wire oddSelect = scb_ce_i & scb_stb_i[1]; + wire evenSelect = scb_ce_i & scb_stb_i[0]; + wire [ 8:0] addr = scb_Addr_i[9:1]; + wire [ 7:0] dblo = scb_Data_i[7:0]; + wire [ 7:0] dbhi = scb_Data_i[15:8]; + + wire [ 7:0] dbolo, dbohi, dbelo, dbehi; + wire [15:0] dbol = {dbolo, dbelo}; + wire [15:0] dboh = {dbohi, dbehi}; + + assign scb_rdy_o = 1'b1; + assign scb_Data_o = (highSelect) ? dboh :dbol; + + gf180mcu_fd_ip_sram__sram512x8m8wm1 oddMemLow ( + .CLK (clk_i) + , .CEN (~(oddSelect & lowSelect)) + , .GWEN(~scb_ce_i | scb_wr_i) + , .WEN (8'h00) + , .A (addr) + , .D (dbhi) + , .Q (dbolo) + ); + + gf180mcu_fd_ip_sram__sram512x8m8wm1 oddMemHigh ( + .CLK (clk_i) + , .CEN (~(oddSelect & highSelect)) + , .GWEN(~scb_ce_i | scb_wr_i) + , .WEN (8'h00) + , .A (addr) + , .D (dbhi) + , .Q (dbohi) + ); + + gf180mcu_fd_ip_sram__sram512x8m8wm1 evenMemLow ( + .CLK (clk_i) + , .CEN (~(evenSelect & lowSelect)) + , .GWEN(~scb_ce_i | scb_wr_i) + , .WEN (8'h00) + , .A (addr) + , .D (dblo) + , .Q (dbelo) + ); + + gf180mcu_fd_ip_sram__sram512x8m8wm1 evenMemHigh( + .CLK (clk_i) + , .CEN (~(evenSelect & highSelect)) + , .GWEN(~scb_ce_i | scb_wr_i) + , .WEN (8'h00) + , .A (addr) + , .D (dblo) + , .Q (dbehi) + ); + +endmodule +
diff --git a/verilog/rtl/Minx16/trapAddr.v b/verilog/rtl/Minx16/trapAddr.v new file mode 100644 index 0000000..2798a97 --- /dev/null +++ b/verilog/rtl/Minx16/trapAddr.v
@@ -0,0 +1,22 @@ + +module trapAddr #( + parameter A = 16 +) ( + input [ 2:0] trapSel +, input [A-1:0] pc +, output reg [A-1:0] cpc +); + + always @* + case(trapSel) + 3'b000 : cpc = pc; + 3'b001 : cpc = 16'h0400; + 3'b010 : cpc = 16'h0800; + 3'b011 : cpc = 16'h0c00; + 3'b100 : cpc = 16'h0000; + 3'b101 : cpc = 16'h0000; + 3'b110 : cpc = 16'h0000; + 3'b111 : cpc = pc + 2'd2; + endcase + +endmodule
diff --git a/verilog/rtl/gf180mcu_fd_ip_sram/gf180mcu_fd_ip_sram__sram512x8m8wm1.v b/verilog/rtl/gf180mcu_fd_ip_sram/gf180mcu_fd_ip_sram__sram512x8m8wm1.v new file mode 100644 index 0000000..484732b --- /dev/null +++ b/verilog/rtl/gf180mcu_fd_ip_sram/gf180mcu_fd_ip_sram__sram512x8m8wm1.v
@@ -0,0 +1,465 @@ +/* + * $Id: $ + * Copyright 2022 GlobalFoundries PDK Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http:www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project: 018 5VGREEN SRAM + * Author: GlobalFoundries PDK Authors + * Data Created: 05-06-2014 + * Revision: 0.0 + * + * Description: gf180mcu_fd_ip_sram__sram512x8m8wm1 Simulation Model + */ + +`timescale 1 ps / 1 ps + +module gf180mcu_fd_ip_sram__sram512x8m8wm1 ( + CLK, + CEN, + GWEN, + WEN, + A, + D, + Q, + VDD, + VSS +); + +input CLK; +input CEN; //Chip Enable +input GWEN; //Global Write Enable +input [7:0] WEN; //Write Enable +input [8:0] A; +input [7:0] D; +output [7:0] Q; +inout VDD; +inout VSS; + +reg [7:0] mem[511:0]; +reg [7:0] qo_reg; + +wire cen_flag; +wire write_flag; +wire read_flag; + +reg ntf_Tcyc; //notifier for clock period/low/high pulse +reg ntf_Tckh; +reg ntf_Tckl; + +reg ntf_tcs; //notifier for setup time +reg ntf_tas; +reg ntf_tds; +reg ntf_tws; +reg ntf_twis; + +reg ntf_tch; //notifier for hold time +reg ntf_tah; +reg ntf_tdh; +reg ntf_twh; +reg ntf_twih; + +wire no_st_viol; //no setup violation +wire no_hd_viol; //no hold violation +wire no_ck_viol; //no clock related violation + +reg clk_dly; //for read/write +reg write_flag_dly; //for write invalidation +reg read_flag_dly; //for read invalidation +reg cen_dly; +reg cen_fell; //detect CEN 1 -> 0 transition +reg cen_not_rst; //detect CEN is not reset initially + +wire [7:0] we; //inversion of WEN +wire [7:0] cd2; +wire [7:0] cd4; +wire [7:0] cd5; +reg [7:0] cdx; + +reg [8:0] marked_a; + +integer i; + +assign Q = qo_reg; + +//---- for debugging +wire [7:0] mem_0; +wire [7:0] mem_1; +wire [7:0] mem_2; +wire [7:0] mem_3; +assign mem_0 = mem[0]; +assign mem_1 = mem[1]; +assign mem_2 = mem[2]; +assign mem_3 = mem[3]; + +always @(CEN) cen_dly = #100 CEN; +always @(CEN or cen_dly) begin + if (!CEN & cen_dly) cen_fell = 1'b1; +end + +always @(posedge CLK) begin + if (!CEN & !cen_fell & !cen_not_rst) cen_not_rst = 1; +end + +always @(posedge cen_not_rst) begin + $display("-------- WARNING: CEN is not reset, memory is not operational ---------"); + $display("-------- @Time %0t: scope = %m", $realtime, " ---------"); +end + +always @(posedge cen_fell) begin + $display("-------- MESSAGE: CEN is just reset, memory is operational ---------"); + $display("-------- @Time %0t: scope = %m", $realtime, " ---------"); +end + +assign cen_flag = cen_fell & !CEN; +assign write_flag = cen_fell & !CEN & !GWEN & !(&WEN); +assign read_flag = cen_fell & !CEN & GWEN; + +reg cen_flag_dly; +always @(cen_flag) cen_flag_dly = #100 cen_flag; + +specify + specparam Tcyc = 55600 : 55600 : 55600; + specparam Tckh = 25000 : 25000 : 25000; + specparam Tckl = 25000 : 25000 : 25000; + + specparam tcs = 5000 : 5000 : 5000; + specparam tas = 5000 : 5000 : 5000; + specparam tds = 5000 : 5000 : 5000; + specparam tws = 5000 : 5000 : 5000; + specparam twis = 5000 : 5000 : 5000; + + specparam tch = 10000 : 10000 : 10000; + specparam tah = 10000 : 10000 : 10000; + specparam tdh = 10000 : 10000 : 10000; + specparam twh = 10000 : 10000 : 10000; + specparam twih = 10000 : 10000 : 10000; + + specparam ta = 45000 : 45000 : 45000; + + specparam Tdly = 100 : 100: 100; + +//---- CLK period/pulse timing + $period (negedge CLK, Tcyc, ntf_Tcyc); + $width (posedge CLK, Tckh, 0, ntf_Tckh); + $width (negedge CLK, Tckl, 0, ntf_Tckl); + +//---- CEN setup/hold timing + $setup (negedge CEN, posedge CLK &&& cen_flag, tcs, ntf_tcs); + $setup (posedge CEN, posedge CLK &&& cen_flag, tcs, ntf_tcs); + + $hold (posedge CLK &&& cen_flag_dly, posedge CEN, tch, ntf_tch); + $hold (posedge CLK &&& cen_flag, negedge CEN, tch, ntf_tch); + +//---- GWEN setup/hold timing + $setup (negedge GWEN, posedge CLK &&& cen_flag, tws, ntf_tws); + $setup (posedge GWEN, posedge CLK &&& cen_flag, tws, ntf_tws); + + $hold (posedge CLK &&& cen_flag, posedge GWEN, twh, ntf_twh); + $hold (posedge CLK &&& cen_flag, negedge GWEN, twh, ntf_twh); + +//---- WEN[7:0] setup/hold timing + $setup (negedge WEN[0], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[1], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[2], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[3], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[4], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[5], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[6], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (negedge WEN[7], posedge CLK &&& write_flag, twis, ntf_twis); + + $setup (posedge WEN[0], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[1], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[2], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[3], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[4], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[5], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[6], posedge CLK &&& write_flag, twis, ntf_twis); + $setup (posedge WEN[7], posedge CLK &&& write_flag, twis, ntf_twis); + + $hold (posedge CLK &&& write_flag, posedge WEN[0], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[1], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[2], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[3], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[4], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[5], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[6], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, posedge WEN[7], twih, ntf_twih); + + $hold (posedge CLK &&& write_flag, negedge WEN[0], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[1], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[2], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[3], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[4], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[5], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[6], twih, ntf_twih); + $hold (posedge CLK &&& write_flag, negedge WEN[7], twih, ntf_twih); + +//---- A[8:0] setup/hold timing + $setup (posedge A[0], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[1], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[2], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[3], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[4], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[5], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[6], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[7], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (posedge A[8], posedge CLK &&& cen_flag, tas, ntf_tas); + + $setup (negedge A[0], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[1], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[2], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[3], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[4], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[5], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[6], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[7], posedge CLK &&& cen_flag, tas, ntf_tas); + $setup (negedge A[8], posedge CLK &&& cen_flag, tas, ntf_tas); + + $hold (posedge CLK &&& cen_flag, negedge A[0], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[1], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[2], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[3], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[4], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[5], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[6], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[7], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, negedge A[8], tah, ntf_tah); + + $hold (posedge CLK &&& cen_flag, posedge A[0], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[1], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[2], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[3], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[4], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[5], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[6], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[7], tah, ntf_tah); + $hold (posedge CLK &&& cen_flag, posedge A[8], tah, ntf_tah); + +//---- D[7:0] setup/hold timing + $setup (posedge D[0], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[1], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[2], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[3], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[4], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[5], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[6], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (posedge D[7], posedge CLK &&& write_flag, tds, ntf_tds); + + $setup (negedge D[0], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[1], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[2], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[3], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[4], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[5], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[6], posedge CLK &&& write_flag, tds, ntf_tds); + $setup (negedge D[7], posedge CLK &&& write_flag, tds, ntf_tds); + + $hold (posedge CLK &&& write_flag, negedge D[0], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[1], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[2], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[3], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[4], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[5], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[6], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, negedge D[7], tdh, ntf_tdh); + + $hold (posedge CLK &&& write_flag, posedge D[0], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[1], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[2], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[3], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[4], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[5], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[6], tdh, ntf_tdh); + $hold (posedge CLK &&& write_flag, posedge D[7], tdh, ntf_tdh); + +//---- Output delay +// rise transition: 0->1, z->1, Ta +// fall transition: 1->0, 1->z, Ta +// turn-off transition: 0->z, 1->z, Tcqx +//if (!CEN & GWEN) (posedge CLK => (Q : 8'bx)) = (Ta, Ta, Tcqx); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[0] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[1] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[2] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[3] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[4] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[5] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[6] : 1'bx)) = (ta, ta); +if ((CEN == 1'b0) && (GWEN == 1'b1)) (posedge CLK => (Q[7] : 1'bx)) = (ta, ta); +endspecify + +assign no_st_viol = ~(|{ntf_tcs, ntf_tas, ntf_tds, ntf_tws, ntf_twis}); +assign no_hd_viol = ~(|{ntf_tch, ntf_tah, ntf_tdh, ntf_twh, ntf_twih}); +assign no_ck_viol = ~(|{ntf_Tcyc, ntf_Tckh, ntf_Tckl}); + +always @(CLK) clk_dly = #Tdly CLK; +always @(CLK) write_flag_dly = #200 write_flag; +always @(CLK) read_flag_dly = #200 read_flag; + +always @(posedge CLK) marked_a = A; + +assign we = ~WEN; +assign cd2 = mem[A] & WEN; //set write bits to 0, others unchanged +assign cd4 = D & we; //set write bits to 0/1, others = 0 +assign cd5 = cd2 | cd4; //memory content after write + +always @(posedge CLK) cdx = {8{1'bx}} & we; //latch cdx + +always @(posedge clk_dly) begin + if (write_flag) begin //write + if (no_st_viol) begin //write, no viol + mem[A] = cd5; + end + else begin //write, with viol + mem[A] = mem[A] ^ cdx; //1^x = x + qo_reg = qo_reg ^ cdx; + end + end //write + else if (read_flag) begin //read + if (no_st_viol) begin //read, no viol + qo_reg = mem[marked_a]; + end + else begin //read, with viol + qo_reg = 8'bx; + end + end //read +end + +always @(negedge clk_dly) begin //invalidate write/read when hold/clk viol + if (no_hd_viol == 0 | no_ck_viol == 0) begin + if (write_flag_dly) begin + if (ntf_twh) begin + mem[marked_a] = mem[marked_a] ^ 8'bx; //GWEN can't be used to generate cdx + qo_reg = qo_reg ^ 8'bx; + end + else begin + mem[marked_a] = mem[marked_a] ^ cdx; + qo_reg = qo_reg ^ cdx; + end + end + else if (read_flag_dly) begin + qo_reg = 8'bx; + end + + #100; + ntf_tch = 0; + ntf_tah = 0; + ntf_tdh = 0; + ntf_twh = 0; + ntf_twih = 0; + + ntf_Tcyc = 0; + ntf_Tckh = 0; + ntf_Tckl = 0; + end + else begin + #100; + ntf_tch = 0; + ntf_tah = 0; + ntf_tdh = 0; + ntf_twh = 0; + ntf_twih = 0; + + ntf_Tcyc = 0; + ntf_Tckh = 0; + ntf_Tckl = 0; + end +end + +always @(posedge ntf_tcs or posedge ntf_tas or posedge ntf_tds or + posedge ntf_tws or posedge ntf_twis or + posedge ntf_tch or posedge ntf_tah or posedge ntf_tdh or + posedge ntf_twh or posedge ntf_twih or + posedge ntf_Tcyc or posedge ntf_Tckh or posedge ntf_Tckl) begin + if (cen_fell) begin + #Tdly; + if (ntf_tcs) $display("---- ERROR: CEN setup violation! ----"); + if (ntf_tas) $display("---- ERROR: A setup violation! ----"); + if (ntf_tds) $display("---- ERROR: D setup violation! ----"); + if (ntf_tws) $display("---- ERROR: GWEN setup violation! ----"); + if (ntf_twis) $display("---- ERROR: WEN setup violation! ----"); + + if (ntf_tch) $display("---- ERROR: CEN hold violation! ----"); + if (ntf_tah) $display("---- ERROR: A hold violation! ----"); + if (ntf_tdh) $display("---- ERROR: D hold violation! ----"); + if (ntf_twh) $display("---- ERROR: GWEN hold violation! ----"); + if (ntf_twih) $display("---- ERROR: WEN hold violation! ----"); + + if (ntf_Tcyc) $display("---- ERROR: CLK period violation! ----"); + if (ntf_Tckh) $display("---- ERROR: CLK pulse width high violation! ----"); + if (ntf_Tckl) $display("---- ERROR: CLK pulse width low violation! ----"); + end +end + +always @(posedge cen_fell) begin //reset fasle notifiers + ntf_tcs = 0; //after CEN reset (CEN from 1 to 0) + ntf_tas = 0; + ntf_tds = 0; + ntf_tws = 0; + ntf_twis = 0; + + ntf_tch = 0; + ntf_tah = 0; + ntf_tdh = 0; + ntf_twh = 0; + ntf_twih = 0; +end + +always @(negedge clk_dly) begin //reset setup/hold notifiers + #100; + ntf_tcs = 0; + ntf_tas = 0; + ntf_tds = 0; + ntf_tws = 0; + ntf_twis = 0; + + ntf_tch = 0; + ntf_tah = 0; + ntf_tdh = 0; + ntf_twh = 0; + ntf_twih = 0; +end + +initial begin //initialization + ntf_Tcyc = 0; + ntf_Tckh = 0; + ntf_Tckl = 0; + + ntf_tcs = 0; + ntf_tas = 0; + ntf_tds = 0; + ntf_tws = 0; + ntf_twis = 0; + + ntf_tch = 0; + ntf_tah = 0; + ntf_tdh = 0; + ntf_twh = 0; + ntf_twih = 0; + + marked_a = 9'd0; + + qo_reg = 8'd0; + clk_dly = 0; + write_flag_dly = 0; + read_flag_dly = 0; + cen_dly = 0; + cen_fell = 0; + cen_not_rst = 0; + + for(i=0; i<512; i=i+1) begin + mem[i] = 8'd0; + end +end + +endmodule
diff --git a/verilog/rtl/user_proj_example.v b/verilog/rtl/user_proj_example.v index 26081e9..04421fe 100644 --- a/verilog/rtl/user_proj_example.v +++ b/verilog/rtl/user_proj_example.v
@@ -18,20 +18,7 @@ *------------------------------------------------------------- * * user_proj_example - * - * This is an example of a (trivially simple) user project, - * showing how the user project can connect to the logic - * analyzer, the wishbone bus, and the I/O pads. - * - * This project generates an integer count, which is output - * on the user area GPIO pads (digital output only). The - * wishbone connection allows the project to be controlled - * (start and stop) from the management SoC program. - * - * See the testbenches in directory "mprj_counter" for the - * example programs that drive this user project. The three - * testbenches are "io_ports", "la_test1", and "la_test2". - * + * *------------------------------------------------------------- */ @@ -44,17 +31,17 @@ `endif // Wishbone Slave ports (WB MI A) - input wb_clk_i, - input wb_rst_i, - input wbs_stb_i, - input wbs_cyc_i, - input wbs_we_i, - input [3:0] wbs_sel_i, - input [31:0] wbs_dat_i, - input [31:0] wbs_adr_i, - output wbs_ack_o, + input wb_clk_i, + input wb_rst_i, + input wbs_stb_i, + input wbs_cyc_i, + input wbs_we_i, + input [ 3:0] wbs_sel_i, + input [31:0] wbs_dat_i, + input [31:0] wbs_adr_i, + output wbs_ack_o, output [31:0] wbs_dat_o, - + // Logic Analyzer Signals input [127:0] la_data_in, output [127:0] la_data_out, @@ -68,98 +55,74 @@ // IRQ output [2:0] irq ); - wire clk; - wire rst; - - wire [`MPRJ_IO_PADS-1:0] io_in; - wire [`MPRJ_IO_PADS-1:0] io_out; - wire [`MPRJ_IO_PADS-1:0] io_oeb; - - wire [31:0] rdata; - wire [31:0] wdata; - wire [BITS-1:0] count; - - wire valid; - wire [3:0] wstrb; - wire [31:0] la_write; - - // WB MI A - assign valid = wbs_cyc_i && wbs_stb_i; - assign wstrb = wbs_sel_i & {4{wbs_we_i}}; - assign wbs_dat_o = rdata; - assign wdata = wbs_dat_i; - - // IO - assign io_out = count; - assign io_oeb = {(`MPRJ_IO_PADS-1){rst}}; - - // IRQ - assign irq = 3'b000; // Unused - - // LA - assign la_data_out = {{(127-BITS){1'b0}}, count}; - // Assuming LA probes [63:32] are for controlling the count register - assign la_write = ~la_oenb[63:32] & ~{BITS{valid}}; - // Assuming LA probes [65:64] are for controlling the count clk & reset - assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i; - assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i; - - counter #( - .BITS(BITS) - ) counter( - .clk(clk), - .reset(rst), - .ready(wbs_ack_o), - .valid(valid), - .rdata(rdata), - .wdata(wbs_dat_i), - .wstrb(wstrb), - .la_write(la_write), - .la_input(la_data_in[63:32]), - .count(count) - ); - + + wire [`MPRJ_IO_PADS-1:0] io_in; + wire [`MPRJ_IO_PADS-1:0] io_out; + wire [`MPRJ_IO_PADS-1:0] io_oeb; + + wire [1:0] mode = io_in[37:36]; + + + + Minx16Top cpu16 ( + .clk_i (io_in [33]) + , .rst_i (io_in [32]) + + , .dbus_ADBus_i(io_in [31:16]) + , .dbus_ADBus_o(io_out[31:16]) + , .dbus_ADBus_e(io_oeb[31:16]) + , .dbus_ale_o (io_out[15]) + , .dbus_ale_e (io_oeb[15]) + , .dbus_dle_o (io_out[14]) + , .dbus_dle_e (io_oeb[14]) + , .dbus_stb_o (io_out[13:12]) + , .dbus_stb_e (io_oeb[13:12]) + , .dbus_rd_o (io_out[11]) + , .dbus_rd_e (io_oeb[11]) + , .dbus_wr_o (io_out[10]) + , .dbus_wr_e (io_oeb[10]) + , .dbus_rdy_i (io_in [9]) + + , .dbus_req_i (io_in [8]) + , .dbus_ack_o (io_out[7]) + + , .intr_i (io_in [6]) + , .inta_o (io_out[5]) + , .nmir_i (io_in [34]) + , .nmia_o (io_out[35]) + ); + endmodule -module counter #( - parameter BITS = 32 -)( - input clk, - input reset, - input valid, - input [3:0] wstrb, - input [BITS-1:0] wdata, - input [BITS-1:0] la_write, - input [BITS-1:0] la_input, - output ready, - output [BITS-1:0] rdata, - output [BITS-1:0] count +(* blackbox *) +module Minx16Top ( + input clk_i +, input rst_i + +, input [15:0] dbus_ADBus_i +, output wire [15:0] dbus_ADBus_o +, output wire [15:0] dbus_ADBus_e +, output wire dbus_ale_o +, output wire dbus_ale_e +, output wire dbus_dle_o +, output wire dbus_dle_e +, output wire [ 1:0] dbus_stb_o +, output wire [ 1:0] dbus_stb_e +, output wire dbus_rd_o +, output wire dbus_rd_e +, output wire dbus_wr_o +, output wire dbus_wr_e +, input dbus_rdy_i + +, input dbus_req_i +, output wire dbus_ack_o + +, input intr_i +, output wire inta_o +, input nmir_i +, output wire nmia_o ); - reg ready; - reg [BITS-1:0] count; - reg [BITS-1:0] rdata; - - always @(posedge clk) begin - if (reset) begin - count <= 0; - ready <= 0; - end else begin - ready <= 1'b0; - if (~|la_write) begin - count <= count + 1; - end - if (valid && !ready) begin - ready <= 1'b1; - rdata <= count; - if (wstrb[0]) count[7:0] <= wdata[7:0]; - if (wstrb[1]) count[15:8] <= wdata[15:8]; - if (wstrb[2]) count[23:16] <= wdata[23:16]; - if (wstrb[3]) count[31:24] <= wdata[31:24]; - end else if (|la_write) begin - count <= la_write & la_input; - end - end - end endmodule + `default_nettype wire