Can change word size

This commit is contained in:
Bee 2023-11-21 16:50:58 -05:00
parent 2e4cd0240c
commit 057ee6cb61
4 changed files with 108 additions and 81 deletions

View file

@ -1,15 +1,17 @@
// `include "instructions.v" `include "instructions.v"
module Beepo #( module Beepo #(
parameter FREQ = 27_000_000, parameter FREQ = 27_000_000,
parameter UART_BAUD = 115200 parameter UART_BAUD = 115200,
parameter WORD_SIZE = 16
) ( ) (
input i_clk, input i_clk,
input i_button1, input i_button1,
input i_resume, input i_resume,
output [6:0] o_segments_drive, output [6:0] o_segments_drive,
output [3:0] o_displays_neg, output [3:0] o_displays_neg,
output o_breakpoint output o_breakpoint,
output o_uart_tx
); );
// State values // State values
localparam IDLE = 0; // Start fetching instruction localparam IDLE = 0; // Start fetching instruction
@ -36,22 +38,22 @@ module Beepo #(
localparam NUM_REGS = 4; localparam NUM_REGS = 4;
reg [2:0] r_state = IDLE; reg [2:0] r_state = IDLE;
reg [63:0] r_tick = 0; reg [WORD_SIZE-1:0] r_tick = 0;
// Registers // Registers
reg [63:0] r_pc = PC_START; // program counter reg [WORD_SIZE-1:0] r_pc = PC_START; // program counter
reg [63:0] r_registers [0:NUM_REGS]; // up to 255 modifiable registers reg [WORD_SIZE-1:0] r_registers [0: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 [WORD_SIZE-1:0] r_arg_imm = 0; // immediate argument
reg [63:0] r_arg_addr = 0; // relative/absolute address argument reg [WORD_SIZE-1:0] r_arg_addr = 0; // relative/absolute address argument
reg [1:0] r_arg_index = 3; // the instruction index currently being fetched reg [1:0] r_arg_index = 3; // the instruction index currently being fetched
reg [3:0] r_arg_types [0:3]; // the types of each argument to be fetched reg [3:0] r_arg_types [0:3]; // the types of each argument to be fetched
reg [15:0] r_arg_types_packed = 0; // to be unpacked into r_arg_types reg [15:0] r_arg_types_packed = 0; // to be unpacked into r_arg_types
reg [2:0] r_arg_bytes = 0; // the number of bytes left to fetch for the current argument reg [2:0] r_arg_bytes = 0; // the number of bytes left to fetch for the current argument
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
reg r_mem_wre = 0; reg r_mem_wre = 0;
reg r_mem_busy = 0; reg r_mem_busy = 0;
@ -59,12 +61,19 @@ module Beepo #(
reg [7:0] r_mem_in = 0; reg [7:0] r_mem_in = 0;
reg [7:0] r_mem_index = 0; // the index of the byte in transfer reg [7:0] r_mem_index = 0; // the index of the byte in transfer
reg [7:0] r_mem_reg = 0; // the register currently used in transfer reg [7:0] r_mem_reg = 0; // the register currently used in transfer
wire [63:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc; wire [WORD_SIZE-1:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc;
wire [7:0] w_mem_fetch; wire [7:0] w_mem_fetch;
reg r_breakpoint = 0; reg r_breakpoint = 0;
assign o_breakpoint = r_breakpoint; assign o_breakpoint = r_breakpoint;
reg r_uart_rst_n = 0;
reg [7:0] r_uart_data = 0;
reg r_uart_busy = 0;
reg [7:0] r_uart_left = 0;
reg [WORD_SIZE-1:0] r_uart_addr = 0;
wire w_uart_ready;
genvar i; genvar i;
generate generate
@ -172,46 +181,58 @@ module Beepo #(
EXEC: begin EXEC: begin
r_state <= FETCHI; r_state <= FETCHI;
case (r_instr) if (WORD_SIZE >= 8)
`TX: r_state <= DONE; case (r_instr)
`NOP: ; `TX: r_state <= DONE;
`ADD8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_registers [r_arg_regs[2]][0+:8]); `NOP: ;
`ADD16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_registers [r_arg_regs[2]][0+:16]); `ADD8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_registers [r_arg_regs[2]][0+:8]);
`ADD32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_registers [r_arg_regs[2]][0+:32]); `ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]);
`ADD64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_registers [r_arg_regs[2]][0+:64]); `LI8: set_reg_byte (r_arg_regs[0], r_arg_imm);
`ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]); `LD: begin
`ADDI16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_arg_imm [0+:16]); if (r_arg_imm > 0) begin
`ADDI32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_arg_imm [0+:32]); r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
`ADDI64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_arg_imm [0+:64]); r_mem_index <= 0;
`LI8: set_reg_byte (r_arg_regs[0], r_arg_imm); r_mem_reg <= r_arg_regs[0];
`LI16: set_reg_hword (r_arg_regs[0], r_arg_imm); r_mem_busy <= 1;
`LI32: set_reg_word (r_arg_regs[0], r_arg_imm); r_state <= MEMR;
`LI64: set_reg_dword (r_arg_regs[0], r_arg_imm); r_mem_trans <= 1;
`LD: begin end
if (r_arg_imm > 0) begin
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
r_mem_index <= 0;
r_mem_reg <= r_arg_regs[0];
r_mem_busy <= 1;
r_state <= MEMR;
r_mem_trans <= 1;
end end
end `ST: begin
`ST: begin if (r_arg_imm > 0) begin
if (r_arg_imm > 0) begin r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]]; r_mem_index <= 1;
r_mem_index <= 1; r_mem_reg <= r_arg_regs[0];
r_mem_reg <= r_arg_regs[0]; r_mem_wre <= 1;
r_mem_wre <= 1; r_mem_in <= r_registers[r_arg_regs[0]][0+:8];
r_mem_in <= r_registers[r_arg_regs[0]][0+:8]; r_mem_busy <= 1;
r_mem_busy <= 1; r_state <= MEMR;
r_state <= MEMR; r_mem_trans <= 1;
r_mem_trans <= 1; end
end
`EBP: r_breakpoint = 1;
endcase
end if (WORD_SIZE >= 16)
end case (r_instr)
`EBP: r_breakpoint = 1; `ADD16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_registers [r_arg_regs[2]][0+:16]);
endcase `ADDI16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_arg_imm [0+:16]);
`LI16: set_reg_hword (r_arg_regs[0], r_arg_imm);
endcase
if (WORD_SIZE >= 32)
case (r_instr)
`ADD32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_registers [r_arg_regs[2]][0+:32]);
`ADDI32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_arg_imm [0+:32]);
`LI32: set_reg_word (r_arg_regs[0], r_arg_imm);
endcase
if (WORD_SIZE >= 64)
case (r_instr)
`ADD64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_registers [r_arg_regs[2]][0+:64]);
`ADDI64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_arg_imm [0+:64]);
`LI64: set_reg_dword (r_arg_regs[0], r_arg_imm);
endcase
end end
MEMR: begin MEMR: begin
case (r_instr) case (r_instr)
@ -229,7 +250,7 @@ module Beepo #(
end else begin end else begin
r_mem_index = r_mem_index + 1; r_mem_index = r_mem_index + 1;
if (r_mem_index == 8) begin if (r_mem_index == WORD_SIZE / 8) begin
// reached the end of this register // reached the end of this register
r_mem_reg <= r_mem_reg + 1; r_mem_reg <= r_mem_reg + 1;
r_mem_index <= 0; r_mem_index <= 0;
@ -240,9 +261,9 @@ module Beepo #(
end end
end end
endcase endcase
end
always @(r_registers[0]) r_registers[0] <= 0; r_registers[0] <= 0;
end
task automatic set_reg_byte( task automatic set_reg_byte(
input [7:0] being_set, input [7:0] being_set,
@ -267,7 +288,7 @@ module Beepo #(
task automatic set_reg_dword( task automatic set_reg_dword(
input [7:0] being_set, input [7:0] being_set,
input [63:0] setting_to input [WORD_SIZE-1:0] setting_to
); );
r_registers[being_set][0+:64] = setting_to; r_registers[being_set][0+:64] = setting_to;
endtask endtask
@ -280,13 +301,24 @@ module Beepo #(
if (start_bit <= 56) r_registers[being_set][start_bit+:8] = setting_to; if (start_bit <= 56) r_registers[being_set][start_bit+:8] = setting_to;
endtask 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)
); );
// uart_tx #(
// .CLK_FRE(FREQ/1_000_000),
// .BAUD_RATE(115200)
// ) serial (
// .clk(i_clk),
// .rst_n(r_uart_rst_n),
// .tx_data(r_uart_data),
// .tx_data_ready(w_uart_ready),
// .tx_pin(o_uart_tx)
// );
spMem mem ( spMem mem (
.clk(i_clk), .clk(i_clk),
.ad(w_mem_addr), .ad(w_mem_addr),

View file

@ -61,5 +61,7 @@
`define JEQ 'h56 `define JEQ 'h56
// Environment traps // Environment traps
`define ECA 'h5C
`define ECA_ARGS {ARG_N, ARG_N, ARG_N, ARG_N}
`define EBP 'h5D `define EBP 'h5D
`define EBP_ARGS {ARG_N, ARG_N, ARG_N, ARG_N} `define EBP_ARGS {ARG_N, ARG_N, ARG_N, ARG_N}

View file

@ -1,13 +1,2 @@
li64 (r4, 0x1020304050607080); nop();
st (r4, r0, 0x400, 8);
ld (r1, r0, 0x400, 8); // 0x1020304050607080
ebp();
ld (r2, r0, 0x404, 4); // 0x0000000010203040
ebp();
li64 (r1, 0x1010202030304040);
li64 (r2, 0x5050606070708080);
st (r1, r0, 0x410, 16);
ld (r3, r0, 0x410, 16);
ebp(); ebp();

View file

@ -46,16 +46,20 @@ module tb_beepo();
$display("BREAK"); $display("BREAK");
case (r_test) case (r_test)
T_STLD: begin T_STLD: begin
`assert(bep.r_registers[1], 64'h1020304050607080); // `assert(bep.r_registers[1], 64'h1020304050607080);
`assert(bep.r_registers[1], 16'h1020);
$display("[MEM] ST/LD test passed"); $display("[MEM] ST/LD test passed");
end end
T_STLD_HALF: begin T_STLD_HALF: begin
`assert(bep.r_registers[2], 64'h0000000010203040); // `assert(bep.r_registers[2], 64'h0000000010203040);
`assert(bep.r_registers[2], 16'h10);
$display("[MEM] ST/LD Half test passed"); $display("[MEM] ST/LD Half test passed");
end end
T_STLD_DOUBLE: begin T_STLD_DOUBLE: begin
`assert(bep.r_registers[3], 64'h1010202030304040); // `assert(bep.r_registers[3], 64'h1010202030304040);
`assert(bep.r_registers[4], 64'h5050606070708080); // `assert(bep.r_registers[4], 64'h5050606070708080);
`assert(bep.r_registers[3], 64'h1010);
`assert(bep.r_registers[4], 64'h5050);
$display("[MEM] ST/LD Double test passed"); $display("[MEM] ST/LD Double test passed");
end end
endcase endcase