├── Makefile ├── README.md ├── fpga └── Makefile ├── risc5top.bit ├── rtl ├── BRAM.v ├── DVI.v ├── Divider.v ├── FPAdder.v ├── FPDivider.v ├── FPMultiplier.v ├── LeftShifter.v ├── MousePM.v ├── Multiplier.v ├── PROM.v ├── PS2.v ├── PSRAM.v ├── RISC5.v ├── RISC5Top.v ├── RS232R.v ├── RS232T.v ├── Registers.v ├── RightShifter.v ├── SPI.v ├── VID.v ├── VRAM.v ├── cache_64k.v ├── encode.v ├── prom.mem └── serialiser_10_to_1.v ├── vivado.mk └── xdc └── a7_mtfb.xdc /Makefile: -------------------------------------------------------------------------------- 1 | # Targets 2 | TARGETS:= 3 | 4 | # Subdirectories 5 | SUBDIRS = fpga 6 | SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS)) 7 | 8 | # Rules 9 | .PHONY: all 10 | all: $(SUBDIRS) $(TARGETS) 11 | 12 | .PHONY: $(SUBDIRS) 13 | $(SUBDIRS): 14 | cd $@ && $(MAKE) 15 | 16 | .PHONY: $(SUBDIRS_CLEAN) 17 | $(SUBDIRS_CLEAN): 18 | cd $(@:.clean=) && $(MAKE) clean 19 | 20 | .PHONY: clean 21 | clean: $(SUBDIRS_CLEAN) 22 | -rm -rf $(TARGETS) 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISC5Verilog_psram -------------------------------------------------------------------------------- /fpga/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # FPGA settings 3 | FPGA_PART = xc7a50ticpg236-1L 4 | FPGA_TOP = risc5top 5 | FPGA_ARCH = Artix7 6 | 7 | # Files for synthesis 8 | SYN_FILES = rtl/RISC5Top.v 9 | SYN_FILES += rtl/BRAM.v 10 | SYN_FILES += rtl/cache_64k.v 11 | SYN_FILES += rtl/Divider.v 12 | SYN_FILES += rtl/DVI.v 13 | SYN_FILES += rtl/encode.v 14 | SYN_FILES += rtl/FPAdder.v 15 | SYN_FILES += rtl/FPDivider.v 16 | SYN_FILES += rtl/FPMultiplier.v 17 | SYN_FILES += rtl/LeftShifter.v 18 | SYN_FILES += rtl/MousePM.v 19 | SYN_FILES += rtl/Multiplier.v 20 | SYN_FILES += rtl/PROM.v 21 | SYN_FILES += rtl/PSRAM.v 22 | SYN_FILES += rtl/PS2.v 23 | SYN_FILES += rtl/Registers.v 24 | SYN_FILES += rtl/RightShifter.v 25 | SYN_FILES += rtl/RISC5.v 26 | SYN_FILES += rtl/RS232R.v 27 | SYN_FILES += rtl/RS232T.v 28 | SYN_FILES += rtl/serialiser_10_to_1.v 29 | SYN_FILES += rtl/SPI.v 30 | SYN_FILES += rtl/VID.v 31 | SYN_FILES += rtl/VRAM.v 32 | 33 | 34 | # XDC files 35 | XDC_FILES = xdc/a7_mtfb.xdc 36 | #XDC_FILES += xdc/clocks.xdc 37 | 38 | # IP 39 | XCI_FILES = 40 | 41 | ifeq ($(OS), Windows_NT) 42 | VIVADO = C:\Xilinx\Vivado\2017.2\bin\vivado 43 | else 44 | VIVADO = /opt/Xilinx/Vivado/2017.2/bin/vivado 45 | endif 46 | 47 | include ../vivado.mk 48 | 49 | 50 | -------------------------------------------------------------------------------- /risc5top.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saanlima/RISC5Verilog_psram/1ed039df2d6c6d3b3f173298a8a606c670a8fbb2/risc5top.bit -------------------------------------------------------------------------------- /rtl/BRAM.v: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Filename: BRAM.v 4 | // Description: 128 KB memory block in BRAM 5 | // Creation date: Jan 9, 2021 6 | // 7 | // Author: Magnus Karlsson 8 | // e-mail: magnus@saanlima.com 9 | // 10 | // 11 | ///////////////////////////////////////////////////////////////////////////////// 12 | // 13 | // Copyright (C) 2021 Magnus Karlsson 14 | // 15 | // This source file may be used and distributed without 16 | // restriction provided that this copyright statement is not 17 | // removed from the file and that any derivative work contains 18 | // the original copyright notice and the associated disclaimer. 19 | // 20 | // This source file is free software; you can redistribute it 21 | // and/or modify it under the terms of the GNU Lesser General 22 | // Public License as published by the Free Software Foundation; 23 | // either version 2.1 of the License, or (at your option) any 24 | // later version. 25 | // 26 | // This source is distributed in the hope that it will be 27 | // useful, but WITHOUT ANY WARRANTY; without even the implied 28 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 29 | // PURPOSE. See the GNU Lesser General Public License for more 30 | // details. 31 | // 32 | // You should have received a copy of the GNU Lesser General 33 | // Public License along with this source; if not, download it 34 | // from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 35 | // 36 | /////////////////////////////////////////////////////////////////////////////////// 37 | 38 | module BRAM ( 39 | input clka, 40 | input [14:0] adra, 41 | input [3:0] bea, 42 | input wea, 43 | input [31:0] wda, 44 | output [31:0] rda); 45 | 46 | wire [7:0] rda_0, rda_1, rda_2, rda_3; 47 | 48 | RAM8 ram8_0(.clka(clka), .adra(adra), .wea(wea & bea[0]), 49 | .wda(wda[7:0]), .rda(rda_0)); 50 | 51 | RAM8 ram8_1(.clka(clka), .adra(adra), .wea(wea & bea[1]), 52 | .wda(wda[15:8]), .rda(rda_1)); 53 | 54 | RAM8 ram8_2(.clka(clka), .adra(adra), .wea(wea & bea[2]), 55 | .wda(wda[23:16]), .rda(rda_2)); 56 | 57 | RAM8 ram8_3(.clka(clka), .adra(adra), .wea(wea & bea[3]), 58 | .wda(wda[31:24]), .rda(rda_3)); 59 | 60 | assign rda = {rda_3, rda_2, rda_1, rda_0}; 61 | 62 | endmodule 63 | 64 | 65 | module RAM8 ( 66 | input clka, 67 | input [14:0] adra, 68 | input wea, 69 | input [7:0] wda, 70 | output reg [7:0] rda); 71 | 72 | reg [7:0] ram [24575:0]; 73 | 74 | always @(posedge clka) begin 75 | rda <= ram[adra]; 76 | if(wea) begin 77 | rda <= wda; 78 | ram[adra] <= wda; 79 | end 80 | end 81 | 82 | endmodule 83 | -------------------------------------------------------------------------------- /rtl/DVI.v: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Filename: DVI.v 4 | // Description: VGA to DVI 5 | // Creation date: Jan 9, 2021 6 | // 7 | // Author: Magnus Karlsson 8 | // e-mail: magnus@saanlima.com 9 | // 10 | // 11 | ///////////////////////////////////////////////////////////////////////////////// 12 | // 13 | // Copyright (C) 2021 Magnus Karlsson 14 | // 15 | // This source file may be used and distributed without 16 | // restriction provided that this copyright statement is not 17 | // removed from the file and that any derivative work contains 18 | // the original copyright notice and the associated disclaimer. 19 | // 20 | // This source file is free software; you can redistribute it 21 | // and/or modify it under the terms of the GNU Lesser General 22 | // Public License as published by the Free Software Foundation; 23 | // either version 2.1 of the License, or (at your option) any 24 | // later version. 25 | // 26 | // This source is distributed in the hope that it will be 27 | // useful, but WITHOUT ANY WARRANTY; without even the implied 28 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 29 | // PURPOSE. See the GNU Lesser General Public License for more 30 | // details. 31 | // 32 | // You should have received a copy of the GNU Lesser General 33 | // Public License along with this source; if not, download it 34 | // from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 35 | // 36 | /////////////////////////////////////////////////////////////////////////////////// 37 | 38 | `timescale 1 ps / 1 ps 39 | 40 | module DVI ( 41 | input wire reset, 42 | input wire pll_reset, 43 | input wire clkx1, 44 | input wire clkx5, 45 | input wire [7:0] blue_in, 46 | input wire [7:0] green_in, 47 | input wire [7:0] red_in, 48 | input wire hsync, 49 | input wire vsync, 50 | input wire vde, 51 | output wire [3:0] TMDS, 52 | output wire [3:0] TMDSB 53 | ); 54 | 55 | wire [9:0] red; 56 | wire [9:0] green; 57 | wire [9:0] blue; 58 | wire [2:0] tmdsint; 59 | 60 | encode encb ( 61 | .clkin (clkx1), 62 | .rstin (reset), 63 | .din (blue_in), 64 | .c0 (hsync), 65 | .c1 (vsync), 66 | .de (vde), 67 | .dout (blue) 68 | ); 69 | 70 | encode encg ( 71 | .clkin (clkx1), 72 | .rstin (reset), 73 | .din (green_in), 74 | .c0 (1'b0), 75 | .c1 (1'b0), 76 | .de (vde), 77 | .dout (green) 78 | ); 79 | 80 | encode encr ( 81 | .clkin (clkx1), 82 | .rstin (reset), 83 | .din (red_in), 84 | .c0 (1'b0), 85 | .c1 (1'b0), 86 | .de (vde), 87 | .dout (red) 88 | ); 89 | 90 | serialiser_10_to_1 oserdes0 ( 91 | .clk_x1 (clkx1), 92 | .clk_x5 (clkx5), 93 | .reset (pll_reset), 94 | .din (blue), 95 | .serial (tmdsint[0]) 96 | ); 97 | 98 | serialiser_10_to_1 oserdes1 ( 99 | .clk_x1 (clkx1), 100 | .clk_x5 (clkx5), 101 | .reset (pll_reset), 102 | .din (green), 103 | .serial (tmdsint[1]) 104 | ); 105 | 106 | serialiser_10_to_1 oserdes2 ( 107 | .clk_x1 (clkx1), 108 | .clk_x5 (clkx5), 109 | .reset (pll_reset), 110 | .din (red), 111 | .serial (tmdsint[2]) 112 | ); 113 | 114 | serialiser_10_to_1 clkout ( 115 | .clk_x1 (clkx1), 116 | .clk_x5 (clkx5), 117 | .reset (pll_reset), 118 | .din (10'b0000011111), 119 | .serial (tmdsclk) 120 | ); 121 | 122 | OBUFDS TMDS0 (.I(tmdsint[0]), .O(TMDS[0]), .OB(TMDSB[0])); 123 | OBUFDS TMDS1 (.I(tmdsint[1]), .O(TMDS[1]), .OB(TMDSB[1])); 124 | OBUFDS TMDS2 (.I(tmdsint[2]), .O(TMDS[2]), .OB(TMDSB[2])); 125 | OBUFDS TMDS3 (.I(tmdsclk), .O(TMDS[3]), .OB(TMDSB[3])); 126 | 127 | endmodule 128 | -------------------------------------------------------------------------------- /rtl/Divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 20.9.2015 23 | 24 | module Divider( 25 | input clk, ce, run, u, 26 | output stall, 27 | input [31:0] x, y, // y > 0 28 | output [31:0] quot, rem); 29 | 30 | reg [5:0] S; // state 31 | reg [63:0] RQ; 32 | wire sign; 33 | wire [31:0] x0, w0, w1; 34 | 35 | assign stall = run & ~(S == 33); 36 | assign sign = x[31] & u; 37 | assign x0 = sign ? -x : x; 38 | assign w0 = RQ[62: 31]; 39 | assign w1 = w0 - y; 40 | assign quot = ~sign ? RQ[31:0] : 41 | (RQ[63:32] == 0) ? -RQ[31:0] : -RQ[31:0] - 1; 42 | assign rem = ~sign ? RQ[63:32] : 43 | (RQ[63:32] == 0) ? 0 : y - RQ[63:32]; 44 | 45 | always @ (posedge(clk)) if(ce) begin 46 | RQ <= (S == 0) ? {32'b0, x0} : {(w1[31] ? w0 : w1), RQ[30:0], ~w1[31]}; 47 | S <= run ? S+1 : 0; 48 | end 49 | endmodule 50 | -------------------------------------------------------------------------------- /rtl/FPAdder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 4.10.2016 pipelined 23 | // u = 1: FLT; v = 1: FLOOR 24 | 25 | module FPAdder( 26 | input clk, ce, run, u, v, 27 | input [31:0] x, y, 28 | output stall, 29 | output [31:0] z); 30 | 31 | reg [1:0] State; 32 | 33 | wire xs, ys, xn, yn; // signs 34 | wire [7:0] xe, ye; 35 | wire [24:0] xm, ym; 36 | 37 | wire [8:0] dx, dy, e0, e1; 38 | wire [7:0] sx, sy; // shift counts 39 | wire [1:0] sx0, sx1, sy0, sy1; 40 | wire sxh, syh; 41 | wire [24:0] x0, x1, x2, y0, y1, y2; 42 | reg [24:0] x3, y3; 43 | 44 | reg [26:0] Sum; 45 | wire [26:0] s; 46 | 47 | wire z24, z22, z20, z18, z16, z14, z12, z10, z8, z6, z4, z2; 48 | wire [4:0] sc; // shift count 49 | wire [1:0] sc0, sc1; 50 | wire [24:0] t1, t2; 51 | reg [24:0] t3; 52 | 53 | assign xs = x[31]; // sign x 54 | assign xe = u ? 8'h96 : x[30:23]; // expo x 55 | assign xm = {~u|x[23], x[22:0], 1'b0}; //mant x 56 | assign xn = (x[30:0] == 0); 57 | assign ys = y[31]; // sign y 58 | assign ye = y[30:23]; // expo y 59 | assign ym = {~u&~v, y[22:0], 1'b0}; //mant y 60 | assign yn = (y[30:0] == 0); 61 | 62 | assign dx = xe - ye; 63 | assign dy = ye - xe; 64 | assign e0 = (dx[8]) ? ye : xe; 65 | assign sx = dy[8] ? 0 : dy; 66 | assign sy = dx[8] ? 0 : dx; 67 | assign sx0 = sx[1:0]; 68 | assign sx1 = sx[3:2]; 69 | assign sy0 = sy[1:0]; 70 | assign sy1 = sy[3:2]; 71 | assign sxh = sx[7] | sx[6] | sx[5]; 72 | assign syh = sy[7] | sy[6] | sy[5]; 73 | 74 | // denormalize, shift right 75 | assign x0 = xs&~u ? -xm : xm; 76 | assign x1 = (sx0 == 3) ? {{3{xs}}, x0[24:3]} : 77 | (sx0 == 2) ? {{2{xs}}, x0[24:2]} : (sx0 == 1) ? {xs, x0[24:1]} : x0; 78 | assign x2 = (sx1 == 3) ? {{12{xs}}, x1[24:12]} : 79 | (sx1 == 2) ? {{8{xs}}, x1[24:8]} : (sx1 == 1) ? {{4{xs}}, x1[24:4]} : x1; 80 | always @ (posedge(clk)) if(ce) 81 | x3 <= sxh ? {25{xs}} : (sx[4] ? {{16{xs}}, x2[24:16]} : x2); 82 | 83 | assign y0 = ys&~u ? -ym : ym; 84 | assign y1 = (sy0 == 3) ? {{3{ys}}, y0[24:3]} : 85 | (sy0 == 2) ? {{2{ys}}, y0[24:2]} : (sy0 == 1) ? {ys, y0[24:1]} : y0; 86 | assign y2 = (sy1 == 3) ? {{12{ys}}, y1[24:12]} : 87 | (sy1 == 2) ? {{8{ys}}, y1[24:8]} : (sy1 == 1) ? {{4{ys}}, y1[24:4]} : y1; 88 | always @ (posedge(clk)) if(ce) 89 | y3 <= syh ? {25{ys}} : (sy[4] ? {{16{ys}}, y2[24:16]} : y2); 90 | 91 | // add 92 | always @ (posedge(clk)) if(ce) Sum <= {xs, xs, x3} + {ys, ys, y3}; 93 | assign s = (Sum[26] ? -Sum : Sum) + 1; 94 | 95 | // post-normalize 96 | assign z24 = ~s[25] & ~ s[24]; 97 | assign z22 = z24 & ~s[23] & ~s[22]; 98 | assign z20 = z22 & ~s[21] & ~s[20]; 99 | assign z18 = z20 & ~s[19] & ~s[18]; 100 | assign z16 = z18 & ~s[17] & ~s[16]; 101 | assign z14 = z16 & ~s[15] & ~s[14]; 102 | assign z12 = z14 & ~s[13] & ~s[12]; 103 | assign z10 = z12 & ~s[11] & ~s[10]; 104 | assign z8 = z10 & ~s[9] & ~s[8]; 105 | assign z6 = z8 & ~s[7] & ~s[6]; 106 | assign z4 = z6 & ~s[5] & ~s[4]; 107 | assign z2 = z4 & ~s[3] & ~s[2]; 108 | 109 | assign sc[4] = z10; // sc = shift count of post normalization 110 | assign sc[3] = z18 & (s[17] | s[16] | s[15] | s[14] | s[13] | s[12] | s[11] | s[10]) 111 | | z2; 112 | assign sc[2] = z22 & (s[21] | s[20] | s[19] | s[18]) 113 | | z14 & (s[13] | s[12] | s[11] | s[10]) 114 | | z6 & (s[5] | s[4] | s[3] | s[2]); 115 | assign sc[1] = z24 & (s[23] | s[22]) 116 | | z20 & (s[19] | s[18]) 117 | | z16 & (s[15] | s[14]) 118 | | z12 & (s[11] | s[10]) 119 | | z8 & (s[7] | s[6]) 120 | | z4 & (s[3] | s[2]); 121 | assign sc[0] = ~s[25] & s[24] 122 | | z24 & ~s[23] & s[22] 123 | | z22 & ~s[21] & s[20] 124 | | z20 & ~s[19] & s[18] 125 | | z18 & ~s[17] & s[16] 126 | | z16 & ~s[15] & s[14] 127 | | z14 & ~s[13] & s[12] 128 | | z12 & ~s[11] & s[10] 129 | | z10 & ~s[9] & s[8] 130 | | z8 & ~s[7] & s[6] 131 | | z6 & ~s[5] & s[4] 132 | | z4 & ~s[3] & s[2]; 133 | 134 | assign e1 = e0 - sc + 1; 135 | assign sc0 = sc[1:0]; 136 | assign sc1 = sc[3:2]; 137 | 138 | assign t1 = (sc0 == 3) ? {s[22:1], 3'b0} : 139 | (sc0 == 2) ? {s[23:1], 2'b0} : (sc0 == 1) ? {s[24:1], 1'b0} : s[25:1]; 140 | assign t2 = (sc1 == 3) ? {t1[12:0], 12'b0} : 141 | (sc1 == 2) ? {t1[16:0], 8'b0} : (sc1 == 1) ? {t1[20:0], 4'b0} : t1; 142 | always @ (posedge(clk)) if(ce) t3 <= sc[4] ? {t2[8:0], 16'b0} : t2; 143 | 144 | assign stall = run & ~(State == 3); 145 | always @ (posedge(clk)) if(ce) State <= run ? State + 1 : 0; 146 | 147 | assign z = v ? {{7{Sum[26]}}, Sum[25:1]} : // FLOOR 148 | xn ? (u|yn ? 0 : y) : // FLT or x = y = 0 149 | yn ? x : 150 | ((t3 == 0) | e1[8]) ? 0 : 151 | {Sum[26], e1[7:0], t3[23:1]}; 152 | endmodule 153 | -------------------------------------------------------------------------------- /rtl/FPDivider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 16.9.2016 23 | 24 | module FPDivider( 25 | input clk, ce, run, 26 | input [31:0] x, 27 | input [31:0] y, 28 | output stall, 29 | output [31:0] z); 30 | 31 | reg [4:0] S; // state 32 | reg [23:0] R; 33 | reg [25:0] Q; 34 | 35 | wire sign; 36 | wire [7:0] xe, ye; 37 | wire [8:0] e0, e1; 38 | wire [24:0] r0, r1, d; 39 | wire [25:0] q0; 40 | wire [24:0] z0, z1; 41 | 42 | assign sign = x[31]^y[31]; 43 | assign xe = x[30:23]; 44 | assign ye = y[30:23]; 45 | assign e0 = {1'b0, xe} - {1'b0, ye}; 46 | assign e1 = e0 + 126 + Q[25]; 47 | assign stall = run & ~(S == 26); 48 | 49 | assign r0 = (S == 0) ? {2'b01, x[22:0]} : {R, 1'b0}; 50 | assign r1 = d[24] ? r0 : d; 51 | assign d = r0 - {2'b01, y[22:0]}; 52 | assign q0 = (S == 0) ? 0 : Q; 53 | 54 | assign z0 = Q[25] ? Q[25:1] : Q[24:0]; 55 | assign z1 = z0 + 1; 56 | assign z = (xe == 0) ? 0 : 57 | (ye == 0) ? {sign, 8'b11111111, 23'b0} : // div by 0 58 | (~e1[8]) ? {sign, e1[7:0], z0[23:1]} : 59 | (~e1[7]) ? {sign, 8'b11111111, z0[23:1]} : 0; // NaN 60 | 61 | always @ (posedge(clk)) if(ce) begin 62 | R <= r1[23:0]; 63 | Q <= {q0[24:0], ~d[24]}; 64 | S <= run ? S+1 : 0; 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /rtl/FPMultiplier.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 15.9.2015 23 | module FPMultiplier( 24 | input clk, ce, run, 25 | input [31:0] x, y, 26 | output stall, 27 | output [31:0] z); 28 | 29 | reg [4:0] S; // state 30 | reg [47:0] P; // product 31 | 32 | wire sign; 33 | wire [7:0] xe, ye; 34 | wire [8:0] e0, e1; 35 | wire [24:0] w1, z0; 36 | wire [23:0] w0; 37 | 38 | assign sign = x[31] ^ y[31]; 39 | assign xe = x[30:23]; 40 | assign ye = y[30:23]; 41 | assign e0 = xe + ye; 42 | assign e1 = e0 - 127 + P[47]; 43 | 44 | assign stall = run & ~(S == 25); 45 | assign w0 = P[0] ? {1'b1, y[22:0]} : 0; 46 | assign w1 = {1'b0, P[47:24]} + {1'b0, w0}; 47 | assign z0 = P[47] ? P[47:23]+1 : P[46:22]+1; // round and normalize 48 | assign z = (xe == 0) | (ye == 0) ? 0 : 49 | (~e1[8]) ? {sign, e1[7:0], z0[23:1]} : 50 | (~e1[7]) ? {sign, 8'b11111111, z0[23:1]} : 0; 51 | always @ (posedge(clk)) if(ce) begin 52 | P <= (S == 0) ? {24'b0, 1'b1, x[22:0]} : {w1, P[23:1]}; 53 | S <= run ? S+1 : 0; 54 | end 55 | endmodule 56 | -------------------------------------------------------------------------------- /rtl/LeftShifter.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps // NW 9.11.2016 2 | 3 | module LeftShifter( 4 | input [31:0] x, 5 | input [4:0] sc, 6 | output [31:0] y); 7 | 8 | // shifter for LSL 9 | wire [1:0] sc0, sc1; 10 | wire [31:0] t1, t2; 11 | 12 | assign sc0 = sc[1:0]; 13 | assign sc1 = sc[3:2]; 14 | 15 | assign t1 = (sc0 == 3) ? {x[28:0], 3'b0} : 16 | (sc0 == 2) ? {x[29:0], 2'b0} : 17 | (sc0 == 1) ? {x[30:0], 1'b0} : x; 18 | assign t2 = (sc1 == 3) ? {t1[19:0], 12'b0} : 19 | (sc1 == 2) ? {t1[23:0], 8'b0} : 20 | (sc1 == 1) ? {t1[27:0], 4'b0} : t1; 21 | assign y = sc[4] ? {t2[15:0], 16'b0} : t2; 22 | endmodule -------------------------------------------------------------------------------- /rtl/MousePM.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // PS/2 mouse PDR 14.10.2013 / 03.09.2015 / 01.10.2015 23 | // with Microsoft 3rd (scroll) button init magic 24 | module MousePM( 25 | input wire clk, rst, 26 | inout wire msclk, msdat, 27 | output wire [27:0] out); 28 | 29 | reg [30:0] rx; 30 | reg [14:0] count; 31 | reg [9:0] filter, tx, x, y; 32 | reg [2:0] btns, sent; 33 | reg req; 34 | wire shift, endbit, endcount, done, run; 35 | wire [9:0] dx, dy; 36 | wire [8:0] cmd; //including odd tx parity bit 37 | 38 | // 322222222221111111111 (scroll mouse z and rx parity p ignored) 39 | // 0987654321098765432109876543210 X, Y = overflow 40 | // ------------------------------- s, t = x, y sign bits 41 | // yyyyyyyy01pxxxxxxxx01pYXts1MRL0 normal report 42 | // p--ack---0Ap--cmd---01111111111 cmd + ack bit (A) & byte 43 | 44 | assign run = (sent == 7); 45 | assign cmd = (sent == 0) ? 9'h0F4 : //enable reporting, rate 200,100,80 46 | (sent == 2) ? 9'h0C8 : (sent == 4) ? 9'h064 : (sent == 6) ? 9'h150 : 9'h1F3; 47 | assign endcount = (count[14:12] == 3'b111); // more than 11*100uS @25MHz 48 | assign shift = ~req & (filter == 10'b1); //low for 360nS @25MHz 49 | assign endbit = run ? ~rx[0] : ~rx[10]; 50 | assign done = endbit & endcount & ~req; 51 | assign dx = {{2{rx[5]}}, rx[7] ? 8'b0 : rx[19:12]}; //sign+overfl 52 | assign dy = {{2{rx[6]}}, rx[8] ? 8'b0 : rx[30:23]}; //sign+overfl 53 | // assign out = {run, // full debug 54 | // run ? {rx[25:0], endbit} : {rx[30:10], endbit, sent, tx[0], ~req}}; 55 | // assign out = {run, // debug then normal 56 | // run ? {btns, 2'b0, y, 2'b0, x} : {rx[30:10], sent, endbit, tx[0], ~req}}; 57 | assign out = {run, btns, 2'b0, y, 2'b0, x}; // normal 58 | assign msclk = req ? 1'b0 : 1'bz; //bidir clk/request 59 | assign msdat = ~tx[0] ? 1'b0 : 1'bz; //bidir data 60 | 61 | always @ (posedge clk) begin 62 | filter <= {msclk, filter[9:1]}; 63 | count <= (~rst | shift | endcount) ? 15'b0 : count+15'b1; 64 | req <= rst & ~run & (req ^ endcount); 65 | sent <= ~rst ? 3'b0 : sent + {2'b0, (done & ~run)} ; 66 | tx <= (~rst | run) ? 10'h3FF : req ? {cmd, 1'b0} : shift ? {1'b1, tx[9:1]} : tx; 67 | rx <= (~rst | done) ? 31'h7FFFFFFF : (shift & ~endbit) ? {msdat, rx[30:1]} : rx; 68 | x <= ~run ? 10'b0 : done ? x + dx : x; 69 | y <= ~run ? 10'b0 : done ? y + dy : y; 70 | btns <= ~run ? 3'b0 : done ? {rx[1], rx[3], rx[2]} : btns; 71 | end 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /rtl/Multiplier.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 14.9.2015 23 | 24 | module Multiplier( 25 | input clk, ce, run, u, 26 | output stall, 27 | input [31:0] x, y, 28 | output [63:0] z); 29 | 30 | reg [5:0] S; // state 31 | reg [63:0] P; // product 32 | wire [31:0] w0; 33 | wire [32:0] w1; 34 | 35 | assign stall = run & ~(S == 33); 36 | assign w0 = P[0] ? y : 0; 37 | assign w1 = (S == 32) & u ? {P[63], P[63:32]} - {w0[31], w0} : 38 | {P[63], P[63:32]} + {w0[31], w0}; 39 | assign z = P; 40 | 41 | always @ (posedge(clk)) if(ce) begin 42 | P <= (S == 0) ? {32'b0, x} : {w1[32:0], P[31:1]}; 43 | S <= run ? S+1 : 0; 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /rtl/PROM.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // 32-bit PROM initialised from hex file PDR 23.12.13 23 | 24 | module PROM (input clk, 25 | input [8:0] adr, 26 | output reg [31:0] data); 27 | 28 | reg [31:0] mem [511: 0]; 29 | initial $readmemh("prom.mem", mem); 30 | always @(posedge clk) data <= mem[adr]; 31 | 32 | endmodule 33 | 34 | -------------------------------------------------------------------------------- /rtl/PS2.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | // NW 20.10.2012 4 | // PS2 receiver for keyboard, 8 bit data 5 | // clock is 25 MHz; 25000 / 1302 = 19.2 KHz 6 | 7 | module PS2( 8 | input clk, rst, 9 | input done, // "byte has been read" 10 | output rdy, // "byte is available" 11 | output shift, // shift in, tramsmitter 12 | output [7:0] data, 13 | input PS2C, // serial input 14 | input PS2D); 15 | 16 | reg Q0, Q1; // synchronizer and falling edge detector 17 | reg [10:0] shreg; 18 | reg [3:0] inptr, outptr; 19 | reg [7:0] fifo [15:0]; // 16 byte buffer 20 | wire endbit; 21 | 22 | assign endbit = ~shreg[0]; //start bit reached correct pos 23 | assign shift = Q1 & ~Q0; 24 | assign data = fifo[outptr]; 25 | assign rdy = ~(inptr == outptr); 26 | 27 | always @ (posedge clk) begin 28 | Q0 <= PS2C; Q1 <= Q0; 29 | shreg <= (~rst | endbit) ? 11'h7FF : 30 | shift ? {PS2D, shreg[10:1]} : shreg; 31 | outptr <= ~rst ? 0 : rdy & done ? outptr+1 : outptr; 32 | inptr <= ~rst ? 0 : endbit ? inptr+1 : inptr; 33 | if (endbit) fifo[inptr] <= shreg[8:1]; 34 | end 35 | endmodule 36 | -------------------------------------------------------------------------------- /rtl/PSRAM.v: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Filename: PSRAM.v 4 | // Description: Memory controller for QSPI PSRAM 5 | // Reading and writing 64 byte cache lines 6 | // Creation date: Jan 9, 2021 7 | // 8 | // Author: Magnus Karlsson 9 | // e-mail: magnus@saanlima.com 10 | // 11 | // 12 | ///////////////////////////////////////////////////////////////////////////////// 13 | // 14 | // Copyright (C) 2021 Magnus Karlsson 15 | // 16 | // This source file may be used and distributed without 17 | // restriction provided that this copyright statement is not 18 | // removed from the file and that any derivative work contains 19 | // the original copyright notice and the associated disclaimer. 20 | // 21 | // This source file is free software; you can redistribute it 22 | // and/or modify it under the terms of the GNU Lesser General 23 | // Public License as published by the Free Software Foundation; 24 | // either version 2.1 of the License, or (at your option) any 25 | // later version. 26 | // 27 | // This source is distributed in the hope that it will be 28 | // useful, but WITHOUT ANY WARRANTY; without even the implied 29 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 30 | // PURPOSE. See the GNU Lesser General Public License for more 31 | // details. 32 | // 33 | // You should have received a copy of the GNU Lesser General 34 | // Public License along with this source; if not, download it 35 | // from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 36 | // 37 | /////////////////////////////////////////////////////////////////////////////////// 38 | 39 | module PSRAM ( 40 | input mem_clk, 41 | input reset, 42 | input mem_rd, // memory read request from cache 43 | input mem_wr, // memory write request from cache 44 | input [23:6] waddr, // memory write address 45 | input [23:6] raddr, // memory read address 46 | input [127:0] cache_rdata, // write data to memory 47 | output reg [127:0] cache_wdata, // read data from memory 48 | output reg cache_en, // cache enable 49 | output reg cache_we, // cache write 50 | output reg [1:0] cache_addr, // cache address 51 | output reg rd_busy, // memory controller busy read 52 | output reg wr_busy, // memory controller busy write 53 | output reg psram_ce, // psram chip enable 54 | output psram_sclk, // psram clock 55 | inout psram_sio0, // psram data bit 0 56 | inout psram_sio1, // psram data bit 1 57 | inout psram_sio2, // psram data bit 2 58 | inout psram_sio3, // psram data bit 3 59 | output reg [63:0] id_reg // result of id register read 60 | ); 61 | 62 | reg mem_wr_sync; 63 | reg mem_rd_sync; 64 | reg [4:0] state, next_state; 65 | reg [1:0] next_cache_addr; 66 | reg next_cache_en; 67 | reg next_cache_we; 68 | reg [127:0] next_cache_wdata; 69 | reg next_wr_busy; 70 | reg next_rd_busy; 71 | reg [13:0] pscnt, next_pscnt; 72 | reg next_psram_ce; 73 | reg psram_oe, next_psram_oe; 74 | reg [31:0] psram_data, next_psram_data; 75 | reg [6:0] psram_bitcnt, next_psram_bitcnt; 76 | reg [3:0] high_nybble, next_high_nybble; 77 | reg [63:0] next_id_reg; 78 | 79 | wire [3:0] psram_out; 80 | wire [3:0] psram_in; 81 | 82 | 83 | IOBUF buf_data0 (.IO(psram_sio0), .O(psram_in[0]), .I(psram_out[0]), .T(psram_oe)); 84 | IOBUF buf_data1 (.IO(psram_sio1), .O(psram_in[1]), .I(psram_out[1]), .T(psram_oe)); 85 | IOBUF buf_data2 (.IO(psram_sio2), .O(psram_in[2]), .I(psram_out[2]), .T(psram_oe)); 86 | IOBUF buf_data3 (.IO(psram_sio3), .O(psram_in[3]), .I(psram_out[3]), .T(psram_oe)); 87 | 88 | ODDR #( 89 | .DDR_CLK_EDGE("SAME_EDGE"), 90 | .INIT(1'b0), 91 | .SRTYPE("SYNC") 92 | ) clock_forward_inst ( 93 | .Q(psram_sclk), 94 | .C(mem_clk), 95 | .CE(1'b1), 96 | .D1(1'b1), 97 | .D2(1'b0), 98 | .R(1'b0), 99 | .S(1'b0) 100 | ); 101 | 102 | parameter [4:0] 103 | STARTUP = 5'd0, 104 | INIT1 = 5'd1, 105 | INIT2 = 5'd2, 106 | INIT3 = 5'd3, 107 | INIT4 = 5'd4, 108 | INIT5 = 5'd5, 109 | INIT6 = 5'd6, 110 | INIT7 = 5'd7, 111 | INIT8 = 5'd8, 112 | INIT9 = 5'd9, 113 | INIT10 = 5'd10, 114 | INIT11 = 5'd11, 115 | INIT12 = 5'd12, 116 | INIT13 = 5'd13, 117 | IDLE = 5'd14, 118 | READ1 = 5'd15, 119 | READ2 = 5'd16, 120 | READ3 = 5'd17, 121 | WRITE1 = 5'd18, 122 | WRITE2 = 5'd19; 123 | 124 | assign psram_out = psram_data[31:28]; 125 | 126 | always @ (negedge mem_clk) begin 127 | if (reset) begin 128 | mem_wr_sync <= 1'b0; 129 | mem_rd_sync <= 1'b0; 130 | state <= STARTUP; 131 | cache_addr <= 2'd0; 132 | cache_en <= 1'b0; 133 | cache_wdata <= 128'd0; 134 | cache_we <= 1'b0; 135 | wr_busy <= 1'b0; 136 | rd_busy <= 1'b0; 137 | pscnt <= 14'd0; 138 | psram_ce <= 1'b1; 139 | psram_oe <= 1'b1; 140 | psram_data <= 32'd0; 141 | psram_bitcnt <= 7'd0; 142 | high_nybble <= 4'd0; 143 | id_reg <= 64'd0; 144 | end else begin 145 | mem_wr_sync <= mem_wr; 146 | mem_rd_sync <= mem_rd; 147 | state <= next_state; 148 | cache_addr <= next_cache_addr; 149 | cache_en <= next_cache_en; 150 | cache_wdata <= next_cache_wdata; 151 | cache_we <= next_cache_we; 152 | wr_busy <= next_wr_busy; 153 | rd_busy <= next_rd_busy; 154 | pscnt <= next_pscnt; 155 | psram_ce <= next_psram_ce; 156 | psram_oe <= next_psram_oe; 157 | psram_data <= next_psram_data; 158 | psram_bitcnt <= next_psram_bitcnt; 159 | high_nybble <= next_high_nybble; 160 | id_reg <= next_id_reg; 161 | end 162 | end 163 | 164 | always @* begin 165 | next_state = state; 166 | next_cache_addr = cache_en ? cache_addr + 1'b1 : cache_addr; 167 | next_cache_wdata = cache_wdata; 168 | next_cache_en = 1'b0; 169 | next_cache_we = 1'b0; 170 | next_wr_busy = wr_busy; 171 | next_rd_busy = rd_busy; 172 | next_pscnt = pscnt; 173 | next_psram_ce = psram_ce; 174 | next_psram_oe = psram_oe; 175 | next_psram_data = psram_data; 176 | next_psram_bitcnt = psram_bitcnt; 177 | next_high_nybble = high_nybble; 178 | next_id_reg = id_reg; 179 | case(state) 180 | STARTUP: begin 181 | next_wr_busy = 1'b0; 182 | next_rd_busy = 1'b0; 183 | next_psram_ce = 1'b1; 184 | next_psram_oe = 1'b1; 185 | next_psram_data = 32'd0; 186 | next_pscnt = pscnt + 1'b1; 187 | if (pscnt == 14'd16383) 188 | next_state = INIT1; 189 | end 190 | INIT1: begin 191 | next_psram_ce = 1'b0; 192 | next_psram_oe = 1'b0; 193 | next_psram_data = 32'h01100110; // reset command 1 (0x66) 194 | next_psram_bitcnt = 7'd0; 195 | next_state = INIT2; 196 | end 197 | INIT2: begin 198 | next_psram_data = {psram_data[27:0], 4'd0}; 199 | next_psram_bitcnt = psram_bitcnt + 1'b1; 200 | if (psram_bitcnt[2:0] == 3'd7) begin 201 | next_psram_ce = 1'b1; 202 | next_psram_oe = 1'b1; 203 | next_state = INIT3; 204 | end 205 | end 206 | INIT3: begin 207 | next_state = INIT4; 208 | end 209 | INIT4: begin 210 | next_psram_ce = 1'b0; 211 | next_psram_oe = 1'b0; 212 | next_psram_data = 32'h10011001; // reset command 2 (0x99) 213 | next_psram_bitcnt = 7'd0; 214 | next_state = INIT5; 215 | end 216 | INIT5: begin 217 | next_psram_data = {psram_data[27:0], 4'd0}; 218 | next_psram_bitcnt = psram_bitcnt + 1'b1; 219 | if (psram_bitcnt[2:0] == 3'd7) begin 220 | next_psram_ce = 1'b1; 221 | next_psram_oe = 1'b1; 222 | next_state = INIT6; 223 | end 224 | end 225 | INIT6: begin 226 | next_state = INIT7; 227 | end 228 | INIT7: begin 229 | next_psram_ce = 1'b0; 230 | next_psram_oe = 1'b0; 231 | next_psram_data = 32'h10011111; // read ID command (0x9F) 232 | next_psram_bitcnt = 7'd0; 233 | next_state = INIT8; 234 | end 235 | INIT8: begin 236 | next_psram_data = {psram_data[27:0], 4'd0}; 237 | next_psram_bitcnt = psram_bitcnt + 1'b1; 238 | if (psram_bitcnt[4:0] == 5'd31) begin 239 | next_psram_oe = 1'b1; 240 | next_psram_bitcnt = 7'd0; 241 | next_id_reg = 64'd0; 242 | next_state = INIT9; 243 | end 244 | end 245 | INIT9: begin 246 | next_id_reg = {id_reg[62:0], psram_in[1]}; 247 | next_psram_bitcnt = psram_bitcnt + 1'b1; 248 | if (psram_bitcnt == 7'd63) begin 249 | next_psram_ce = 1'b1; 250 | next_psram_bitcnt = 7'd0; 251 | next_state = INIT10; 252 | end 253 | end 254 | INIT10: begin 255 | next_state = INIT11; 256 | end 257 | INIT11: begin 258 | next_psram_ce = 1'b0; 259 | next_psram_oe = 1'b0; 260 | next_psram_data = 32'h00110101; // enter Quad mode (0x35) 261 | next_psram_bitcnt = 7'd0; 262 | next_state = INIT12; 263 | end 264 | INIT12: begin 265 | next_psram_data = {psram_data[27:0], 4'd0}; 266 | next_psram_bitcnt = psram_bitcnt + 1'b1; 267 | if (psram_bitcnt[2:0] == 3'd7) begin 268 | next_psram_ce = 1'b1; 269 | next_psram_oe = 1'b1; 270 | next_state = INIT13; 271 | end 272 | end 273 | INIT13: begin 274 | next_state = IDLE; 275 | end 276 | IDLE: begin 277 | next_wr_busy = 1'b0; 278 | next_rd_busy = 1'b0; 279 | next_psram_bitcnt = 7'd0; 280 | next_cache_addr = 2'd0; 281 | if (mem_wr_sync) begin 282 | next_wr_busy = 1'b1; 283 | next_cache_en = 1'b1; 284 | next_psram_ce = 1'b0; 285 | next_psram_oe = 1'b0; 286 | next_psram_data = {8'h38, waddr, 6'd0}; // Quad write command (0x38 + address) 287 | next_state = WRITE1; 288 | end else if (mem_rd_sync) begin 289 | next_rd_busy = 1'b1; 290 | next_psram_ce = 1'b0; 291 | next_psram_oe = 1'b0; 292 | next_psram_data = {8'heb, raddr, 6'd0}; // Quad read command (0xEB + address) 293 | next_state = READ1; 294 | end 295 | end 296 | READ1: begin 297 | next_psram_data = {psram_data[27:0], 4'd0}; 298 | next_psram_bitcnt = psram_bitcnt + 1'b1; 299 | if (psram_bitcnt[2:0] == 3'd7) begin 300 | next_psram_bitcnt = 7'd0; 301 | next_psram_oe = 1'b1; 302 | next_state = READ2; 303 | end 304 | end 305 | READ2: begin 306 | next_psram_bitcnt = psram_bitcnt + 1'b1; 307 | if (psram_bitcnt[2:0] == 3'd5) begin 308 | next_psram_bitcnt = 7'd0; 309 | next_state = READ3; 310 | end 311 | end 312 | READ3: begin 313 | if (psram_bitcnt[0]) 314 | next_cache_wdata = {high_nybble, psram_in, cache_wdata[127:8]}; 315 | else 316 | next_high_nybble = psram_in; 317 | next_psram_bitcnt = psram_bitcnt + 1'b1; 318 | if (psram_bitcnt[4:0] == 5'd31) begin 319 | next_cache_en = 1'b1; 320 | next_cache_we = 1'b1; 321 | end 322 | if (psram_bitcnt == 7'd127) begin 323 | next_psram_ce = 1'b1; 324 | next_psram_bitcnt = 7'd0; 325 | next_state = INIT13; 326 | end 327 | end 328 | 329 | WRITE1: begin 330 | next_psram_bitcnt = psram_bitcnt + 1'b1; 331 | if (psram_bitcnt[2:0] == 3'd7) begin 332 | next_psram_data = {cache_rdata[7:0], cache_rdata[15:8], cache_rdata[23:16], cache_rdata[31:24]}; 333 | next_psram_bitcnt = 7'd0; 334 | next_state = WRITE2; 335 | end else begin 336 | next_psram_data = {psram_data[27:0], 4'd0}; 337 | end 338 | end 339 | WRITE2: begin 340 | next_psram_bitcnt = psram_bitcnt + 1'b1; 341 | if (psram_bitcnt == 7'd127) begin 342 | next_psram_ce = 1'b1; 343 | next_psram_oe = 1'b1; 344 | next_state = INIT13; 345 | end else begin 346 | if (psram_bitcnt[2:0] < 3'd7) 347 | next_psram_data = {psram_data[27:0], 4'd0}; 348 | else if (psram_bitcnt[4:3] == 2'b00) 349 | next_psram_data = {cache_rdata[39:32], cache_rdata[47:40], cache_rdata[55:48], cache_rdata[63:56]}; 350 | else if (psram_bitcnt[4:3] == 2'b01) 351 | next_psram_data = {cache_rdata[71:64], cache_rdata[79:72], cache_rdata[87:80], cache_rdata[95:88]}; 352 | else if (psram_bitcnt[4:3] == 2'b10) begin 353 | next_psram_data = {cache_rdata[103:96], cache_rdata[111:104], cache_rdata[119:112], cache_rdata[127:120]}; 354 | if (psram_bitcnt[6:5] < 2'd3) 355 | next_cache_en = 1'b1; 356 | end else 357 | next_psram_data = {cache_rdata[7:0], cache_rdata[15:8], cache_rdata[23:16], cache_rdata[31:24]}; 358 | end 359 | end 360 | endcase 361 | end 362 | 363 | endmodule 364 | -------------------------------------------------------------------------------- /rtl/RISC5.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 31.8.2018 23 | // Modified for SDRAM - Nicolae Dumitrache 2016 - added clock enable 24 | 25 | module RISC5( 26 | input clk, rst, irq, stallX, ce, 27 | input [31:0] inbus, codebus, 28 | output [23:0] adr, 29 | output rd, wr, ben, 30 | output [31:0] outbus); 31 | 32 | localparam StartAdr = 22'h3FF800; // ROM 33 | 34 | reg [21:0] PC; 35 | reg [31:0] IR; // instruction register 36 | reg N, Z, C, OV; // condition flags 37 | reg [31:0] H; // aux register 38 | reg stallL1; 39 | 40 | wire [21:0] pcmux, pcmux0, nxpc; 41 | wire cond, S; 42 | wire sa, sb, sc; 43 | 44 | wire p, q, u, v; // instruction fields 45 | wire [3:0] op, ira, ira0, irb, irc; 46 | wire [2:0] cc; 47 | wire [15:0] imm; 48 | wire [19:0] off; 49 | wire [21:0] disp; 50 | 51 | wire regwr; 52 | wire stall, stallL0, stallM, stallD, stallFA, stallFM, stallFD; 53 | wire nn, zz, cx, vv; 54 | 55 | reg irq1, intEnb, intPnd, intMd; 56 | reg [25:0] SPC; // saved PC on interrupt 57 | wire intAck; 58 | 59 | wire [31:0] A, B, C0, C1, aluRes, regmux, inbus1; 60 | wire [31:0] lshout, rshout; 61 | wire [31:0] quotient, remainder; 62 | wire [63:0] product; 63 | wire [31:0] fsum, fprod, fquot; 64 | 65 | wire ADD, SUB, MUL, DIV; 66 | wire FAD, FSB, FML, FDV; 67 | wire LDR, STR, BR, RTI; 68 | 69 | Registers regs (.clk(clk), .wr(regwr), .ce(ce), .rno0(ira0), .rno1(irb), 70 | .rno2(irc), .din(regmux), .dout0(A), .dout1(B), .dout2(C0)); 71 | 72 | Multiplier mulUnit (.clk(clk), .ce(ce), .run(MUL), .stall(stallM), 73 | .u(~u), .x(B), .y(C1), .z(product)); 74 | 75 | Divider divUnit (.clk(clk), .ce(ce), .run(DIV), .stall(stallD), 76 | .u(~u), .x(B), .y(C1), .quot(quotient), .rem(remainder)); 77 | 78 | LeftShifter LSUnit (.x(B), .y(lshout), .sc(C1[4:0])); 79 | 80 | RightShifter RSUnit(.x(B), .y(rshout), .sc(C1[4:0]), .md(IR[16])); 81 | 82 | FPAdder fpaddx (.clk(clk), .ce(ce), .run(FAD|FSB), .u(u), .v(v), .stall(stallFA), 83 | .x(B), .y({FSB^C0[31], C0[30:0]}), .z(fsum)); 84 | 85 | FPMultiplier fpmulx (.clk(clk), .ce(ce), .run(FML), .stall(stallFM), 86 | .x(B), .y(C0), .z(fprod)); 87 | 88 | FPDivider fpdivx (.clk(clk), .ce(ce), .run(FDV), .stall(stallFD), 89 | .x(B), .y(C0), .z(fquot)); 90 | 91 | assign p = IR[31]; 92 | assign q = IR[30]; 93 | assign u = IR[29]; 94 | assign v = IR[28]; 95 | assign cc = IR[26:24]; 96 | assign ira = IR[27:24]; 97 | assign irb = IR[23:20]; 98 | assign op = IR[19:16]; 99 | assign irc = IR[3:0]; 100 | assign imm = IR[15:0]; // reg instr. 101 | assign off = IR[19:0]; // mem instr. 102 | assign disp = IR[21:0]; // branch instr. 103 | 104 | assign ADD = ~p & (op == 8); 105 | assign SUB = ~p & (op == 9); 106 | assign MUL = ~p & (op == 10); 107 | assign DIV = ~p & (op == 11); 108 | 109 | assign FAD = ~p & (op == 12); 110 | assign FSB = ~p & (op == 13); 111 | assign FML = ~p & (op == 14); 112 | assign FDV = ~p & (op == 15); 113 | 114 | assign LDR = p & ~q & ~u; 115 | assign STR = p & ~q & u; 116 | assign BR = p & q; 117 | assign RTI = BR & ~u & ~v & IR[4]; 118 | 119 | // Arithmetic-logical unit (ALU) 120 | assign ira0 = BR ? 15 : ira; 121 | assign C1 = q ? {{16{v}}, imm} : C0; 122 | assign adr = stallL0 ? B[23:0] + {{4{off[19]}}, off} : {pcmux, 2'b00}; 123 | assign rd = LDR & ~stallX & ~stallL1; 124 | assign wr = STR & ~stallX & ~stallL1; 125 | assign ben = p & ~q & v & ~stallX & ~stallL1; // byte enable 126 | 127 | assign aluRes = 128 | ~op[3] ? 129 | (~op[2] ? 130 | (~op[1] ? 131 | (~op[0] ? 132 | (q ? // MOV 133 | (~u ? {{16{v}}, imm} : {imm, 16'b0}) : 134 | (~u ? C0 : (~v ? H : {N, Z, C, OV, 20'b0, 8'h53}))) : 135 | lshout) : // LSL 136 | rshout) : // ASR, ROR 137 | (~op[1] ? 138 | (~op[0] ? B & C1 : B & ~C1) : // AND, ANN 139 | (~op[0] ? B | C1 : B ^ C1))) : // IOR. XOR 140 | (~op[2] ? 141 | (~op[1] ? 142 | (~op[0] ? B + C1 + (u&C) : B - C1 - (u&C)) : // ADD, SUB 143 | (~op[0] ? product[31:0] : quotient)) : // MUL, DIV 144 | (~op[1] ? // flt.pt. 145 | fsum : 146 | (~op[0] ? fprod : fquot))); 147 | 148 | assign regwr = ~p & ~stall | (LDR & ~stallX & ~stallL1) | (BR & cond & v & ~stallX); 149 | assign inbus1 = ~ben ? inbus : 150 | {24'b0, (adr[1] ? (adr[0] ? inbus[31:24] : inbus[23:16]) : 151 | (adr[0] ? inbus[15:8] : inbus[7:0]))}; 152 | assign regmux = LDR ? inbus1 : (BR & v) ? {8'b0, nxpc, 2'b0} : aluRes; 153 | assign outbus = ~ben ? A : 154 | adr[1] ? (adr[0] ? {A[7:0], 24'b0} : {8'b0, A[7:0], 16'b0}) : 155 | (adr[0] ? {16'b0, A[7:0], 8'b0} : {24'b0, A[7:0]}); 156 | 157 | // Control unit CU 158 | assign S = N ^ OV; 159 | assign nxpc = PC + 1; 160 | assign cond = IR[27] ^ 161 | ((cc == 0) & N | // MI, PL 162 | (cc == 1) & Z | // EQ, NE 163 | (cc == 2) & C | // CS, CC 164 | (cc == 3) & OV | // VS, VC 165 | (cc == 4) & (C|Z) | // LS, HI 166 | (cc == 5) & S | // LT, GE 167 | (cc == 6) & (S|Z) | // LE, GT 168 | (cc == 7)); // T, F 169 | 170 | assign intAck = intPnd & intEnb & ~intMd & ~stall; 171 | assign pcmux = ~rst | stall | intAck | RTI ? 172 | (~rst | stall ? (~rst ? StartAdr : PC) : 173 | (intAck ? 1 : SPC)) : pcmux0; 174 | assign pcmux0 = (BR & cond) ? (u? nxpc + disp : C0[23:2]) : nxpc; 175 | 176 | assign sa = aluRes[31]; 177 | assign sb = B[31]; 178 | assign sc = C1[31]; 179 | 180 | assign nn = RTI ? SPC[25] : regwr ? regmux[31] : N; 181 | assign zz = RTI ? SPC[24] : regwr ? (regmux == 0) : Z; 182 | assign cx = RTI ? SPC[23] : 183 | ADD ? (~sb&sc&~sa) | (sb&sc&sa) | (sb&~sa) : 184 | SUB ? (~sb&sc&~sa) | (sb&sc&sa) | (~sb&sa) : C; 185 | assign vv = RTI ? SPC[22] : 186 | ADD ? (sa&~sb&~sc) | (~sa&sb&sc): 187 | SUB ? (sa&~sb&sc) | (~sa&sb&~sc) : OV; 188 | 189 | assign stallL0 = (LDR|STR) & ~stallL1; 190 | assign stall = stallL0 | stallM | stallD | stallX | stallFA | stallFM | stallFD; 191 | 192 | always @ (posedge clk) if(ce) begin 193 | PC <= pcmux; 194 | IR <= stall ? IR : codebus; 195 | stallL1 <= stallX ? stallL1 : stallL0; 196 | N <= nn; Z <= zz; C <= cx; OV <= vv; 197 | H <= MUL ? product[63:32] : DIV ? remainder : H; 198 | 199 | irq1 <= irq; // edge detector 200 | intPnd <= rst & ~intAck & ((~irq1 & irq) | intPnd); 201 | intMd <= rst & ~RTI & (intAck | intMd); 202 | intEnb <= ~rst ? 0 : (BR & ~u & ~v & IR[5]) ? IR[0] : intEnb; 203 | SPC <= (intAck) ? {nn, zz, cx, vv, pcmux0} : SPC; 204 | end 205 | 206 | `ifdef XILINX_ISIM 207 | initial begin stall1 <= 0; R[15] <= 0; 208 | end 209 | `endif 210 | 211 | endmodule 212 | -------------------------------------------------------------------------------- /rtl/RISC5Top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps // 22.9.2015 2 | // with SRAM, byte access, flt.-pt., and gpio 3 | // PS/2 mouse and network 7.1.2014 PDR 4 | 5 | module RISC5Top( 6 | input sys_clk, 7 | input SWITCH, 8 | input RxD, 9 | output TxD, 10 | input [1:0] MISO, 11 | output [1:0] SCLK, MOSI, 12 | output [1:0] SS, 13 | output NEN, 14 | output [3:0] TMDS, 15 | output [3:0] TMDSB, 16 | input PS2C, PS2D, // keyboard 17 | inout msclk, msdat, // mouse 18 | output LED1, 19 | output LED2, 20 | output LED5, 21 | input [3:0] swi, 22 | output [7:0] leds, 23 | inout [7:0] gpio, 24 | output psram_ce, 25 | output psram_sclk, 26 | inout psram_sio0, 27 | inout psram_sio1, 28 | inout psram_sio2, 29 | inout psram_sio3 30 | ); 31 | 32 | // IO addresses for input / output 33 | // 0 milliseconds / -- 34 | // 1 switches / LEDs 35 | // 2 RS-232 data / RS-232 data (start) 36 | // 3 RS-232 status / RS-232 control 37 | // 4 SPI data / SPI data (start) 38 | // 5 SPI status / SPI control 39 | // 6 PS2 keyboard / -- 40 | // 7 mouse / -- 41 | // 8 general-purpose I/O data 42 | // 9 general-purpose I/O tri-state control 43 | 44 | wire [3:0] btn = {SWITCH, 3'b000}; 45 | 46 | wire[23:0] adr; 47 | wire [3:0] iowadr; // word address 48 | wire [31:0] inbus, inbus0; // data to RISC core 49 | wire [31:0] outbus; // data from RISC core 50 | wire [31:0] romout, codebus; // code to RISC core 51 | wire rd, wr, ben, ioenb; 52 | 53 | wire [7:0] dataTx, dataRx, dataKbd; 54 | wire rdyRx, doneRx, startTx, rdyTx, rdyKbd, doneKbd; 55 | wire [27:0] dataMs; 56 | reg bitrate; // for RS232 57 | wire limit; // of cnt0 58 | 59 | reg [7:0] Lreg; 60 | reg [15:0] cnt0; 61 | reg [31:0] cnt1; // milliseconds 62 | 63 | wire [31:0] spiRx; 64 | wire spiStart, spiRdy; 65 | reg [3:0] spiCtrl; 66 | 67 | reg [23:0] display; 68 | wire [23:0] vram_base; 69 | wire vram_access; 70 | wire [31:0] vram_rdata; 71 | 72 | wire [14:0] vidadr; 73 | wire [31:0] viddata; 74 | 75 | wire bram_access; 76 | wire mreq; 77 | 78 | reg [7:0] gpout, gpoc; 79 | wire [7:0] gpin; 80 | 81 | wire [2:0] RGB; 82 | wire hsync, vsync, vde; 83 | 84 | wire clkfbout, pllclk0, pllclk1, pllclk2, pllclk3; 85 | wire pll_locked; 86 | wire clk, pclk, pclkx5, mem_clk; 87 | reg rst; 88 | wire [3:0] ram_be; 89 | 90 | wire [31:0] cache_out, bram_out; 91 | wire [127:0] cache_rdata, cache_wdata; 92 | wire [23:6] waddr, raddr; 93 | wire mem_rd, mem_wr; 94 | wire cache_en; 95 | wire cache_we; 96 | wire [1:0] cache_addr; 97 | wire wr_busy, rd_busy; 98 | wire [63:0] id_reg; 99 | 100 | MMCME2_BASE #( 101 | .BANDWIDTH("OPTIMIZED"), 102 | .CLKIN1_PERIOD(31.25), 103 | .CLKFBOUT_MULT_F(25.0), 104 | .CLKOUT0_DIVIDE_F(16.0) 105 | ) MMCME2_pre_inst( 106 | .CLKOUT0(clk50), 107 | .CLKFBOUT(fbout), 108 | .LOCKED(locked), 109 | .CLKIN1(sys_clk), 110 | .PWRDWN(1'b0), 111 | .RST(1'b0), 112 | .CLKFBIN(fbout) 113 | ); 114 | 115 | MMCME2_BASE #( 116 | .BANDWIDTH("OPTIMIZED"), 117 | .CLKIN1_PERIOD(20.0), 118 | .CLKFBOUT_MULT_F(15.0), 119 | .CLKOUT0_DIVIDE_F(10.0), 120 | .CLKOUT1_DIVIDE(2), 121 | .CLKOUT2_DIVIDE(10), 122 | .CLKOUT3_DIVIDE(30) 123 | ) MMCME2_BASE_inst( 124 | .CLKOUT0(pllclk0), // 75 MHz 125 | .CLKOUT1(pllclk1), // 375 MHz 126 | .CLKOUT2(pllclk2), // 75 MHz 127 | .CLKOUT3(pllclk3), // 25 MHz 128 | .CLKFBOUT(clkfbout), 129 | .LOCKED(pll_locked), 130 | .CLKIN1(clk50), 131 | .PWRDWN(1'b0), 132 | .RST(1'b0), 133 | .CLKFBIN(clkfbout) 134 | ); 135 | 136 | BUFG pclkx5bufg (.I(pllclk1), .O(pclkx5)); 137 | BUFG pclkbufg (.I(pllclk2), .O(pclk)); 138 | BUFG clk25buf(.I(pllclk3), .O(clk)); 139 | BUFG clk100buf(.I(pllclk0), .O(mem_clk)); 140 | 141 | RISC5 riscx(.clk(clk), .rst(rst), .ce(ce), .irq(limit), 142 | .rd(rd), .wr(wr), .ben(ben), .stallX(1'b0), 143 | .adr(adr), .codebus(codebus), .inbus(inbus), 144 | .outbus(outbus)); 145 | 146 | PROM PM (.adr(adr[10:2]), .data(romout), .clk(~clk)); 147 | 148 | RS232R receiver(.clk(clk), .rst(rst), .RxD(RxD), .fsel(bitrate), .done(doneRx), 149 | .data(dataRx), .rdy(rdyRx)); 150 | 151 | RS232T transmitter(.clk(clk), .rst(rst), .start(startTx), .fsel(bitrate), 152 | .data(dataTx), .TxD(TxD), .rdy(rdyTx)); 153 | 154 | SPI spi(.clk(clk), .rst(rst), .start(spiStart), .dataTx(outbus), 155 | .fast(spiCtrl[2]), .dataRx(spiRx), .rdy(spiRdy), 156 | .SCLK(SCLK[0]), .MOSI(MOSI[0]), .MISO(MISO[0] & MISO[1])); 157 | 158 | VID vid(.pclk(pclk), .clk(clk), .req(), .inv(swi[3]), .vidadr(vidadr), 159 | .viddata(viddata), .RGB(RGB), .hsync(hsync), .vsync(vsync), .vde(vde)); 160 | 161 | PS2 kbd(.clk(clk), .rst(rst), .done(doneKbd), .rdy(rdyKbd), .shift(), 162 | .data(dataKbd), .PS2C(PS2C), .PS2D(PS2D)); 163 | 164 | MousePM Ms(.clk(clk), .rst(rst), .msclk(msclk), .msdat(msdat), .out(dataMs)); 165 | 166 | DVI dvi(.clkx1(pclk), .clkx5(pclkx5), .pll_reset(~pll_locked), 167 | .reset(~pll_locked), .red_in({8{RGB[2]}}), .green_in({8{RGB[1]}}), .blue_in({8{RGB[0]}}), 168 | .hsync(hsync), .vsync(vsync), .vde(vde), .TMDS(TMDS), .TMDSB(TMDSB)); 169 | 170 | VRAM vram(.clka(~clk), .adra(vram_base[16:2]), .bea(ram_be), .wea(wr & vram_access), 171 | .wda(outbus), .rda(vram_rdata), .clkb(~clk), .adrb(vidadr), 172 | .rdb(viddata)); 173 | 174 | BRAM bram(.clka(~clk), .adra(adr[16:2]), .bea(ram_be), .wea(wr & bram_access), 175 | .wda(outbus), .rda(bram_out)); 176 | 177 | assign inbus0 = bram_access ? bram_out : cache_out; 178 | assign codebus = adr[23:12] == 12'hFFE ? romout : inbus0; 179 | assign iowadr = adr[5:2]; 180 | assign ioenb = (adr[23:6] == 18'h3FFFF); 181 | assign vram_base = adr[23:0] - display; 182 | assign vram_access = (vram_base[23:17] == 7'h0) & 183 | ((vram_base[16] == 1'b0) | (vram_base[15] == 1'b0)); 184 | assign bram_access = (adr[23:17] == 7'h0); 185 | assign mreq = (adr[23] != 1'b1) & ~vram_access & ~bram_access; 186 | 187 | assign inbus = (~ioenb & ~vram_access) ? codebus : (~ioenb & vram_access ? vram_rdata : 188 | ((iowadr == 0) ? cnt1 : 189 | (iowadr == 1) ? {20'b0, btn, swi[3], 4'b0, swi[2:0]} : 190 | (iowadr == 2) ? {24'b0, dataRx} : 191 | (iowadr == 3) ? {30'b0, rdyTx, rdyRx} : 192 | (iowadr == 4) ? spiRx : 193 | (iowadr == 5) ? {31'b0, spiRdy} : 194 | (iowadr == 6) ? {3'b0, rdyKbd, dataMs} : 195 | (iowadr == 7) ? {24'b0, dataKbd} : 196 | (iowadr == 8) ? {24'b0, gpin} : 197 | (iowadr == 9) ? {24'b0, gpoc} : 198 | (iowadr == 15) ? {8'b0, display} : 199 | 0)); 200 | 201 | assign ram_be[0] = ~ben | (~adr[1] & ~adr[0]); 202 | assign ram_be[1] = ~ben | (~adr[1] & adr[0]); 203 | assign ram_be[2] = ~ben | (adr[1] & ~adr[0]); 204 | assign ram_be[3] = ~ben | (adr[1] & adr[0]); 205 | 206 | genvar i; 207 | generate // tri-state buffer for gpio port 208 | for (i = 0; i < 8; i = i+1) 209 | begin: gpioblock 210 | IOBUF gpiobuf (.I(gpout[i]), .O(gpin[i]), .IO(gpio[i]), .T(~gpoc[i])); 211 | end 212 | endgenerate 213 | 214 | assign dataTx = outbus[7:0]; 215 | assign startTx = wr & ioenb & (iowadr == 2); 216 | assign doneRx = rd & ioenb & (iowadr == 2); 217 | assign limit = (cnt0 == 24999); 218 | assign spiStart = wr & ioenb & (iowadr == 4); 219 | assign SS = ~spiCtrl[1:0]; //active low slave select 220 | assign MOSI[1] = MOSI[0], SCLK[1] = SCLK[0], NEN = spiCtrl[3]; 221 | assign doneKbd = rd & ioenb & (iowadr == 7); 222 | assign LED1 = wr_busy | rd_busy; 223 | assign LED2 = (id_reg[55:48] != 8'h5d); 224 | assign LED5 = ~SS[0]; 225 | assign leds = Lreg; 226 | 227 | always @(posedge clk) 228 | begin 229 | rst <= ((cnt1[4:0] == 0) & limit) ? ~btn[3] : rst; 230 | Lreg <= ~rst ? 0 : (wr & ioenb & (iowadr == 1)) ? outbus[7:0] : Lreg; 231 | cnt0 <= limit ? 0 : cnt0 + 1; 232 | cnt1 <= cnt1 + limit; 233 | spiCtrl <= ~rst ? 0 : (wr & ioenb & (iowadr == 5)) ? outbus[3:0] : spiCtrl; 234 | bitrate <= ~rst ? 0 : (wr & ioenb & (iowadr == 3)) ? outbus[0] : bitrate; 235 | gpout <= (wr & ioenb & (iowadr == 8)) ? outbus[7:0] : gpout; 236 | gpoc <= ~rst ? 0 : (wr & ioenb & (iowadr == 9)) ? outbus[7:0] : gpoc; 237 | display <= (wr & ioenb & (iowadr == 15)) ? outbus[23:0] : display; 238 | end 239 | 240 | initial 241 | display = 24'h0e7f00; 242 | 243 | cache_64k cache ( 244 | .addr(adr), 245 | .dout(cache_out), 246 | .din(outbus), 247 | .clk(clk), 248 | .mreq(mreq), 249 | .wmask(({4{!ben}} | (1'b1 << adr[1:0])) & {4{wr}}), 250 | .ce(ce), 251 | .mem_din(cache_wdata), 252 | .mem_dout(cache_rdata), 253 | .mem_clk(mem_clk), 254 | .mem_rd(mem_rd), 255 | .mem_wr(mem_wr), 256 | .waddr(waddr), 257 | .raddr(raddr), 258 | .cache_wr(cache_en && cache_we), 259 | .cache_rd(cache_en && ~cache_we), 260 | .cache_addr(cache_addr), 261 | .rd_busy(rd_busy), 262 | .wr_busy(wr_busy) 263 | ); 264 | 265 | PSRAM psram( 266 | .mem_clk(mem_clk), 267 | .reset(~pll_locked), 268 | .mem_rd(mem_rd), // memory read request 269 | .mem_wr(mem_wr), // memory write request 270 | .waddr(waddr), // memory write address 271 | .raddr(raddr), // memory read address 272 | .cache_rdata(cache_rdata), // write data to memory 273 | .cache_wdata(cache_wdata), // read data from memory 274 | .cache_en(cache_en), // cache eneble 275 | .cache_we(cache_we), // cache write 276 | .cache_addr(cache_addr), // cache address 277 | .rd_busy(rd_busy), // memory controller busy read 278 | .wr_busy(wr_busy), // memory controller busy write 279 | .psram_ce(psram_ce), 280 | .psram_sclk(psram_sclk), 281 | .psram_sio0(psram_sio0), 282 | .psram_sio1(psram_sio1), 283 | .psram_sio2(psram_sio2), 284 | .psram_sio3(psram_sio3), 285 | .id_reg(id_reg) 286 | ); 287 | 288 | 289 | 290 | endmodule -------------------------------------------------------------------------------- /rtl/RS232R.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 4.5.09 / 15.11.10 23 | // RS232 receiver for 19200 or 115200 bps, 8 bit data 24 | // clock is 25 MHz 25 | 26 | module RS232R( 27 | input clk, rst, 28 | input RxD, 29 | input fsel, 30 | input done, // "byte has been read" 31 | output rdy, 32 | output [7:0] data); 33 | 34 | wire endtick, midtick, endbit; 35 | wire [11:0] limit; 36 | reg run, stat; 37 | reg Q0, Q1; // synchronizer and edge detector 38 | reg [11:0] tick; 39 | reg [3:0] bitcnt; 40 | reg [7:0] shreg; 41 | 42 | assign limit = fsel ? 217 : 1302; 43 | assign endtick = tick == limit; 44 | assign midtick = tick == {1'b0, limit[11:1]}; // limit/2 45 | assign endbit = bitcnt == 8; 46 | assign data = shreg; 47 | assign rdy = stat; 48 | 49 | always @ (posedge clk) begin 50 | Q0 <= RxD; Q1 <= Q0; 51 | run <= (Q1 & ~Q0) | ~(~rst | endtick & endbit) & run; 52 | tick <= (run & ~endtick) ? tick+1 : 0; 53 | bitcnt <= (endtick & ~endbit) ? bitcnt + 1 : 54 | (endtick & endbit) ? 0 : bitcnt; 55 | shreg <= midtick ? {Q1, shreg[7:1]} : shreg; 56 | stat <= (endtick & endbit) | ~(~rst | done) & stat; 57 | end 58 | endmodule 59 | -------------------------------------------------------------------------------- /rtl/RS232T.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | /*Project Oberon, Revised Edition 2013 4 | 5 | Book copyright (C)2013 Niklaus Wirth and Juerg Gutknecht; 6 | software copyright (C)2013 Niklaus Wirth (NW), Juerg Gutknecht (JG), Paul 7 | Reed (PR/PDR). 8 | 9 | Permission to use, copy, modify, and/or distribute this software and its 10 | accompanying documentation (the "Software") for any purpose with or 11 | without fee is hereby granted, provided that the above copyright notice 12 | and this permission notice appear in all copies. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 15 | WITH REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 16 | MERCHANTABILITY, FITNESS AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS BE LIABLE FOR ANY CLAIM, SPECIAL, DIRECT, INDIRECT, OR 18 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES OR LIABILITY WHATSOEVER, WHETHER IN 19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE DEALINGS IN OR USE OR PERFORMANCE OF THE SOFTWARE.*/ 21 | 22 | // NW 4.5.09 / 15.8.10 / 15.11.10 23 | // RS232 transmitter for 19200 bps, 8 bit data 24 | // clock is 25 MHz; 25000 / 1302 = 19.2 KHz 25 | 26 | module RS232T( 27 | input clk, rst, 28 | input start, // request to accept and send a byte 29 | input fsel, // frequency selection 30 | input [7:0] data, 31 | output rdy, 32 | output TxD); 33 | 34 | wire endtick, endbit; 35 | wire [11:0] limit; 36 | reg run; 37 | reg [11:0] tick; 38 | reg [3:0] bitcnt; 39 | reg [8:0] shreg; 40 | 41 | assign limit = fsel ? 217 : 1302; 42 | assign endtick = tick == limit; 43 | assign endbit = bitcnt == 9; 44 | assign rdy = ~run; 45 | assign TxD = shreg[0]; 46 | 47 | always @ (posedge clk) begin 48 | run <= (~rst | endtick & endbit) ? 0 : start ? 1 : run; 49 | tick <= (run & ~endtick) ? tick + 1 : 0; 50 | bitcnt <= (endtick & ~endbit) ? bitcnt + 1 : 51 | (endtick & endbit) ? 0 : bitcnt; 52 | shreg <= (~rst) ? 1 : start ? {data, 1'b0} : 53 | endtick ? {1'b1, shreg[8:1]} : shreg; 54 | end 55 | endmodule 56 | -------------------------------------------------------------------------------- /rtl/Registers.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps // 1.2.2018 2 | // register file, triple-port 3 | 4 | module Registers( 5 | input clk, wr, ce, 6 | input [3:0] rno0, rno1, rno2, 7 | input [31:0] din, 8 | output [31:0] dout0, dout1, dout2); 9 | genvar i; 10 | generate //triple port register file, duplicated LUT array 11 | for (i = 0; i < 32; i = i+1) 12 | begin: rf32 13 | RAM16X1D # (.INIT(16'h0000)) 14 | rfb( 15 | .DPO(dout1[i]), // data out 16 | .SPO(dout0[i]), 17 | .A0(rno0[0]), // R/W address, controls D and SPO 18 | .A1(rno0[1]), 19 | .A2(rno0[2]), 20 | .A3(rno0[3]), 21 | .D(din[i]), // data in 22 | .DPRA0(rno1[0]), // read-only adr, controls DPO 23 | .DPRA1(rno1[1]), 24 | .DPRA2(rno1[2]), 25 | .DPRA3(rno1[3]), 26 | .WCLK(clk), 27 | .WE(wr & ce)); 28 | 29 | RAM16X1D # (.INIT(16'h0000)) 30 | rfc( 31 | .DPO(dout2[i]), // data out 32 | .SPO(), 33 | .A0(rno0[0]), // R/W address, controls D and SPO 34 | .A1(rno0[1]), 35 | .A2(rno0[2]), 36 | .A3(rno0[3]), 37 | .D(din[i]), // data in 38 | .DPRA0(rno2[0]), // read-only adr, controls DPO 39 | .DPRA1(rno2[1]), 40 | .DPRA2(rno2[2]), 41 | .DPRA3(rno2[3]), 42 | .WCLK(clk), 43 | .WE(wr & ce)); 44 | end 45 | endgenerate 46 | endmodule 47 | -------------------------------------------------------------------------------- /rtl/RightShifter.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps // NW 9.11.2016 2 | 3 | module RightShifter( 4 | input [31:0] x, 5 | input [4:0] sc, 6 | input md, 7 | output [31:0] y); 8 | 9 | // shifter for ASR and ROR 10 | wire [1:0] sc0, sc1; 11 | wire [31:0] s1, s2; 12 | 13 | assign sc0 = sc[1:0]; 14 | assign sc1 = sc[3:2]; 15 | 16 | assign s1 = (sc0 == 3) ? {(md ? x[2:0] : {3{x[31]}}), x[31:3]} : 17 | (sc0 == 2) ? {(md ? x[1:0] : {2{x[31]}}), x[31:2]} : 18 | (sc0 == 1) ? {(md ? x[0] : x[31]), x[31:1]} : x; 19 | 20 | assign s2 = (sc1 == 3) ? {(md ? s1[11:0] : {12{s1[31]}}), s1[31:12]} : 21 | (sc1 == 2) ? {(md ? s1[7:0] : {8{s1[31]}}), s1[31:8]} : 22 | (sc1 == 1) ? {(md ? s1[3:0] : {4{s1[31]}}), s1[31:4]} : s1; 23 | assign y = sc[4] ? {(md ? s2[15:0] : {16{s2[31]}}), s2[31:16]} : s2; 24 | endmodule -------------------------------------------------------------------------------- /rtl/SPI.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | // Motorola Serial Peripheral Interface (SPI) PDR 23.3.12 / 16.10.13 4 | // transmitter / receiver of words (fast, clk/3) or bytes (slow, clk/64) 5 | // e.g 8.33MHz or ~400KHz respectively at 25MHz (slow needed for SD-card init) 6 | // note: bytes are always MSbit first; but if fast, words are LSByte first 7 | 8 | module SPI( 9 | input clk, rst, 10 | input start, fast, 11 | input [31:0] dataTx, 12 | output [31:0] dataRx, 13 | output reg rdy, 14 | input MISO, output MOSI, output SCLK); 15 | 16 | wire endbit, endtick; 17 | reg [31:0] shreg; 18 | reg [5:0] tick; 19 | reg [4:0] bitcnt; 20 | 21 | assign endtick = fast ? (tick == 2) : (tick == 63); //25MHz clk 22 | assign endbit = fast ? (bitcnt == 31) : (bitcnt == 7); 23 | assign dataRx = fast ? shreg : {24'b0, shreg[7:0]}; 24 | assign MOSI = (~rst | rdy) ? 1 : shreg[7]; 25 | assign SCLK = (~rst | rdy) ? 0 : fast ? endtick : tick[5]; 26 | 27 | always @ (posedge clk) begin 28 | tick <= (~rst | rdy | endtick) ? 0 : tick + 1; 29 | rdy <= (~rst | endtick & endbit) ? 1 : start ? 0 : rdy; 30 | bitcnt <= (~rst | start) ? 0 : (endtick & ~endbit) ? bitcnt + 1 : bitcnt; 31 | shreg <= ~rst ? -1 : start ? dataTx : endtick ? 32 | {shreg[30:24], MISO, shreg[22:16], shreg[31], shreg[14:8], 33 | shreg[23], shreg[6:0], (fast ? shreg[15] : MISO)} : shreg; 34 | end 35 | 36 | endmodule -------------------------------------------------------------------------------- /rtl/VID.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // 1024x768 display controller NW/PR 24.1.2014 3 | 4 | module VID( 5 | input pclk, clk, inv, 6 | input [31:0] viddata, 7 | output reg req, // SRAM read request 8 | output [14:0] vidadr, 9 | output hsync, vsync, // to display 10 | output vde, 11 | output [2:0] RGB); 12 | 13 | //localparam Org = 18'b1101_1111_1111_0000_00; // DFF00: adr of vcnt=1023 14 | reg [10:0] hcnt; 15 | reg [9:0] vcnt; 16 | reg [4:0] hword; // from hcnt, but latched in the clk domain 17 | reg [9:0] vline; // from vcnt, but latched in the clk domain 18 | reg [31:0] vidbuf, pixbuf; 19 | reg hblank; 20 | wire pclk, hend, vend, vblank, xfer, vid; 21 | 22 | assign hend = (hcnt == 1327), vend = (vcnt == 805); 23 | assign vblank = (vcnt[8] & vcnt[9]); // (vcnt >= 768) 24 | assign hsync = ~((hcnt >= 1048+6) & (hcnt < 1185+6)); // -ve polarity 25 | assign vsync = (vcnt >= 771) & (vcnt < 777); // +ve polarity 26 | assign xfer = (hcnt[4:0] == 6); // data delay > hcnt cycle + req cycle 27 | assign vid = (pixbuf[0] ^ inv) & ~hblank & ~vblank; 28 | assign RGB = {vid, vid, vid}; 29 | assign vidadr = {~vline, hword} - 15'h2000;//Org + {3'b0, ~vline, hword}; 30 | assign vde = ~hblank & ~vblank; 31 | 32 | always @(posedge pclk) begin // pixel clock domain 33 | hcnt <= hend ? 0 : hcnt+1; 34 | vcnt <= hend ? (vend ? 0 : (vcnt+1)) : vcnt; 35 | hblank <= xfer ? hcnt[10] : hblank; // hcnt >= 1024 36 | pixbuf <= xfer ? vidbuf : {1'b0, pixbuf[31:1]}; 37 | end 38 | 39 | always @(posedge clk) begin // CPU (SRAM) clock domain 40 | hword <= hcnt[9:5]; 41 | vline <= vcnt; 42 | req <= ~vblank & ~hcnt[10] & (hcnt[5] ^ hword[0]); // i.e. adr changed 43 | vidbuf <= req ? viddata : vidbuf; 44 | end 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /rtl/VRAM.v: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Filename: VRAM.v 4 | // Description: Video frame buffer in BRAM 5 | // Creation date: Jan 9, 2021 6 | // 7 | // Author: Magnus Karlsson 8 | // e-mail: magnus@saanlima.com 9 | // 10 | // 11 | ///////////////////////////////////////////////////////////////////////////////// 12 | // 13 | // Copyright (C) 2021 Magnus Karlsson 14 | // 15 | // This source file may be used and distributed without 16 | // restriction provided that this copyright statement is not 17 | // removed from the file and that any derivative work contains 18 | // the original copyright notice and the associated disclaimer. 19 | // 20 | // This source file is free software; you can redistribute it 21 | // and/or modify it under the terms of the GNU Lesser General 22 | // Public License as published by the Free Software Foundation; 23 | // either version 2.1 of the License, or (at your option) any 24 | // later version. 25 | // 26 | // This source is distributed in the hope that it will be 27 | // useful, but WITHOUT ANY WARRANTY; without even the implied 28 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 29 | // PURPOSE. See the GNU Lesser General Public License for more 30 | // details. 31 | // 32 | // You should have received a copy of the GNU Lesser General 33 | // Public License along with this source; if not, download it 34 | // from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 35 | // 36 | /////////////////////////////////////////////////////////////////////////////////// 37 | 38 | module VRAM ( 39 | input clka, 40 | input [14:0] adra, 41 | input [3:0] bea, 42 | input wea, 43 | input [31:0] wda, 44 | output [31:0] rda, 45 | input clkb, 46 | input [14:0] adrb, 47 | output [31:0] rdb); 48 | 49 | wire [7:0] rda_0, rda_1, rda_2, rda_3; 50 | wire [7:0] viddata_0, viddata_1, viddata_2, viddata_3; 51 | 52 | VRAM8 vram8_0(.clka(clka), .adra(adra), .wea(wea & bea[0]), 53 | .wda(wda[7:0]), .rda(rda_0), .clkb(clkb), .adrb(adrb), 54 | .rdb(viddata_0)); 55 | 56 | VRAM8 vram8_1(.clka(clka), .adra(adra), .wea(wea & bea[1]), 57 | .wda(wda[15:8]), .rda(rda_1), .clkb(clkb), .adrb(adrb), 58 | .rdb(viddata_1)); 59 | 60 | VRAM8 vram8_2(.clka(clka), .adra(adra), .wea(wea & bea[2]), 61 | .wda(wda[23:16]), .rda(rda_2), .clkb(clkb), .adrb(adrb), 62 | .rdb(viddata_2)); 63 | 64 | VRAM8 vram8_3(.clka(clka), .adra(adra), .wea(wea & bea[3]), 65 | .wda(wda[31:24]), .rda(rda_3), .clkb(clkb), .adrb(adrb), 66 | .rdb(viddata_3)); 67 | 68 | assign rda = {rda_3, rda_2, rda_1, rda_0}; 69 | assign rdb = {viddata_3, viddata_2, viddata_1, viddata_0}; 70 | 71 | endmodule 72 | 73 | 74 | module VRAM8 ( 75 | input clka, 76 | input [14:0] adra, 77 | input wea, 78 | input [7:0] wda, 79 | output reg [7:0] rda, 80 | input clkb, 81 | input [14:0] adrb, 82 | output reg [7:0] rdb); 83 | 84 | reg [7:0] ram [24575:0]; 85 | 86 | // Port A 87 | always @(posedge clka) begin 88 | rda <= ram[adra]; 89 | if(wea) begin 90 | rda <= wda; 91 | ram[adra] <= wda; 92 | end 93 | end 94 | 95 | // Port B 96 | always @(posedge clkb) begin 97 | rdb <= ram[adrb]; 98 | end 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /rtl/cache_64k.v: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Filename: cache_64k.v 4 | // Description: 2-way, 512-set cache with 64 byte cache lines 5 | // Version 1.1 6 | // Creation date: Jan 9, 2021 7 | // 8 | // Author: Magnus Karlsson 9 | // e-mail: magnus@saanlima.com 10 | // 11 | // Loosely based on cache_controller.v written by Nicolae Dumitrache 12 | // 13 | ///////////////////////////////////////////////////////////////////////////////// 14 | // 15 | // Copyright (C) 2020 Magnus Karlsson 16 | // 17 | // This source file may be used and distributed without 18 | // restriction provided that this copyright statement is not 19 | // removed from the file and that any derivative work contains 20 | // the original copyright notice and the associated disclaimer. 21 | // 22 | // This source file is free software; you can redistribute it 23 | // and/or modify it under the terms of the GNU Lesser General 24 | // Public License as published by the Free Software Foundation; 25 | // either version 2.1 of the License, or (at your option) any 26 | // later version. 27 | // 28 | // This source is distributed in the hope that it will be 29 | // useful, but WITHOUT ANY WARRANTY; without even the implied 30 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 31 | // PURPOSE. See the GNU Lesser General Public License for more 32 | // details. 33 | // 34 | // You should have received a copy of the GNU Lesser General 35 | // Public License along with this source; if not, download it 36 | // from https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html 37 | // 38 | /////////////////////////////////////////////////////////////////////////////////// 39 | 40 | 41 | module cache_64k( 42 | // cpu interface 43 | input clk, 44 | input [23:0] addr, // cpu address 45 | output [31:0] dout, // read data to cpu 46 | input [31:0] din, // write data from cpu 47 | input mreq, // memory accress request 48 | input [3:0] wmask, // memory byte write enable 49 | output ce, // cpu clock enable signal (cpu stall if 0) 50 | // memory controller interface 51 | input mem_clk, // memory controller clock 52 | input [127:0] mem_din, // read data from memory 53 | output [127:0] mem_dout, // write data to memory 54 | output reg mem_rd, // memory read request 55 | output reg mem_wr, // memory write request 56 | output reg [23:6] waddr, // memory write address 57 | output reg [23:6] raddr, // memory read address 58 | input cache_wr, // cache write 59 | input cache_rd, // cache read 60 | input [1:0] cache_addr, // cache address 61 | input rd_busy, // memory controller busy read 62 | input wr_busy // memory controller busy write 63 | ); 64 | 65 | reg [2:0] STATE; 66 | reg [8:0] tag0 [0:511] = 67 | {9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 68 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 69 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 70 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 71 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 72 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 73 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 74 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 75 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 76 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 77 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 78 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 79 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 80 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 81 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 82 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 83 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 84 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 85 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 86 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 87 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 88 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 89 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 90 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 91 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 92 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 93 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 94 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 95 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 96 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 97 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 98 | 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0, 9'd0} ; 99 | reg [8:0] tag1 [0:511] = 100 | {9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 101 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 102 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 103 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 104 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 105 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 106 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 107 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 108 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 109 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 110 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 111 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 112 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 113 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 114 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 115 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 116 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 117 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 118 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 119 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 120 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 121 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 122 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 123 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 124 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 125 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 126 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 127 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 128 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 129 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 130 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 131 | 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1, 9'd1} ; 132 | reg [511:0] dirty0 = 512'b0; 133 | reg [511:0] dirty1 = 512'b0; 134 | reg [511:0] mru = 512'b0; 135 | wire [8:0] index; 136 | wire hit0, hit1, hit; 137 | wire st0; 138 | wire wr; 139 | reg rd_busy_sync, wr_busy_sync; 140 | 141 | assign ce = st0 & (~mreq | hit); 142 | assign index = addr[14:6]; 143 | assign hit0 = (tag0[index] == addr[23:15]); 144 | assign hit1 = (tag1[index] == addr[23:15]); 145 | assign hit = hit0 | hit1; 146 | assign st0 = (STATE == 3'b000); 147 | assign wr = |wmask; 148 | 149 | always @(posedge clk) begin 150 | rd_busy_sync <= rd_busy; 151 | wr_busy_sync <= wr_busy; 152 | raddr <= addr[23:6]; 153 | case(STATE) 154 | 3'b000: begin 155 | mem_wr <= 1'b0; 156 | mem_rd <= 1'b0; 157 | if(mreq & hit0) begin // cache hit0 158 | mru[index] <= 1'b0; 159 | if(wr) dirty0[index] <= 1'b1; 160 | end else if(mreq & hit1) begin // cache hit1 161 | mru[index] <= 1'b1; 162 | if(wr) dirty1[index] <= 1'b1; 163 | end 164 | if(mreq && !hit) begin // cache miss 165 | if(mru[index] == 1'b1) begin 166 | waddr <= {tag0[index], addr[14:6]}; 167 | tag0[index] <= addr[23:15]; 168 | if (dirty0[index]) begin 169 | mem_wr <= 1'b1; 170 | dirty0[index] <= 1'b0; 171 | STATE <= 3'b011; 172 | end else begin 173 | mem_rd <= 1'b1; 174 | STATE <= 3'b111; 175 | end 176 | end else begin 177 | waddr <= {tag1[index], addr[14:6]}; 178 | tag1[index] <= addr[23:15]; 179 | if (dirty1[index]) begin 180 | mem_wr <= 1'b1; 181 | dirty1[index] <= 1'b0; 182 | STATE <= 3'b011; 183 | end else begin 184 | mem_rd <= 1'b1; 185 | STATE <= 3'b111; 186 | end 187 | end 188 | end 189 | end 190 | 3'b011: begin // write cache to memory 191 | if(wr_busy_sync) begin 192 | mem_wr <= 1'b0; 193 | mem_rd <= 1'b1; 194 | STATE <= 3'b111; 195 | end 196 | end 197 | 3'b111: begin // read cache from memory 198 | if(rd_busy_sync) begin 199 | mem_rd <= 1'b0; 200 | STATE <= 3'b101; 201 | end 202 | end 203 | 3'b101: begin // wait for memory read to finish 204 | if(~rd_busy_sync) 205 | STATE <= 3'b000; 206 | end 207 | endcase 208 | end 209 | 210 | cache_mem mem 211 | ( 212 | .clka(~clk), 213 | .ena(mreq & hit & st0), 214 | .wea({4{mreq & hit & st0 & wr}} & wmask), 215 | .addra({~hit0, addr[14:2]}), 216 | .dina(din), 217 | .douta(dout), 218 | .clkb(mem_clk), 219 | .enb(cache_wr | cache_rd), 220 | .web({16{cache_wr}}), 221 | .addrb({~mru[raddr[14:6]], raddr[14:6], cache_addr}), 222 | .dinb(mem_din), 223 | .doutb(mem_dout) 224 | ); 225 | 226 | endmodule 227 | 228 | module cache_mem ( 229 | input wire clka, 230 | input wire ena, 231 | input wire [3:0] wea, 232 | input wire [13:0] addra, 233 | input wire [31:0] dina, 234 | output wire [31:0] douta, 235 | input wire clkb, 236 | input wire enb, 237 | input wire [15:0] web, 238 | input wire [11:0] addrb, 239 | input wire [127:0] dinb, 240 | output wire [127:0] doutb 241 | ); 242 | 243 | wire [127:0] dina_64; 244 | wire [127:0] douta_64; 245 | wire [15:0] wea_64; 246 | wire [11:0] addra_64; 247 | 248 | assign dina_64 = {4{dina}}; 249 | assign addra_64 = addra[13:2]; 250 | assign wea_64 = addra[1:0] == 2'b00 ? {12'b0, wea} : 251 | addra[1:0] == 2'b01 ? {8'b0, wea, 4'b0} : 252 | addra[1:0] == 2'b10 ? {4'b0, wea, 8'b0} : {wea, 12'b0}; 253 | assign douta = addra[1:0] == 2'b00 ? douta_64[31:0] : 254 | addra[1:0] == 2'b01 ? douta_64[63:32] : 255 | addra[1:0] == 2'b10 ? douta_64[95:64] : douta_64[127:96]; 256 | 257 | bram_tdp byte0 ( 258 | .a_clk (clka), 259 | .a_en (ena), 260 | .a_wr (wea_64[0]), 261 | .a_addr (addra_64), 262 | .a_din (dina_64[7:0]), 263 | .a_dout (douta_64[7:0]), 264 | .b_clk (clkb), 265 | .b_en (enb), 266 | .b_wr (web[0]), 267 | .b_addr (addrb), 268 | .b_din (dinb[7:0]), 269 | .b_dout (doutb[7:0]) 270 | ); 271 | 272 | bram_tdp byte1 ( 273 | .a_clk (clka), 274 | .a_en (ena), 275 | .a_wr (wea_64[1]), 276 | .a_addr (addra_64), 277 | .a_din (dina_64[15:8]), 278 | .a_dout (douta_64[15:8]), 279 | .b_clk (clkb), 280 | .b_en (enb), 281 | .b_wr (web[1]), 282 | .b_addr (addrb), 283 | .b_din (dinb[15:8]), 284 | .b_dout (doutb[15:8]) 285 | ); 286 | 287 | bram_tdp byte2 ( 288 | .a_clk (clka), 289 | .a_en (ena), 290 | .a_wr (wea_64[2]), 291 | .a_addr (addra_64), 292 | .a_din (dina_64[23:16]), 293 | .a_dout (douta_64[23:16]), 294 | .b_clk (clkb), 295 | .b_en (enb), 296 | .b_wr (web[2]), 297 | .b_addr (addrb), 298 | .b_din (dinb[23:16]), 299 | .b_dout (doutb[23:16]) 300 | ); 301 | 302 | bram_tdp byte3 ( 303 | .a_clk (clka), 304 | .a_en (ena), 305 | .a_wr (wea_64[3]), 306 | .a_addr (addra_64), 307 | .a_din (dina_64[31:24]), 308 | .a_dout (douta_64[31:24]), 309 | .b_clk (clkb), 310 | .b_en (enb), 311 | .b_wr (web[3]), 312 | .b_addr (addrb), 313 | .b_din (dinb[31:24]), 314 | .b_dout (doutb[31:24]) 315 | ); 316 | 317 | bram_tdp byte4 ( 318 | .a_clk (clka), 319 | .a_en (ena), 320 | .a_wr (wea_64[4]), 321 | .a_addr (addra_64), 322 | .a_din (dina_64[39:32]), 323 | .a_dout (douta_64[39:32]), 324 | .b_clk (clkb), 325 | .b_en (enb), 326 | .b_wr (web[4]), 327 | .b_addr (addrb), 328 | .b_din (dinb[39:32]), 329 | .b_dout (doutb[39:32]) 330 | ); 331 | 332 | bram_tdp byte5 ( 333 | .a_clk (clka), 334 | .a_en (ena), 335 | .a_wr (wea_64[5]), 336 | .a_addr (addra_64), 337 | .a_din (dina_64[47:40]), 338 | .a_dout (douta_64[47:40]), 339 | .b_clk (clkb), 340 | .b_en (enb), 341 | .b_wr (web[5]), 342 | .b_addr (addrb), 343 | .b_din (dinb[47:40]), 344 | .b_dout (doutb[47:40]) 345 | ); 346 | 347 | bram_tdp byte6 ( 348 | .a_clk (clka), 349 | .a_en (ena), 350 | .a_wr (wea_64[6]), 351 | .a_addr (addra_64), 352 | .a_din (dina_64[55:48]), 353 | .a_dout (douta_64[55:48]), 354 | .b_clk (clkb), 355 | .b_en (enb), 356 | .b_wr (web[6]), 357 | .b_addr (addrb), 358 | .b_din (dinb[55:48]), 359 | .b_dout (doutb[55:48]) 360 | ); 361 | 362 | bram_tdp byte7 ( 363 | .a_clk (clka), 364 | .a_en (ena), 365 | .a_wr (wea_64[7]), 366 | .a_addr (addra_64), 367 | .a_din (dina_64[63:56]), 368 | .a_dout (douta_64[63:56]), 369 | .b_clk (clkb), 370 | .b_en (enb), 371 | .b_wr (web[7]), 372 | .b_addr (addrb), 373 | .b_din (dinb[63:56]), 374 | .b_dout (doutb[63:56]) 375 | ); 376 | bram_tdp byte8 ( 377 | .a_clk (clka), 378 | .a_en (ena), 379 | .a_wr (wea_64[8]), 380 | .a_addr (addra_64), 381 | .a_din (dina_64[71:64]), 382 | .a_dout (douta_64[71:64]), 383 | .b_clk (clkb), 384 | .b_en (enb), 385 | .b_wr (web[8]), 386 | .b_addr (addrb), 387 | .b_din (dinb[71:64]), 388 | .b_dout (doutb[71:64]) 389 | ); 390 | 391 | bram_tdp byte9 ( 392 | .a_clk (clka), 393 | .a_en (ena), 394 | .a_wr (wea_64[9]), 395 | .a_addr (addra_64), 396 | .a_din (dina_64[79:72]), 397 | .a_dout (douta_64[79:72]), 398 | .b_clk (clkb), 399 | .b_en (enb), 400 | .b_wr (web[9]), 401 | .b_addr (addrb), 402 | .b_din (dinb[79:72]), 403 | .b_dout (doutb[79:72]) 404 | ); 405 | 406 | bram_tdp byte10 ( 407 | .a_clk (clka), 408 | .a_en (ena), 409 | .a_wr (wea_64[10]), 410 | .a_addr (addra_64), 411 | .a_din (dina_64[87:80]), 412 | .a_dout (douta_64[87:80]), 413 | .b_clk (clkb), 414 | .b_en (enb), 415 | .b_wr (web[10]), 416 | .b_addr (addrb), 417 | .b_din (dinb[87:80]), 418 | .b_dout (doutb[87:80]) 419 | ); 420 | 421 | bram_tdp byte11 ( 422 | .a_clk (clka), 423 | .a_en (ena), 424 | .a_wr (wea_64[11]), 425 | .a_addr (addra_64), 426 | .a_din (dina_64[95:88]), 427 | .a_dout (douta_64[95:88]), 428 | .b_clk (clkb), 429 | .b_en (enb), 430 | .b_wr (web[11]), 431 | .b_addr (addrb), 432 | .b_din (dinb[95:88]), 433 | .b_dout (doutb[95:88]) 434 | ); 435 | bram_tdp byte12 ( 436 | .a_clk (clka), 437 | .a_en (ena), 438 | .a_wr (wea_64[12]), 439 | .a_addr (addra_64), 440 | .a_din (dina_64[103:96]), 441 | .a_dout (douta_64[103:96]), 442 | .b_clk (clkb), 443 | .b_en (enb), 444 | .b_wr (web[12]), 445 | .b_addr (addrb), 446 | .b_din (dinb[103:96]), 447 | .b_dout (doutb[103:96]) 448 | ); 449 | 450 | bram_tdp byte13 ( 451 | .a_clk (clka), 452 | .a_en (ena), 453 | .a_wr (wea_64[13]), 454 | .a_addr (addra_64), 455 | .a_din (dina_64[111:104]), 456 | .a_dout (douta_64[111:104]), 457 | .b_clk (clkb), 458 | .b_en (enb), 459 | .b_wr (web[13]), 460 | .b_addr (addrb), 461 | .b_din (dinb[111:104]), 462 | .b_dout (doutb[111:104]) 463 | ); 464 | 465 | bram_tdp byte14 ( 466 | .a_clk (clka), 467 | .a_en (ena), 468 | .a_wr (wea_64[14]), 469 | .a_addr (addra_64), 470 | .a_din (dina_64[119:112]), 471 | .a_dout (douta_64[119:112]), 472 | .b_clk (clkb), 473 | .b_en (enb), 474 | .b_wr (web[14]), 475 | .b_addr (addrb), 476 | .b_din (dinb[119:112]), 477 | .b_dout (doutb[119:112]) 478 | ); 479 | 480 | bram_tdp byte15 ( 481 | .a_clk (clka), 482 | .a_en (ena), 483 | .a_wr (wea_64[15]), 484 | .a_addr (addra_64), 485 | .a_din (dina_64[127:120]), 486 | .a_dout (douta_64[127:120]), 487 | .b_clk (clkb), 488 | .b_en (enb), 489 | .b_wr (web[15]), 490 | .b_addr (addrb), 491 | .b_din (dinb[127:120]), 492 | .b_dout (doutb[127:120]) 493 | ); 494 | 495 | endmodule 496 | 497 | 498 | module bram_tdp #( 499 | parameter DATA = 8, 500 | parameter ADDR = 12 501 | ) ( 502 | // Port A 503 | input wire a_clk, 504 | input wire a_en, 505 | input wire a_wr, 506 | input wire [ADDR-1:0] a_addr, 507 | input wire [DATA-1:0] a_din, 508 | output reg [DATA-1:0] a_dout, 509 | 510 | // Port B 511 | input wire b_clk, 512 | input wire b_en, 513 | input wire b_wr, 514 | input wire [ADDR-1:0] b_addr, 515 | input wire [DATA-1:0] b_din, 516 | output reg [DATA-1:0] b_dout 517 | ); 518 | 519 | // Shared memory 520 | reg [DATA-1:0] mem [(2**ADDR)-1:0]; 521 | 522 | // Port A 523 | always @(posedge a_clk) begin 524 | if (a_en) begin 525 | a_dout <= mem[a_addr]; 526 | if (a_wr) begin 527 | a_dout <= a_din; 528 | mem[a_addr] <= a_din; 529 | end 530 | end 531 | end 532 | 533 | // Port B 534 | always @(posedge b_clk) begin 535 | if (b_en) begin 536 | b_dout <= mem[b_addr]; 537 | if (b_wr) begin 538 | b_dout <= b_din; 539 | mem[b_addr] <= b_din; 540 | end 541 | end 542 | end 543 | 544 | endmodule -------------------------------------------------------------------------------- /rtl/encode.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saanlima/RISC5Verilog_psram/1ed039df2d6c6d3b3f173298a8a606c670a8fbb2/rtl/encode.v -------------------------------------------------------------------------------- /rtl/prom.mem: -------------------------------------------------------------------------------- 1 | E7000151 00000000 00000000 00000000 00000000 00000000 00000000 00000000 4EE90014 AFE00000 A0E00004 40000000 A0E00008 40000004 A0E00010 80E00010 40090001 A0E00010 5000FFCC 80000000 40030001 E8FFFFFC 5000FFC8 80000000 A0E0000C 80E00008 81E0000C 00080001 40030008 A0E00008 80E00010 E9FFFFEF 80E00008 81E00004 A0100000 8FE00000 4EE80014 C700000F 4EE90010 AFE00000 40E80004 F7FFFFDE 80E00004 40090000 E6000012 40E80008 F7FFFFD9 40E8000C F7FFFFD7 80E00008 81E0000C A1000000 80E00008 40080004 A0E00008 80E00004 40090004 A0E00004 80E00004 E9FFFFF3 40E80004 F7FFFFCA E7FFFFEB 8FE00000 4EE80010 C700000F 4EE90008 AFE00000 A0E00004 5000FFD4 41000000 A1000000 80E00004 40090000 E600000B 80E00004 40090001 A0E00004 5000FFD0 5100FFFF A1000000 5000FFD4 80000000 40030001 E8FFFFFC E7FFFFF2 8FE00000 4EE80008 C700000F 4EE90008 AFE00000 A0E00004 5000FFD4 41000001 A1000000 5000FFD0 81E00004 A1000000 5000FFD4 80000000 40030001 E8FFFFFC 8FE00000 4EE80008 C700000F 4EE90018 AFE00000 A0E00004 A1E00008 40000001 F7FFFFD3 5000FFD0 80000000 A0E00010 80E00010 400900FF E9FFFFF8 400000FF F7FFFFE2 5000FFD0 80000000 A0E00010 80E00010 400900FF E9FFFFF8 80E00004 40090008 E9000003 40000087 A0E00014 E7000007 80E00004 E9000003 40000095 A0E00014 E7000002 400000FF A0E00014 80E00004 4004003F 40080040 F7FFFFCB 40000018 41090000 E5000008 A0E0000C 80E00008 81E0000C 00030001 F7FFFFC3 80E0000C 5008FFF8 E7FFFFF6 80E00014 F7FFFFBE 40000020 A0E0000C 400000FF F7FFFFBA 5000FFD0 80000000 A0E00010 80E0000C 40090001 A0E0000C 80E00010 40090080 E5000002 80E0000C E9FFFFF3 8FE00000 4EE80018 C700000F 4EE9000C AFE00000 40000009 F7FFFF91 40000000 41000000 F7FFFFB5 40000008 410001AA F7FFFFB2 5000FFFF F7FFFFA0 5000FFFF F7FFFF9E 5000FFFF F7FFFF9C 40000037 41000000 F7FFFFA9 40000029 41000001 4111001E F7FFFFA5 5000FFD0 80000000 A0E00004 5000FFFF F7FFFF90 5000FFFF F7FFFF8E 5000FFFF F7FFFF8C 40002710 F7FFFF73 80E00004 E9FFFFEC 40000010 41000200 F7FFFF95 40000001 F7FFFF6C 8FE00000 4EE8000C C700000F 4EE9000C AFE00000 A0E00004 4000003A 41000000 F7FFFF8A 5000FFD0 80000000 A0E00008 5000FFFF F7FFFF75 80E00008 E9000004 5000FFD0 80000000 40030007 E0000005 80E00004 80000000 40010009 81E00004 A0100000 5000FFFF F7FFFF68 5000FFFF F7FFFF66 40000001 F7FFFF4D 8FE00000 4EE8000C C700000F 4EE90014 AFE00000 A0E00004 A1E00008 40E80004 F7FFFFDB 40000011 81E00004 F7FFFF68 40000000 A0E0000C 5000FFFF F7FFFF54 5000FFD0 80000000 A0E00010 80E0000C 40080001 A0E0000C 80E00010 400900FE E9FFFFF5 5000FFD4 41000005 A1000000 40000000 410901FC EE000014 A0E0000C 5000FFD0 5100FFFF A1000000 5000FFD4 80000000 40030001 E8FFFFFC 5000FFD0 80000000 A0E00010 80E00008 81E00010 A1000000 80E00008 40080004 A0E00008 80E0000C 40080004 E7FFFFEA 400000FF F7FFFF2F 400000FF F7FFFF2D 40000001 F7FFFF14 8FE00000 4EE80014 C700000F 4EE90014 AFE00000 60000008 40060004 A0E00004 80E00004 41000000 F7FFFFBF 40000010 80000000 A0E00010 80E00004 40080001 A0E00004 40000200 A0E00008 80E00008 81E00010 00090001 ED00000A 80E00004 81E00008 F7FFFFB0 80E00004 40080001 A0E00004 80E00008 40080200 A0E00008 E7FFFFF2 8FE00000 4EE80014 C700000F 5E00FFC0 60000040 0E000000 4C000020 0000000F 40090000 E9000012 40000080 5100FFC4 A0100000 F7FFFF50 5000FFC4 80000000 40030001 E8000005 40000081 5100FFC4 A0100000 F7FFFEC1 E7000004 40000082 5100FFC4 A0100000 F7FFFFC7 E7000008 5000FFC4 80000000 40030001 E8000004 40000081 5100FFC4 A0100000 F7FFFEB3 4000000C 610000FC A1000000 40000018 61000040 A1000000 40000084 5100FFC4 A0100000 40000000 C7000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -------------------------------------------------------------------------------- /rtl/serialiser_10_to_1.v: -------------------------------------------------------------------------------- 1 | module serialiser_10_to_1 (clk_x1, clk_x5, din, reset, serial); 2 | input clk_x1; 3 | input clk_x5; 4 | input reset; 5 | input [9:0] din; 6 | output serial; 7 | 8 | wire shift1, shift2; 9 | reg ce_delay; 10 | 11 | OSERDESE2 #( 12 | .DATA_RATE_OQ ("DDR"), 13 | .DATA_RATE_TQ ("DDR"), 14 | .DATA_WIDTH (10), 15 | .INIT_OQ (1'b1), 16 | .INIT_TQ (1'b1), 17 | .SERDES_MODE ("MASTER"), 18 | .SRVAL_OQ (1'b0), 19 | .SRVAL_TQ (1'b0), 20 | .TBYTE_CTL ("FALSE"), 21 | .TBYTE_SRC ("FALSE"), 22 | .TRISTATE_WIDTH (1)) 23 | OSERDESE2_master( 24 | .OFB (), 25 | .OQ (serial), 26 | .SHIFTOUT1 (), 27 | .SHIFTOUT2 (), 28 | .TBYTEOUT (), 29 | .TFB (), 30 | .TQ (), 31 | .CLK (clk_x5), 32 | .CLKDIV (clk_x1), 33 | .D1 (din[0]), 34 | .D2 (din[1]), 35 | .D3 (din[2]), 36 | .D4 (din[3]), 37 | .D5 (din[4]), 38 | .D6 (din[5]), 39 | .D7 (din[6]), 40 | .D8 (din[7]), 41 | .OCE (ce_delay), 42 | .RST (reset), 43 | .SHIFTIN1 (shift1), 44 | .SHIFTIN2 (shift2), 45 | .T1 (1'b0), 46 | .T2 (1'b0), 47 | .T3 (1'b0), 48 | .T4 (1'b0), 49 | .TBYTEIN (1'b0), 50 | .TCE (1'b0) 51 | ); 52 | 53 | OSERDESE2 #( 54 | .DATA_RATE_OQ ("DDR"), 55 | .DATA_RATE_TQ ("DDR"), 56 | .DATA_WIDTH (10), 57 | .INIT_OQ (1'b1), 58 | .INIT_TQ (1'b1), 59 | .SERDES_MODE ("SLAVE"), 60 | .SRVAL_OQ (1'b0), 61 | .SRVAL_TQ (1'b0), 62 | .TBYTE_CTL ("FALSE"), 63 | .TBYTE_SRC ("FALSE"), 64 | .TRISTATE_WIDTH (1)) 65 | OSERDESE2_slave( 66 | .OFB (), 67 | .OQ (), 68 | .SHIFTOUT1 (shift1), 69 | .SHIFTOUT2 (shift2), 70 | .TBYTEOUT (), 71 | .TFB (), 72 | .TQ (), 73 | .CLK (clk_x5), 74 | .CLKDIV (clk_x1), 75 | .D1 (1'b0), 76 | .D2 (1'b0), 77 | .D3 (din[8]), 78 | .D4 (din[9]), 79 | .D5 (1'b0), 80 | .D6 (1'b0), 81 | .D7 (1'b0), 82 | .D8 (1'b0), 83 | .OCE (ce_delay), 84 | .RST (reset), 85 | .SHIFTIN1 (1'b0), 86 | .SHIFTIN2 (1'b0), 87 | .T1 (1'b0), 88 | .T2 (1'b0), 89 | .T3 (1'b0), 90 | .T4 (1'b0), 91 | .TBYTEIN (1'b0), 92 | .TCE (1'b0) 93 | ); 94 | 95 | always @ (posedge clk_x5 or posedge reset) 96 | if (reset) 97 | ce_delay <= 1'b0; 98 | else 99 | ce_delay <= 1'b1; 100 | 101 | endmodule -------------------------------------------------------------------------------- /vivado.mk: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | # 3 | # Xilinx Vivado FPGA Makefile 4 | # 5 | # Copyright (c) 2016 Alex Forencich 6 | # 7 | ################################################################### 8 | # 9 | # Parameters: 10 | # FPGA_TOP - Top module name 11 | # FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale) 12 | # FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e) 13 | # SYN_FILES - space-separated list of source files 14 | # INC_FILES - space-separated list of include files 15 | # XDC_FILES - space-separated list of timing constraint files 16 | # XCI_FILES - space-separated list of IP XCI files 17 | # 18 | # Example: 19 | # 20 | # FPGA_TOP = fpga 21 | # FPGA_FAMILY = VirtexUltrascale 22 | # FPGA_DEVICE = xcvu095-ffva2104-2-e 23 | # SYN_FILES = rtl/fpga.v 24 | # XDC_FILES = xdc/fpga.xdc 25 | # XCI_FILES = ip/pcspma.xci 26 | # include ../vivado.mk 27 | # 28 | ################################################################### 29 | 30 | # phony targets 31 | .PHONY: clean fpga 32 | 33 | # prevent make from deleting intermediate files and reports 34 | .PRECIOUS: %.xpr %.bit 35 | .SECONDARY: 36 | 37 | CONFIG ?= config.mk 38 | -include ../$(CONFIG) 39 | 40 | SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES)) 41 | INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES)) 42 | XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES)) 43 | 44 | ifdef XDC_FILES 45 | XDC_FILES_REL = $(patsubst %, ../%, $(XDC_FILES)) 46 | else 47 | XDC_FILES_REL = $(FPGA_TOP).xdc 48 | endif 49 | 50 | ################################################################### 51 | # Main Targets 52 | # 53 | # all: build everything 54 | # clean: remove output files and project files 55 | ################################################################### 56 | 57 | all: fpga 58 | 59 | fpga: $(FPGA_TOP).bit 60 | 61 | tmpclean: 62 | -rm -rf *.log *.jou *.cache *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v 63 | -rm -rf create_project.tcl run_synth.tcl run_impl.tcl generate_bit.tcl 64 | 65 | clean: tmpclean 66 | -rm -rf *.bit 67 | 68 | ################################################################### 69 | # Target implementations 70 | ################################################################### 71 | 72 | # Vivado project file 73 | %.xpr: Makefile $(XCI_FILES_REL) 74 | rm -rf defines.v 75 | touch defines.v 76 | for x in $(DEFS); do echo '`define' $$x >> defines.v; done 77 | echo "create_project -force -part $(FPGA_PART) $*" > create_project.tcl 78 | echo "add_files -fileset sources_1 defines.v" >> create_project.tcl 79 | for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done 80 | for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done 81 | for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done 82 | echo "exit" >> create_project.tcl 83 | $(VIVADO) -mode batch -source create_project.tcl 84 | 85 | # synthesis run 86 | %.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) 87 | echo "open_project $*.xpr" > run_synth.tcl 88 | echo "reset_run synth_1" >> run_synth.tcl 89 | echo "launch_runs synth_1" >> run_synth.tcl 90 | echo "wait_on_run synth_1" >> run_synth.tcl 91 | echo "exit" >> run_synth.tcl 92 | $(VIVADO) -mode batch -source run_synth.tcl 93 | 94 | # implementation run 95 | %.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp 96 | echo "open_project $*.xpr" > run_impl.tcl 97 | echo "reset_run impl_1" >> run_impl.tcl 98 | echo "launch_runs impl_1" >> run_impl.tcl 99 | echo "wait_on_run impl_1" >> run_impl.tcl 100 | echo "exit" >> run_impl.tcl 101 | $(VIVADO) -mode batch -source run_impl.tcl 102 | 103 | # bit file 104 | %.bit: %.runs/impl_1/%_routed.dcp 105 | echo "open_project $*.xpr" > generate_bit.tcl 106 | echo "open_run impl_1" >> generate_bit.tcl 107 | echo "write_bitstream -force $*.bit" >> generate_bit.tcl 108 | echo "exit" >> generate_bit.tcl 109 | $(VIVADO) -mode batch -source generate_bit.tcl 110 | cp $@ ../$@ 111 | 112 | -------------------------------------------------------------------------------- /xdc/a7_mtfb.xdc: -------------------------------------------------------------------------------- 1 | 2 | ## Clock signal 32 MHz 3 | set_property -dict {PACKAGE_PIN C16 IOSTANDARD LVCMOS33} [get_ports sys_clk] 4 | ##create_clock -period 20.000 -name clkin_pin -waveform {0.000 10.000} -add [get_ports sys_clk]; 5 | create_clock -period 31.250 -name clkin_pin -waveform {0.000 15.625} -add [get_ports sys_clk] 6 | 7 | ## FPGA LEDS 8 | set_property -dict {PACKAGE_PIN U1 IOSTANDARD LVCMOS33} [get_ports LED1] 9 | set_property -dict {PACKAGE_PIN T1 IOSTANDARD LVCMOS33} [get_ports LED2] 10 | 11 | ## DVI 12 | set_property -dict {PACKAGE_PIN K2 IOSTANDARD TMDS_33} [get_ports {TMDS[0]}] 13 | set_property -dict {PACKAGE_PIN L2 IOSTANDARD TMDS_33} [get_ports {TMDSB[0]}] 14 | set_property -dict {PACKAGE_PIN J3 IOSTANDARD TMDS_33} [get_ports {TMDS[1]}] 15 | set_property -dict {PACKAGE_PIN K3 IOSTANDARD TMDS_33} [get_ports {TMDSB[1]}] 16 | set_property -dict {PACKAGE_PIN M2 IOSTANDARD TMDS_33} [get_ports {TMDS[2]}] 17 | set_property -dict {PACKAGE_PIN M1 IOSTANDARD TMDS_33} [get_ports {TMDSB[2]}] 18 | set_property -dict {PACKAGE_PIN H2 IOSTANDARD TMDS_33} [get_ports {TMDS[3]}] 19 | set_property -dict {PACKAGE_PIN J2 IOSTANDARD TMDS_33} [get_ports {TMDSB[3]}] 20 | 21 | ## SD CARD 22 | set_property -dict {PACKAGE_PIN A16 IOSTANDARD LVCMOS33} [get_ports {SS[0]}] 23 | set_property -dict {PACKAGE_PIN B16 IOSTANDARD LVCMOS33} [get_ports {MOSI[0]}] 24 | set_property -dict {PACKAGE_PIN A14 IOSTANDARD LVCMOS33} [get_ports {MISO[0]}] 25 | set_property -dict {PACKAGE_PIN A15 IOSTANDARD LVCMOS33} [get_ports {SCLK[0]}] 26 | set_property PULLUP true [get_ports {MISO[0]}] 27 | 28 | ## nRF24 29 | set_property -dict {PACKAGE_PIN W4 IOSTANDARD LVCMOS33} [get_ports {SS[1]}] 30 | set_property -dict {PACKAGE_PIN W3 IOSTANDARD LVCMOS33} [get_ports {MOSI[1]}] 31 | set_property -dict {PACKAGE_PIN V3 IOSTANDARD LVCMOS33} [get_ports {MISO[1]}] 32 | set_property -dict {PACKAGE_PIN U3 IOSTANDARD LVCMOS33} [get_ports {SCLK[1]}] 33 | set_property -dict {PACKAGE_PIN V4 IOSTANDARD LVCMOS33} [get_ports NEN] 34 | set_property PULLUP true [get_ports {MISO[1]}] 35 | 36 | 37 | ## UART 38 | set_property -dict {PACKAGE_PIN G18 IOSTANDARD LVCMOS33} [get_ports RxD] 39 | set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports TxD] 40 | set_property PULLUP true [get_ports RxD] 41 | 42 | ## KBD 43 | set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports PS2D] 44 | set_property -dict {PACKAGE_PIN K17 IOSTANDARD LVCMOS33} [get_ports PS2C] 45 | set_property PULLUP true [get_ports PS2D] 46 | set_property PULLUP true [get_ports PS2C] 47 | 48 | ## MOUSE 49 | set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS33} [get_ports msdat] 50 | set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports msclk] 51 | set_property PULLUP true [get_ports msdat] 52 | set_property PULLUP true [get_ports msclk] 53 | 54 | ## DIP SWITCH 55 | set_property -dict {PACKAGE_PIN N17 IOSTANDARD LVCMOS33} [get_ports {swi[0]}] 56 | set_property -dict {PACKAGE_PIN R18 IOSTANDARD LVCMOS33} [get_ports {swi[1]}] 57 | set_property -dict {PACKAGE_PIN P18 IOSTANDARD LVCMOS33} [get_ports {swi[2]}] 58 | set_property -dict {PACKAGE_PIN T18 IOSTANDARD LVCMOS33} [get_ports {swi[3]}] 59 | set_property PULLDOWN true [get_ports {swi[0]}] 60 | set_property PULLDOWN true [get_ports {swi[1]}] 61 | set_property PULLDOWN true [get_ports {swi[2]}] 62 | set_property PULLDOWN true [get_ports {swi[3]}] 63 | 64 | ## SWITCH 65 | set_property -dict {PACKAGE_PIN T17 IOSTANDARD LVCMOS33} [get_ports SWITCH] 66 | set_property PULLDOWN true [get_ports SWITCH] 67 | 68 | ## LEDS 69 | set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports {leds[7]}] 70 | set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports {leds[6]}] 71 | set_property -dict {PACKAGE_PIN V17 IOSTANDARD LVCMOS33} [get_ports {leds[5]}] 72 | set_property -dict {PACKAGE_PIN V16 IOSTANDARD LVCMOS33} [get_ports {leds[4]}] 73 | set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS33} [get_ports {leds[3]}] 74 | set_property -dict {PACKAGE_PIN U15 IOSTANDARD LVCMOS33} [get_ports {leds[2]}] 75 | set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports {leds[1]}] 76 | set_property -dict {PACKAGE_PIN V13 IOSTANDARD LVCMOS33} [get_ports {leds[0]}] 77 | 78 | ## SD LED 79 | set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports LED5] 80 | 81 | ## GPIO 82 | set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports {gpio[7]}] 83 | set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports {gpio[6]}] 84 | set_property -dict {PACKAGE_PIN W15 IOSTANDARD LVCMOS33} [get_ports {gpio[5]}] 85 | set_property -dict {PACKAGE_PIN W16 IOSTANDARD LVCMOS33} [get_ports {gpio[4]}] 86 | set_property -dict {PACKAGE_PIN W17 IOSTANDARD LVCMOS33} [get_ports {gpio[3]}] 87 | set_property -dict {PACKAGE_PIN W18 IOSTANDARD LVCMOS33} [get_ports {gpio[2]}] 88 | set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports {gpio[1]}] 89 | set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports {gpio[0]}] 90 | 91 | ## PSRAM 92 | set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33} [get_ports psram_ce] 93 | set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS33} [get_ports psram_sio3] 94 | set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports psram_sio1] 95 | set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports psram_sclk] 96 | set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS33} [get_ports psram_sio2] 97 | set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS33} [get_ports psram_sio0] 98 | 99 | 100 | ##set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS33} [get_ports spi_ss] 101 | ##set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports spi_mosi] 102 | ##set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports spi_miso] 103 | 104 | set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design] 105 | set_property CONFIG_VOLTAGE 3.3 [current_design] 106 | set_property CFGBVS VCCO [current_design] 107 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 108 | 109 | 110 | set_false_path -from [get_pins cache/raddr_reg*/C] -to [get_pins cache/mem/byte*/mem_reg/ADDRBWRADDR*] 111 | set_false_path -from [get_pins cache/mru_reg*/C] -to [get_pins cache/mem/byte*/mem_reg/ADDRBWRADDR*] 112 | --------------------------------------------------------------------------------