From a76977af62010a392c16010c367185e61e856ffe Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 30 Oct 2019 20:04:56 +0100 Subject: mv to docs --- docs/j1eforth/fpga/src/j1.v | 199 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 docs/j1eforth/fpga/src/j1.v (limited to 'docs/j1eforth/fpga/src/j1.v') diff --git a/docs/j1eforth/fpga/src/j1.v b/docs/j1eforth/fpga/src/j1.v new file mode 100644 index 0000000..db8901a --- /dev/null +++ b/docs/j1eforth/fpga/src/j1.v @@ -0,0 +1,199 @@ +/* +Copyright (c) 2011 + James Bowman All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of James Bowman nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ + +module j1( + input sys_clk_i, input sys_rst_i, input [15:0] io_din, + output io_rd, output io_wr, output [15:0] io_addr, output [15:0] io_dout); + + reg [15:0] insn; + wire [15:0] immediate = { 1'b0, insn[14:0] }; + + reg [4:0] dsp; // Data stack pointer + reg [4:0] _dsp; + reg [15:0] st0; // Return stack pointer + reg [15:0] _st0; + wire _dstkW; // D stack write + + reg [12:0] pc; + reg [12:0] _pc; + reg [4:0] rsp; + reg [4:0] _rsp; + reg _rstkW; // R stack write + reg [15:0] _rstkD; + wire _ramWE; // RAM write enable + + wire [15:0] pc_plus_1; + assign pc_plus_1 = pc + 1; + + // The D and R stacks + reg [15:0] dstack[0:31]; + reg [15:0] rstack[0:31]; + always @(posedge sys_clk_i) + begin + if (_dstkW) + dstack[_dsp] = st0; + if (_rstkW) + rstack[_rsp] = _rstkD; + end + wire [15:0] st1 = dstack[dsp]; + wire [15:0] rst0 = rstack[rsp]; + + // st0sel is the ALU operation. For branch and call the operation + // is T, for 0branch it is N. For ALU ops it is loaded from the instruction + // field. + reg [3:0] st0sel; + always @* + begin + case (insn[14:13]) + 2'b00: st0sel = 0; // ubranch + 2'b10: st0sel = 0; // call + 2'b01: st0sel = 1; // 0branch + 2'b11: st0sel = insn[11:8]; // ALU + default: st0sel = 4'bxxxx; + endcase + end + + + // Papilio Pro: main memory to be infered instead of specified explitely. + reg [15:0] ram[0:16383]; initial $readmemh("../j1.hex", ram); + + reg [15:0] mem_din; + always @(posedge sys_clk_i) begin + // $monitor("insn_addr= %h, insn = %h, sp=%h, rp=%h, S=%h %h", pc, insn, dsp, rsp, st1, st0); + insn <= ram[_pc]; + mem_din <= ram[_st0[15:1]]; + if (_ramWE & (_st0[15:14] ==0)) + ram[_st0[15:1]] <= st1[15:0]; + end + + + // Compute the new value of T. + always @* + begin + if (insn[15]) + _st0 = immediate; + else + case (st0sel) + 4'b0000: _st0 = st0; + 4'b0001: _st0 = st1; + 4'b0010: _st0 = st0 + st1; + 4'b0011: _st0 = st0 & st1; + 4'b0100: _st0 = st0 | st1; + 4'b0101: _st0 = st0 ^ st1; + 4'b0110: _st0 = ~st0; + 4'b0111: _st0 = {16{(st1 == st0)}}; + 4'b1000: _st0 = {16{($signed(st1) < $signed(st0))}}; + 4'b1001: _st0 = st1 >> st0[3:0]; + 4'b1010: _st0 = st0 - 1; + 4'b1011: _st0 = rst0; + 4'b1100: _st0 = |st0[15:14] ? io_din : mem_din; + 4'b1101: _st0 = st1 << st0[3:0]; + 4'b1110: _st0 = {rsp, 3'b000, dsp}; + 4'b1111: _st0 = {16{(st1 < st0)}}; + default: _st0 = 16'hxxxx; + endcase + end + + wire is_alu = (insn[15:13] == 3'b011); + wire is_lit = (insn[15]); + + assign io_rd = (is_alu & (insn[11:8] == 4'hc)); + assign io_wr = _ramWE; + assign io_addr = st0; + assign io_dout = st1; + + assign _ramWE = is_alu & insn[5]; + assign _dstkW = is_lit | (is_alu & insn[7]); + + wire [1:0] dd = insn[1:0]; // D stack delta + wire [1:0] rd = insn[3:2]; // R stack delta + + always @* + begin + if (is_lit) begin // literal + _dsp = dsp + 1; + _rsp = rsp; + _rstkW = 0; + _rstkD = _pc; + end else if (is_alu) begin + _dsp = dsp + {dd[1], dd[1], dd[1], dd}; + _rsp = rsp + {rd[1], rd[1], rd[1], rd}; + _rstkW = insn[6]; + _rstkD = st0; + end else begin // jump/call + // predicated jump is like DROP + if (insn[15:13] == 3'b001) begin + _dsp = dsp - 1; + end else begin + _dsp = dsp; + end + if (insn[15:13] == 3'b010) begin // call + _rsp = rsp + 1; + _rstkW = 1; + _rstkD = {pc_plus_1[14:0], 1'b0}; + end else begin + _rsp = rsp; + _rstkW = 0; + _rstkD = _pc; + end + end + end + + always @* + begin + if (sys_rst_i) + _pc = pc; + else + if ((insn[15:13] == 3'b000) | + ((insn[15:13] == 3'b001) & (|st0 == 0)) | + (insn[15:13] == 3'b010)) + _pc = insn[12:0]; + else if (is_alu & insn[12]) + _pc = rst0[15:1]; + else + _pc = pc_plus_1; + end + + always @(posedge sys_clk_i) + begin + if (sys_rst_i) begin + pc <= 0; + dsp <= 0; + st0 <= 0; + rsp <= 0; + end else begin + dsp <= _dsp; + pc <= _pc; + st0 <= _st0; + rsp <= _rsp; + end + end + +endmodule // j1 -- cgit v1.2.3