heck
This commit is contained in:
parent
0794824fcd
commit
51ecf47862
144
src/beepo.v
144
src/beepo.v
|
@ -14,6 +14,7 @@ module Beepo #(
|
||||||
localparam FETCHI = 1; // Instruction is fetched, start fetching first argument
|
localparam FETCHI = 1; // Instruction is fetched, start fetching first argument
|
||||||
localparam FETCHA = 2; // Argument byte is fetched
|
localparam FETCHA = 2; // Argument byte is fetched
|
||||||
localparam EXEC = 3; // Start running
|
localparam EXEC = 3; // Start running
|
||||||
|
localparam MEMR = 4; // Transferring bytes between memory and registers
|
||||||
localparam DONE = 7; // Done executing
|
localparam DONE = 7; // Done executing
|
||||||
|
|
||||||
// Argument types
|
// Argument types
|
||||||
|
@ -33,13 +34,12 @@ module Beepo #(
|
||||||
localparam NUM_REGS = 4;
|
localparam NUM_REGS = 4;
|
||||||
|
|
||||||
reg [2:0] r_state = IDLE;
|
reg [2:0] r_state = IDLE;
|
||||||
reg r_fetching = 0; // counter for waiting before reading from memory
|
|
||||||
reg [63:0] r_tick = 0;
|
reg [63:0] r_tick = 0;
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
reg [63:0] r_pc = PC_START; // program counter
|
reg [63:0] r_pc = PC_START; // program counter
|
||||||
reg [63:0] r_pc_latch = PC_START; // address input to ROM
|
reg [63:0] r_pc_latch = PC_START; // address input to ROM
|
||||||
reg [63:0] r_registers [0:NUM_REGS]; // up to 255 modifiable registers
|
reg [63:0] r_registers [1:NUM_REGS]; // up to 255 modifiable registers
|
||||||
reg [7:0] r_instr; // the current instruction
|
reg [7:0] r_instr; // the current instruction
|
||||||
reg [7:0] r_arg_regs [0:3]; // register arguments
|
reg [7:0] r_arg_regs [0:3]; // register arguments
|
||||||
reg [63:0] r_arg_imm = 0; // immediate argument
|
reg [63:0] r_arg_imm = 0; // immediate argument
|
||||||
|
@ -52,7 +52,16 @@ module Beepo #(
|
||||||
reg [3:0] r_arg_current_type = 8; // the type of the current argument
|
reg [3:0] r_arg_current_type = 8; // the type of the current argument
|
||||||
reg [5:0] r_arg_bit = 0; // the current lower bit index being fetched for the current argument
|
reg [5:0] r_arg_bit = 0; // the current lower bit index being fetched for the current argument
|
||||||
|
|
||||||
wire [7:0] w_mem_fetch;
|
reg r_bus_wre = 0;
|
||||||
|
reg [7:0] r_bus_in = 0;
|
||||||
|
reg [4:0] r_bus_bytes = 1; // the number of bytes to transfer on the bus
|
||||||
|
reg [7:0] r_bus_index = 0; // the index of the byte in transfer
|
||||||
|
reg [7:0] r_bus_reg = 0; // the register currently used in transfer
|
||||||
|
reg r_bus_start = 0; // pulsed high when the bus should start a transfer
|
||||||
|
reg r_bus_trans = 0; // trans rights (the bus is executing a transfer instruction)
|
||||||
|
wire [63:0] w_bus_addr = r_bus_trans ? r_arg_addr : r_pc_latch;
|
||||||
|
wire [4:0] w_bus_bytes = r_bus_trans ? r_bus_bytes : 1;
|
||||||
|
wire [7:0] w_bus_fetch;
|
||||||
|
|
||||||
genvar i;
|
genvar i;
|
||||||
|
|
||||||
|
@ -65,20 +74,23 @@ module Beepo #(
|
||||||
always @(posedge i_clk) r_tick <= r_tick + 1;
|
always @(posedge i_clk) r_tick <= r_tick + 1;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (r_fetching) r_fetching <= r_fetching + 1;
|
if (w_bus_ready == 0) begin
|
||||||
else case (r_state)
|
r_bus_start <= 0;
|
||||||
|
r_bus_trans <= r_bus_trans & ~w_bus_ready;
|
||||||
|
end else case (r_state)
|
||||||
IDLE: begin
|
IDLE: begin
|
||||||
r_pc_latch <= r_pc;
|
r_pc_latch <= r_pc;
|
||||||
r_pc <= r_pc + 1;
|
r_pc <= r_pc + 1;
|
||||||
r_fetching <= 1;
|
r_bus_start <= 1;
|
||||||
r_state <= FETCHI;
|
r_state <= FETCHI;
|
||||||
|
r_bus_wre <= 0;
|
||||||
end
|
end
|
||||||
FETCHI: begin
|
FETCHI: begin
|
||||||
r_instr <= w_mem_fetch;
|
r_instr <= w_bus_fetch;
|
||||||
r_arg_index <= 0;
|
r_arg_index <= 0;
|
||||||
r_arg_bit <= 0;
|
r_arg_bit <= 0;
|
||||||
|
|
||||||
case (w_mem_fetch)
|
case (w_bus_fetch)
|
||||||
`TX: r_arg_types_packed = `TX_ARGS;
|
`TX: r_arg_types_packed = `TX_ARGS;
|
||||||
`NOP: r_arg_types_packed = `NOP_ARGS;
|
`NOP: r_arg_types_packed = `NOP_ARGS;
|
||||||
`ADD8: r_arg_types_packed = `ADD8_ARGS;
|
`ADD8: r_arg_types_packed = `ADD8_ARGS;
|
||||||
|
@ -93,6 +105,8 @@ module Beepo #(
|
||||||
`LI16: r_arg_types_packed = `LI16_ARGS;
|
`LI16: r_arg_types_packed = `LI16_ARGS;
|
||||||
`LI32: r_arg_types_packed = `LI32_ARGS;
|
`LI32: r_arg_types_packed = `LI32_ARGS;
|
||||||
`LI64: r_arg_types_packed = `LI64_ARGS;
|
`LI64: r_arg_types_packed = `LI64_ARGS;
|
||||||
|
`LD: r_arg_types_packed = `LD_ARGS;
|
||||||
|
`ST: r_arg_types_packed = `ST_ARGS;
|
||||||
default: r_arg_types_packed = {ARG_N, ARG_N, ARG_N, ARG_N};
|
default: r_arg_types_packed = {ARG_N, ARG_N, ARG_N, ARG_N};
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
@ -100,7 +114,7 @@ module Beepo #(
|
||||||
r_state <= FETCHA;
|
r_state <= FETCHA;
|
||||||
r_pc_latch <= r_pc;
|
r_pc_latch <= r_pc;
|
||||||
r_pc <= r_pc + 1;
|
r_pc <= r_pc + 1;
|
||||||
r_fetching <= 1;
|
r_bus_start <= 1;
|
||||||
|
|
||||||
r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4];
|
r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4];
|
||||||
r_arg_current_type <= r_arg_types_packed[15:12];
|
r_arg_current_type <= r_arg_types_packed[15:12];
|
||||||
|
@ -122,19 +136,19 @@ module Beepo #(
|
||||||
if (r_arg_current_type == ARG_N) r_state <= IDLE;
|
if (r_arg_current_type == ARG_N) r_state <= IDLE;
|
||||||
else begin
|
else begin
|
||||||
case (r_arg_current_type)
|
case (r_arg_current_type)
|
||||||
ARG_R: r_arg_regs[r_arg_index] <= w_mem_fetch;
|
ARG_R: r_arg_regs[r_arg_index] <= w_bus_fetch;
|
||||||
ARG_O: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_O: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_P: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_P: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_B: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_B: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_H: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_H: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_W: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_W: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_D: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_D: r_arg_imm[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
ARG_A: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
ARG_A: r_arg_addr[r_arg_bit+:8] <= w_bus_fetch;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
r_pc_latch <= r_pc;
|
r_pc_latch <= r_pc;
|
||||||
r_pc <= r_pc + 1;
|
r_pc <= r_pc + 1;
|
||||||
r_fetching <= 1;
|
r_bus_start <= 1;
|
||||||
|
|
||||||
r_arg_bytes = r_arg_bytes - 1;
|
r_arg_bytes = r_arg_bytes - 1;
|
||||||
r_arg_bit <= r_arg_bit + 8;
|
r_arg_bit <= r_arg_bit + 8;
|
||||||
|
@ -143,21 +157,11 @@ module Beepo #(
|
||||||
r_arg_index = r_arg_index + 1;
|
r_arg_index = r_arg_index + 1;
|
||||||
r_arg_current_type = r_arg_types[r_arg_index];
|
r_arg_current_type = r_arg_types[r_arg_index];
|
||||||
|
|
||||||
if (r_arg_current_type == ARG_N) r_state <= EXEC;
|
// Execute when there is no next argument or r_arg_index has overflowed
|
||||||
|
if (r_arg_current_type == ARG_N || r_arg_index == 0) r_state <= EXEC;
|
||||||
else begin
|
else begin
|
||||||
r_arg_bit <= 0;
|
r_arg_bit <= 0;
|
||||||
r_arg_bytes <= ARG_SIZES[r_arg_current_type*4+:4];
|
r_arg_bytes <= ARG_SIZES[r_arg_current_type*4+:4];
|
||||||
|
|
||||||
case (r_arg_current_type)
|
|
||||||
ARG_R: r_arg_regs[r_arg_index] <= 0;
|
|
||||||
ARG_O: r_arg_addr[r_arg_bit-1] <= 0;
|
|
||||||
ARG_P: r_arg_addr[r_arg_bit-1] <= 0;
|
|
||||||
ARG_B: r_arg_imm[r_arg_bit-1] <= 0;
|
|
||||||
ARG_H: r_arg_imm[r_arg_bit-1] <= 0;
|
|
||||||
ARG_W: r_arg_imm[r_arg_bit-1] <= 0;
|
|
||||||
ARG_D: r_arg_imm[r_arg_bit-1] <= 0;
|
|
||||||
ARG_A: r_arg_addr[r_arg_bit-1] <= 0;
|
|
||||||
endcase
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -180,13 +184,57 @@ module Beepo #(
|
||||||
`LI16: set_register(r_arg_regs[0], r_arg_imm);
|
`LI16: set_register(r_arg_regs[0], r_arg_imm);
|
||||||
`LI32: set_register(r_arg_regs[0], r_arg_imm);
|
`LI32: set_register(r_arg_regs[0], r_arg_imm);
|
||||||
`LI64: set_register(r_arg_regs[0], r_arg_imm);
|
`LI64: set_register(r_arg_regs[0], r_arg_imm);
|
||||||
|
`LD: begin
|
||||||
|
if (r_arg_imm > 0) begin
|
||||||
|
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
|
||||||
|
r_bus_index <= 0;
|
||||||
|
r_bus_reg <= r_arg_regs[0];
|
||||||
|
r_state <= MEMR;
|
||||||
|
r_bus_start <= 1;
|
||||||
|
r_bus_trans <= 1;
|
||||||
|
r_bus_bytes <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`ST: begin
|
||||||
|
if (r_arg_imm > 0) begin
|
||||||
|
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
|
||||||
|
r_bus_index <= 0;
|
||||||
|
r_bus_reg <= r_arg_regs[0];
|
||||||
|
r_bus_wre <= 1;
|
||||||
|
r_bus_in <= r_registers[r_arg_regs[0]][0+:8];
|
||||||
|
r_state <= MEMR;
|
||||||
|
r_bus_start <= 1;
|
||||||
|
r_bus_trans <= 1;
|
||||||
|
r_bus_bytes <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
MEMR: begin
|
||||||
|
case (r_instr)
|
||||||
|
`LD: set_register(r_arg_regs[0], w_bus_fetch);
|
||||||
|
`ST: r_bus_in <= r_registers[r_arg_regs[0]][r_bus_index];
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (r_arg_imm == 1) begin
|
||||||
|
// reached the end of the transfer
|
||||||
|
r_bus_wre <= 0;
|
||||||
|
r_state <= FETCHI;
|
||||||
|
end else begin
|
||||||
|
if (r_bus_index == 6) begin
|
||||||
|
// reached the end of this register
|
||||||
|
r_bus_reg <= r_bus_reg + 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
r_arg_addr <= r_arg_addr + 1;
|
||||||
|
r_arg_imm <= r_arg_imm - 1;
|
||||||
|
r_bus_start <= 1;
|
||||||
|
r_bus_trans <= 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
task automatic set_register(
|
task automatic set_register(
|
||||||
input [7:0] being_set,
|
input [7:0] being_set,
|
||||||
input [63:0] setting_to
|
input [63:0] setting_to
|
||||||
|
@ -194,23 +242,29 @@ module Beepo #(
|
||||||
if (being_set != 0) r_registers[being_set] = setting_to;
|
if (being_set != 0) r_registers[being_set] = setting_to;
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
task automatic set_reg_byte(
|
||||||
|
input [7:0] being_set,
|
||||||
|
input [2:0] byte_idx,
|
||||||
|
input [7:0] setting_to
|
||||||
|
);
|
||||||
|
if (being_set != 0) r_registers[being_set][byte_idx*8+:8] = setting_to;
|
||||||
|
endtask
|
||||||
|
|
||||||
Multi7 display (
|
Multi7 display (
|
||||||
.i_clk(i_clk),
|
.i_clk(i_clk),
|
||||||
.i_hex({r_registers[1][15:0]}),
|
.i_hex({r_registers[1][15:0]}),
|
||||||
.o_segments_drive(o_segments_drive),
|
.o_segments_drive(o_segments_drive),
|
||||||
.o_displays_neg(o_displays_neg)
|
.o_displays_neg(o_displays_neg)
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Bus
|
Bus bus (
|
||||||
// For now this is just ROM
|
.i_clk(i_clk),
|
||||||
spMem memory (
|
.i_addr(w_bus_addr),
|
||||||
.dout(w_mem_fetch), //output [7:0] dout
|
.i_in(r_bus_in),
|
||||||
.clk(i_clk), //input clk
|
.i_flags(r_bus_wre),
|
||||||
.oce(1'b0), //input oce (unused)
|
.i_size(r_bus_bytes),
|
||||||
.ce(1'b1), //input ce
|
.i_start(r_bus_start),
|
||||||
.reset(1'b0), //input reset
|
.o_ready(w_bus_ready),
|
||||||
.wre(1'b0), //input wre (write enable)
|
.o_out(w_bus_fetch)
|
||||||
.ad(r_pc_latch[0+:32]), //input [15:0] ad
|
|
||||||
.din(1'b0) //input [7:0] din
|
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
71
src/bus.v
Normal file
71
src/bus.v
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// To read:
|
||||||
|
// 1. Set i_addr to start address
|
||||||
|
// 2. Set i_flags.0 to 0
|
||||||
|
// 3. Set i_size to number of bytes to read
|
||||||
|
// 4. Pulse i_start high
|
||||||
|
// 5. When o_ready goes high, the read data will be in o_out
|
||||||
|
|
||||||
|
// To write:
|
||||||
|
// 1. Set i_addr to start address
|
||||||
|
// 2. Set i_in to the data to write
|
||||||
|
// 3. Set i_flags.0 to 1
|
||||||
|
// 4. Pulse i_start high
|
||||||
|
// 5. When o_ready goes high, the transfer is complete
|
||||||
|
module Bus#(
|
||||||
|
parameter ADDR_WIDTH = 16,
|
||||||
|
parameter DATA_WIDTH = 256
|
||||||
|
) (
|
||||||
|
input i_clk,
|
||||||
|
input [ADDR_WIDTH-1:0] i_addr,
|
||||||
|
input [DATA_WIDTH-1:0] i_in,
|
||||||
|
input [0:0] i_flags, // flags.0: read(0)/write(1)
|
||||||
|
input [5:0] i_size,
|
||||||
|
input i_start, // pulsed high to start transfer
|
||||||
|
output o_ready,
|
||||||
|
output [DATA_WIDTH-1:0] o_out
|
||||||
|
);
|
||||||
|
localparam F_READ = 'b0;
|
||||||
|
localparam F_WRITE = 'b1;
|
||||||
|
|
||||||
|
localparam S_IDLE = 0;
|
||||||
|
localparam S_BUSY = 1;
|
||||||
|
|
||||||
|
reg r_status = S_IDLE;
|
||||||
|
reg r_enable = 0;
|
||||||
|
reg [5:0] r_tx_size = 0;
|
||||||
|
reg [5:0] r_byte_index = 0;
|
||||||
|
reg [7:0] r_in = 0;
|
||||||
|
reg [ADDR_WIDTH-1:0] r_mem_addr;
|
||||||
|
|
||||||
|
assign o_ready = r_byte_index == 0 || r_byte_index > r_tx_size;
|
||||||
|
|
||||||
|
always @(posedge i_clk or posedge i_start) begin
|
||||||
|
if (i_start && !r_enable) begin
|
||||||
|
r_mem_addr <= i_addr;
|
||||||
|
r_enable <= 1;
|
||||||
|
r_status <= S_BUSY;
|
||||||
|
r_tx_size <= i_size;
|
||||||
|
r_in <= i_in[0+:8];
|
||||||
|
r_byte_index <= 1; // 0 is transferring now
|
||||||
|
end else if (r_status == S_BUSY) r_status <= S_IDLE;
|
||||||
|
else if (r_enable && r_byte_index > r_tx_size) r_enable <= 0;
|
||||||
|
else if (r_enable) begin
|
||||||
|
// increment address, input next byte
|
||||||
|
r_mem_addr <= r_mem_addr + 1;
|
||||||
|
r_status <= S_BUSY;
|
||||||
|
r_in <= i_in[r_byte_index*8+:8];
|
||||||
|
r_byte_index <= r_byte_index + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
spMem memory (
|
||||||
|
.dout(o_out), //output [7:0] dout
|
||||||
|
.clk(i_clk), //input clk
|
||||||
|
.oce(1'b0), //input oce (unused)
|
||||||
|
.ce(r_enable), //input ce
|
||||||
|
.reset(1'b0), //input reset
|
||||||
|
.wre(i_flags[0]), //input wre (write enable)
|
||||||
|
.ad(r_mem_addr), //input [15:0] ad
|
||||||
|
.din(r_in) //input [7:0] din
|
||||||
|
);
|
||||||
|
endmodule
|
|
@ -51,5 +51,11 @@
|
||||||
`define LI64 'h4B
|
`define LI64 'h4B
|
||||||
`define LI64_ARGS {ARG_R, ARG_D, ARG_N, ARG_N}
|
`define LI64_ARGS {ARG_R, ARG_D, ARG_N, ARG_N}
|
||||||
|
|
||||||
|
// Absolute addresing memory access operations
|
||||||
|
`define LD 'h4D
|
||||||
|
`define LD_ARGS {ARG_R, ARG_R, ARG_A, ARG_H}
|
||||||
|
`define ST 'h4E
|
||||||
|
`define ST_ARGS {ARG_R, ARG_R, ARG_A, ARG_H}
|
||||||
|
|
||||||
// Conditional jump
|
// Conditional jump
|
||||||
`define JEQ 'h56
|
`define JEQ 'h56
|
|
@ -5,8 +5,10 @@ HBASM = ../hbasm
|
||||||
SPMEM = ../spmem.v
|
SPMEM = ../spmem.v
|
||||||
|
|
||||||
INPUT_FILE = inputs.txt
|
INPUT_FILE = inputs.txt
|
||||||
BUILD_DEPS = ../../src/beepo.v ../../src/instructions.v adding.v ../../src/uart_tx.v ../../src/multi7.v build/spmem_gen.v
|
BUILD_DEPS = ../../src/beepo.v ../../src/instructions.v adding.v ../../src/uart_tx.v ../../src/multi7.v ../../src/bus.v build/spmem_gen.v
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r build
|
||||||
|
|
||||||
${SLAPPER_BUILD}:
|
${SLAPPER_BUILD}:
|
||||||
cargo build --manifest-path ${SLAPPER_DIR}/Cargo.toml -r
|
cargo build --manifest-path ${SLAPPER_DIR}/Cargo.toml -r
|
||||||
|
@ -34,5 +36,5 @@ wave: build/dump.vcd
|
||||||
|
|
||||||
assemble: build/program.bin
|
assemble: build/program.bin
|
||||||
insert-mem: build/spmem_gen.v
|
insert-mem: build/spmem_gen.v
|
||||||
synthesize: build/out
|
synth: build/out
|
||||||
run: build/dump.vcd
|
run: build/dump.vcd
|
||||||
|
|
|
@ -22,7 +22,11 @@ module tb_adding();
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
$dumpfile("build/dump.vcd");
|
$dumpfile("build/dump.vcd");
|
||||||
$dumpvars(0, tb_adding, bep.r_registers[1]);
|
$dumpvars(0, tb_adding,
|
||||||
|
bep.r_arg_regs[0], bep.r_arg_regs[1],
|
||||||
|
bep.r_arg_regs[2], bep.r_arg_regs[3],
|
||||||
|
bep.r_registers[1]
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
// should probably do more granular tests
|
// should probably do more granular tests
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
adding.v
|
adding.v
|
||||||
../../src/uart_tx.v
|
../../src/uart_tx.v
|
||||||
../../src/multi7.v
|
../../src/multi7.v
|
||||||
|
../../src/bus.v
|
||||||
build/spmem_gen.v
|
build/spmem_gen.v
|
||||||
|
|
Loading…
Reference in a new issue