gateware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit ab5cc9ce5f7b503cbe762a15c3e71729c917fa18
parent 59efd750e9acc57dbbe70fb1e8bbbbcab987bdbb
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun,  2 Dec 2018 23:06:24 -0800

cleanup: remove old v3 cpu impl and v3/v4 isa docs

- the v3 cpu was never fully operational
- the old docs are not terribly useful

Diffstat:
Ddocs/isa16v3.txt | 66------------------------------------------------------------------
Ddocs/isa16v4.txt | 37-------------------------------------
Dhdl/cpu/alu.v | 53-----------------------------------------------------
Dhdl/cpu/cpu.v | 388-------------------------------------------------------------------------------
Dhdl/cpu/regfile.v | 29-----------------------------
5 files changed, 0 insertions(+), 573 deletions(-)

diff --git a/docs/isa16v3.txt b/docs/isa16v3.txt @@ -1,66 +0,0 @@ - -Basic Instructions Assembly Syntax Operation ---------------------- -------------------- ----------------------------- -iiii iiii aaaa 0000 mov Ra, si8 Ra = si8 -iiii iiii aaaa 0001 mhi Ra, si8 Ra = (Ra & 0xFF) | (si8 << 8) -ffff bbbb aaaa 0010 alu Ra, Ra, Rb Ra = Ra <fn> Rb -iiii ffff aaaa 0011 alu Ra, Ra, si4 Ra = Ra <fn> si4 -ffff bbbb aaaa 01cc alu Rc, Ra, Rb Rc = Ra <fn> Rb -iiii bbbb aaaa 1000 lw Ra, [Rb, si4] Ra = [Rb + si4] -iiii bbbb aaaa 1001 sw Ra, [Rb, si4] [Rb + si4] = Ra -iiii iiii aaaa 1010 bnz Ra, si8 if (Ra != 0) PC += si8 -iiii iiii aaaa 1011 bz Ra, si8 if (Ra == 0) PC += si8 -iiii iiii iiii 1100 b si12 PC += si12 -iiii iiii iiii 1101 bl si12 R14 = PC, PC += si12, -0000 bbbb xxxx 1110 b Rb PC = Rb -0001 bbbb xxxx 1110 bl Rb R14 = PC, PC = Rb -0010 0000 0000 1110 nop -0010 nnnn aaaa 1110 debug Ra, x4 DEBUG(Ra, n4) - -Extended Instructions <--- Not implemented yet. ---------------------- Will likely change during -0011 xxxx xxxx 1110 iret implementation. -0100 nnnn aaaa 1110 mov Ra, Sn -0101 nnnn aaaa 1110 mov Sn, Ra -0110 aaaa bbbb 1110 mov Ra', Rb -0111 aaaa bbbb 1110 mov Ra, Rb' -1xxx xxxx xxxx 1110 undefined -nnnn nnnn 0000 1111 syscall n -nnnn nnnn 0001 1111 break; -nnnn nnnn 0010 1111 set <flags> -nnnn nnnn 0011 1111 clr <flags> -xxxx xxxx 0011 1111 undefined -xxxx xxxx 01xx 1111 undefined -xxxx xxxx 1xxx 1111 undefined - -ALU Functions (<fn>) Key --------------------------------------- ---------------------------------- -0000 mov r = b si4 signed 4bit immediate -0001 and r = a & b si8 signed 8bit immediate -0010 orr r = a | b si12 signed 12bit immediate -0011 xor r = a ^ b fn ALU function -0100 add r = a + b R0-R15 general purpose registers -0101 sub r = a - b PC program counter -0110 mul r = a * b -0111 mhi r = (b << 8) | (a & 0xFF) S0-S15 system control registers -1000 slt r = a < b F0-F7 system flag bits -1001 sle r = a <= b R0'-R15' banked registers -1010 shr r = a >> 1 -1011 shl r = a << 1 -1100 bis r = a | (1 << b[3:0]) -1101 bic r = a & (~(1 << b[3:0])) -1110 tbs r = a & (1 << b[3:0]) -1111 bit r = 1 << b[3:0] - -Register Usage / Procedure Call Standard ------------------------------------------ -R0 - R3 parameters & results -R4 - R11 caller save, working variables -R12 reserved for OS/runtime global use -R13 stack pointer -R14 link register* (for branch-and-link) -R15 scratch (for assembler/linker use) - -* The processor can *only* save PC to R14 on BL calls. - All other register assignements are merely to simplify - software interworking, not required by the architecture. diff --git a/docs/isa16v4.txt b/docs/isa16v4.txt @@ -1,37 +0,0 @@ -instruction formats constant encodings alu opcodes ------------------------ ------------------- -------------------- - FED CBA 987 654 3210 000 add R = A + B -A fff bbb aaa ccc 0ooo 001 sub R = A - B -B sii iii aaa ccc 0ooo si6 siiiii 010 and R = A & B -C sii iii kkk ccc 0ooo si9 skkkiiiii 011 or R = A | B -D sii iii xjj jjj 0ooo si11 sjjjjjiiiii 100 xor R = A ^ B -E sii iii aaa mxx 0ooo si7 smiiiii 101 slt R = A < B -F sii iii aaa ccc 1fff si6 siiiii 110 sge R = A >= B -G sii iii jjj jjj 0ooo si12 sjjjjjjiiiii 111 mul R = A * B - -instruction encodings ---------------------- -A 0000 alu Rc, Ra, Rb Rc = Ra <fn> Rb -? 0001 <expansion> -G 0010 ext si12 Ex = 1*, Ev = si12[11:0] -C 0011 mov Rc, si9 Rc = Ex ? { Ev, si9[3:0] } : si9 -B 0100 lw Rc, [Ra, si6] Rc = mem[Ra + si6] -B 0101 sw Rc, [Ra, si6] mem[Ra + si6] = Rc -D 0110 0 b si11 PC = PC + si11 -D 0110 1 bl si11 R7 = PC + 1, PC = PC + si11 -E 0111 00 bz Ra, si7 (Ra == 0) ? PC = PC + si7 -E 0111 01 bnz Ra, si7 (Ra != 0) ? PC = PC + si7 -E 0111 10 b Ra PC = Ra -E 0111 11 bl Ra R7 = PC + 1, PC = Ra -F 1fff alu Rc, Ra, si6 Rc = Ra <fn> ( Ex ? { Ev, si6[3:0] } : si6 ) - -* Ex reset to 0 after all ops but "ext" - -notes ------ -- consider changing ext to use si10 instead and the reclaimed two bits - to open up more instruction set space -- consider allowing ext to work with b/bl and/or bz/bnz for long branches -- in which case maybe si11->si10 and compact branch instruction footprint - a bit too - diff --git a/hdl/cpu/alu.v b/hdl/cpu/alu.v @@ -1,53 +0,0 @@ -// Copyright 2015, Brian Swetland <swetland@frotz.net> -// Licensed under the Apache License, Version 2.0. - -`timescale 1ns / 1ps - -module alu #( - parameter DWIDTH = 16, - parameter SWIDTH = 4 - )( - input [3:0]op, - input [DWIDTH-1:0]adata, - input [DWIDTH-1:0]bdata, - output reg[DWIDTH-1:0]rdata - ); - -`ifdef BIT_OPS -wire [DWIDTH-1:0]bits = (1 << bdata[SWIDTH-1:0]); -`endif - -always @(*) begin - case (op) - 4'b0000: rdata = bdata; - 4'b0001: rdata = adata & bdata; - 4'b0010: rdata = adata | bdata; - 4'b0011: rdata = adata ^ bdata; - 4'b0100: rdata = adata + bdata; - 4'b0101: rdata = adata - bdata; - 4'b0110: rdata = adata * bdata; - 4'b0111: rdata = { bdata[7:0], adata[7:0] }; - 4'b1000: rdata = { {(DWIDTH-1){1'b0}}, adata < bdata }; - 4'b1001: rdata = { {(DWIDTH-1){1'b0}}, adata <= bdata }; -`ifdef FULL_SHIFTER - 4'b1010: rdata = adata >> bdata[SWIDTH-1:0]; - 4'b1011: rdata = adata << bdata[SWIDTH-1:0]; -`else - 4'b1010: rdata = { 1'b0, adata[DWIDTH-1:1] }; - 4'b1011: rdata = { adata[DWIDTH-2:0], 1'b0 }; -`endif -`ifdef BIT_OPS - 4'b1100: rdata = adata | bits; - 4'b1101: rdata = adata & (~bits); - 4'b1110: rdata = adata & bits; - 4'b1111: rdata = bits; -`else - 4'b1100: rdata = {DWIDTH{1'bX}}; - 4'b1101: rdata = {DWIDTH{1'bX}}; - 4'b1110: rdata = {DWIDTH{1'bX}}; - 4'b1111: rdata = {DWIDTH{1'bX}}; -`endif - endcase -end - -endmodule diff --git a/hdl/cpu/cpu.v b/hdl/cpu/cpu.v @@ -1,388 +0,0 @@ -// Copyright 2015, Brian Swetland <swetland@frotz.net> -// Licensed under the Apache License, Version 2.0. - -`timescale 1ns / 1ps - -module cpu #( - parameter RWIDTH = 16, - parameter SWIDTH = 4 - )( - input clk, -`ifdef WITH_DEBUG - output [RWIDTH-1:0]debug_data - output [3:0]debug_op, - output debug_wr, -`endif - output [15:0]mem_raddr_o, - input [15:0]mem_rdata_i, - output [15:0]mem_waddr_o, - output [15:0]mem_wdata_o, - output mem_wr_o, - output mem_rd_o, - input reset - ); - -localparam AWIDTH = 16; -localparam DWIDTH = 16; -localparam IWIDTH = 16; - -// control signals -reg do_fetch; -reg do_load; -reg do_store; -wire do_wreg; -reg [1:0]do_sel_bdata; -reg [1:0]do_sel_wsel; -reg [1:0]do_sel_branch; -reg [1:0]do_sel_alu_op; -reg do_exe_alu; -reg do_exe_load; -reg do_exe_branch; -reg do_load_pc; - -// processor registers -reg [AWIDTH-1:0]pc = 16'b0; -reg [15:0]ir = 16'b0; -reg ir_valid = 1'b0; -reg ir_loading = 1'b0; - -reg [AWIDTH-1:0]pc_next; -reg [15:0]ir_next; -reg ir_valid_next; -reg ir_loading_next; - -// registers that allow/disallow EXEC/LOAD and IMMEDIATE -reg exe_alu = 1'b0; -reg exe_load = 1'b0; -reg exe_branch = 1'b0; - -// registers loaded during DECODE for use in EXEC/LOAD -reg [3:0]alu_op = 4'b0; -reg [RWIDTH-1:0]adata = 16'b0; -reg [RWIDTH-1:0]bdata = 16'b0; -reg [3:0]wsel = 4'b0; - -// in/out of alu -wire [RWIDTH-1:0]alu_rdata; - -// values computed -wire [3:0]ir_asel = ir[7:4]; -wire [3:0]ir_bsel = ir[11:8]; -wire [RWIDTH-1:0]ir_imm_s4 = { {(RWIDTH-3) {ir[15]}}, ir[14:12] }; -wire [RWIDTH-1:0]ir_imm_s8 = { {(RWIDTH-7) {ir[15]}}, ir[14:8] }; -wire [RWIDTH-1:0]ir_imm_s12 = { {(RWIDTH-11){ir[15]}}, ir[14:4] }; - -// in/out of reg file -wire [3:0]regs_asel = ir_asel; -wire [3:0]regs_bsel = ir_bsel; -wire [RWIDTH-1:0]regs_wdata = exe_load ? { {(RWIDTH-DWIDTH){1'b0}}, mem_rdata_i } : alu_rdata; -wire [RWIDTH-1:0]regs_adata; -wire [RWIDTH-1:0]regs_bdata; - -wire [RWIDTH-1:0]load_store_addr = regs_bdata + ir_imm_s4; - -wire [AWIDTH-1:0]new_pc = exe_branch ? branch_target : (pc + 16'd1); - -reg [AWIDTH-1:0]branch_target; - -localparam BR_REL_S8 = 2'b00; // PC + S8 a short branch -localparam BR_REL_S12 = 2'b01; // PC + S12 a long branch -localparam BR_ABS_RB = 2'b10; // RB an indirect branch - -wire [RWIDTH-1:0]branch_imm = do_sel_branch[0] ? ir_imm_s12 : ir_imm_s8; -wire [RWIDTH-1:0]branch_tgt = do_sel_branch[1] ? regs_bdata : (pc + branch_imm); -wire [AWIDTH-1:0]branch_target_next = branch_tgt[AWIDTH-1:0]; - -// memory interface -assign mem_wr_o = do_store; -assign mem_rd_o = 1; -assign mem_raddr_o = do_load ? load_store_addr[AWIDTH-1:0] : pc_next; -assign mem_waddr_o = load_store_addr[AWIDTH-1:0]; -assign mem_wdata_o = regs_adata[AWIDTH-1:0]; - -always_comb begin - ir_next = ir; - ir_valid_next = ir_valid; - ir_loading_next = ir_loading; - - do_load_pc = 1'b0; - - // we try to read an instruction every cycle - // unless we're pre-empted by a data load - //XXX don't issue a read if we know it's useless? - ir_loading_next = ~do_load; - - if (exe_branch) begin - // branch is always highest priority - ir_valid_next = 1'b0; - do_load_pc = 1'b1; - end else if (ir_loading) begin - // we've read an instruction - if ((~ir_valid) | do_fetch) begin - // ir was empty or is being consumed - // fill it with the just-read instruction - // and advance the pc - ir_next = mem_rdata_i; - ir_valid_next = 1'b1; - do_load_pc = 1'b1; - end else if (do_fetch) begin - // ir has been consumed if it was non-empty - ir_valid_next = 1'b0; - end - end else begin - // not loading - if (do_fetch) begin - ir_valid_next = 1'b0; - end - end - - pc_next = do_load_pc ? new_pc : pc; -end - -/* -always_ff @(posedge clk) begin - pc <= reset ? 16'd0 : pc_next; - ir_valid <= reset ? 1'd0 : ir_valid_next; - ir_loading <= reset ? 1'd0 : ir_loading_next; - ir <= ir_next; -end -*/ - -always_ff @(posedge clk) begin - if (reset) begin - pc <= 16'd0; - ir_valid <= 1'd0; - ir_loading <= 1'd0; - end else begin - pc <= pc_next; - ir_valid <= ir_valid_next; - ir_loading <= ir_loading_next; - end - ir <= ir_next; -end - -localparam BDATA_RB = 2'b00; -localparam BDATA_PC = 2'b01; -localparam BDATA_S4 = 2'b10; -localparam BDATA_S8 = 2'b11; -reg [RWIDTH-1:0]bdata_mux; -always_comb begin - case (do_sel_bdata) - BDATA_RB: bdata_mux = regs_bdata; - BDATA_PC: bdata_mux = pc; - BDATA_S4: bdata_mux = ir_imm_s4; - BDATA_S8: bdata_mux = ir_imm_s8; - endcase -end - -localparam WSEL_RA = 2'b00; -localparam WSEL_RB = 2'b01; -localparam WSEL_OP = 2'b10; -localparam WSEL_LR = 2'b11; -reg [3:0]wsel_mux; -always_comb begin - case (do_sel_wsel) - WSEL_RA: wsel_mux = ir[7:4]; - WSEL_RB: wsel_mux = ir[11:8]; - WSEL_OP: wsel_mux = { 2'b0, ir[1:0] }; - WSEL_LR: wsel_mux = 4'd14; - endcase -end - -localparam ALU_MOV = 2'b00; -localparam ALU_MHI = 2'b01; -localparam ALU_FN_HI = 2'b10; -localparam ALU_FN_LO = 2'b11; -reg [3:0]alu_op_mux; -always_comb begin - case (do_sel_alu_op) - ALU_MOV: alu_op_mux = 4'b0000; - ALU_MHI: alu_op_mux = 4'b0111; - ALU_FN_HI: alu_op_mux = ir[15:12]; - ALU_FN_LO: alu_op_mux = ir[11:8]; - endcase -end - -wire regs_adata_zero = (regs_adata == 16'd0); - -assign do_wreg = exe_alu | exe_load; - -//`define WITH_BYPASS - -localparam USE_RA = 2'b10; -localparam USE_RB = 2'b01; -localparam USE_RA_RB = 2'b11; -localparam USE_NONE = 2'b00; -reg [1:0]using; -wire conflict_a = (wsel == ir_asel) & using[1]; -wire conflict_b = (wsel == ir_bsel) & using[0]; - -`ifdef WITH_DEBUG -assign debug_op = ir_bsel; -assign debug_data = regs_adata; -assign debug_wr = do_fetch & ir_valid & (ir[15:12] == 4'b0010) & (ir[3:0] == 4'b1110); -`endif - -always_comb begin - // decode stage - do_fetch = 1'b1; - do_load = 1'b0; - do_store = 1'b0; - do_sel_branch = BR_ABS_RB; - do_sel_bdata = BDATA_RB; - do_sel_wsel = WSEL_RA; - do_sel_alu_op = ALU_MOV; - - do_exe_alu = 1'b0; - do_exe_load = 1'b0; - do_exe_branch = 1'b0; - - using = USE_RA_RB; - - if (exe_branch) begin - do_fetch = 1'b0; - end -`ifndef WITH_BYPASS - else if (exe_alu | exe_load) begin - do_fetch = ~(conflict_a | conflict_b); - end -`endif - - casez (ir[3:0]) - 4'b0000: begin // mov Ra, imm - using = USE_NONE; - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_MOV; - do_sel_wsel = WSEL_RA; - do_sel_bdata = BDATA_S8; - end - 4'b0001: begin // mhi Ra, imm - using = USE_RA; - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_MHI; - do_sel_wsel = WSEL_RA; - do_sel_bdata = BDATA_S8; - end - 4'b0010: begin // alu Ra, Ra, Rb - using = USE_RA_RB; - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_FN_HI; - do_sel_wsel = WSEL_RA; - do_sel_bdata = BDATA_RB; - end - 4'b0011: begin // alu Ra, Ra, imm4 - using = USE_RA; - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_FN_LO; - do_sel_wsel = WSEL_RA; - do_sel_bdata = BDATA_S4; - end - 4'b01??: begin // alu Rd, Ra, Rb - using = USE_RA_RB; - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_FN_HI; - do_sel_wsel = WSEL_OP; - do_sel_bdata = BDATA_RB; - end - 4'b1000: begin // lw Ra, [Rb, imm] - using = USE_RB; - do_exe_load = 1'b1; - do_load = ir_valid; - end - 4'b1001: begin // sw Ra, [Rb, imm] - using = USE_RA_RB; - do_store = ir_valid; - end - 4'b1010: begin // bnz Ra, rel8 - using = USE_RA; - do_exe_branch = ~regs_adata_zero; - do_sel_branch = BR_REL_S8; - end - 4'b1011: begin // bz Ra, rel8 - using = USE_RA; - do_exe_branch = regs_adata_zero; - do_sel_branch = BR_REL_S8; - end - 4'b1100: begin // b rel12 - using = USE_NONE; - do_exe_branch = 1'b1; - do_sel_branch = BR_REL_S12; - end - 4'b1101: begin // bl rel12 - using = USE_NONE; - do_exe_alu = 1'b1; - do_exe_branch = 1'b1; - do_sel_branch = BR_REL_S12; - do_sel_alu_op = ALU_MOV; - do_sel_bdata = BDATA_PC; - do_sel_wsel = WSEL_LR; - end - 4'b1110: begin - if (ir[15:13] == 3'b000) begin // b Rb / bl Rb - using = USE_RB; - do_exe_branch = 1'b1; - do_sel_branch = BR_ABS_RB; - if (ir[12]) begin - do_exe_alu = 1'b1; - do_sel_alu_op = ALU_MOV; - do_sel_bdata = BDATA_PC; - do_sel_wsel = WSEL_LR; - end - end - end - default: begin - // treat undefined as NOP - end - endcase -end - -always_ff @(posedge clk) begin - alu_op <= alu_op_mux; - adata <= regs_adata; - bdata <= bdata_mux; - wsel <= wsel_mux; - exe_alu <= ir_valid & do_fetch & do_exe_alu; - exe_load <= ir_valid & do_fetch & do_exe_load; - exe_branch <= ir_valid & do_fetch & do_exe_branch; - branch_target <= branch_target_next; - -end - -wire [RWIDTH-1:0]raw_regs_adata; -wire [RWIDTH-1:0]raw_regs_bdata; - -regfile #( - .DWIDTH(RWIDTH) - )regs( - .clk(clk), - .asel(regs_asel), - .bsel(regs_bsel), - .adata(raw_regs_adata), - .bdata(raw_regs_bdata), - .wsel(wsel), - .wdata(regs_wdata), - .wreg(do_wreg) - ); - -`ifdef WITH_BYPASS -wire bypass_a = do_wreg & (wsel == ir_asel) & (~exe_load); -wire bypass_b = do_wreg & (wsel == ir_bsel) & (~exe_load); -assign regs_adata = bypass_a ? regs_wdata : raw_regs_adata; -assign regs_bdata = bypass_b ? regs_wdata : raw_regs_bdata; -`else -assign regs_adata = raw_regs_adata; -assign regs_bdata = raw_regs_bdata; -`endif - -alu #( - .DWIDTH(RWIDTH), - .SWIDTH(SWIDTH) - )alu0( - .op(alu_op), - .adata(adata), - .bdata(bdata), - .rdata(alu_rdata) - ); - -endmodule - diff --git a/hdl/cpu/regfile.v b/hdl/cpu/regfile.v @@ -1,29 +0,0 @@ -// Copyright 2015, Brian Swetland <swetland@frotz.net> -// Licensed under the Apache License, Version 2.0. - -`timescale 1ns / 1ps - -module regfile #( - parameter AWIDTH = 4, - parameter DWIDTH = 16 - )( - input clk, - input [AWIDTH-1:0]asel, - input [AWIDTH-1:0]bsel, - input [AWIDTH-1:0]wsel, - input wreg, - output [DWIDTH-1:0]adata, - output [DWIDTH-1:0]bdata, - input [DWIDTH-1:0]wdata - ); - -reg [DWIDTH-1:0] R[0:((1<<AWIDTH)-1)]; - -always @(posedge clk) begin - if (wreg) - R[wsel] <= wdata; -end -assign adata = R[asel]; -assign bdata = R[bsel]; - -endmodule