Can change word size
This commit is contained in:
parent
2e4cd0240c
commit
057ee6cb61
78
src/beepo.v
78
src/beepo.v
|
@ -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,15 +38,15 @@ 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
|
||||||
|
@ -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,21 +181,13 @@ module Beepo #(
|
||||||
EXEC: begin
|
EXEC: begin
|
||||||
r_state <= FETCHI;
|
r_state <= FETCHI;
|
||||||
|
|
||||||
|
if (WORD_SIZE >= 8)
|
||||||
case (r_instr)
|
case (r_instr)
|
||||||
`TX: r_state <= DONE;
|
`TX: r_state <= DONE;
|
||||||
`NOP: ;
|
`NOP: ;
|
||||||
`ADD8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_registers [r_arg_regs[2]][0+:8]);
|
`ADD8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_registers [r_arg_regs[2]][0+:8]);
|
||||||
`ADD16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_registers [r_arg_regs[2]][0+:16]);
|
|
||||||
`ADD32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_registers [r_arg_regs[2]][0+:32]);
|
|
||||||
`ADD64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_registers [r_arg_regs[2]][0+:64]);
|
|
||||||
`ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]);
|
`ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]);
|
||||||
`ADDI16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_arg_imm [0+:16]);
|
|
||||||
`ADDI32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_arg_imm [0+:32]);
|
|
||||||
`ADDI64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_arg_imm [0+:64]);
|
|
||||||
`LI8: set_reg_byte (r_arg_regs[0], r_arg_imm);
|
`LI8: set_reg_byte (r_arg_regs[0], r_arg_imm);
|
||||||
`LI16: set_reg_hword (r_arg_regs[0], r_arg_imm);
|
|
||||||
`LI32: set_reg_word (r_arg_regs[0], r_arg_imm);
|
|
||||||
`LI64: set_reg_dword (r_arg_regs[0], r_arg_imm);
|
|
||||||
`LD: begin
|
`LD: 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]];
|
||||||
|
@ -207,11 +208,31 @@ module Beepo #(
|
||||||
r_mem_busy <= 1;
|
r_mem_busy <= 1;
|
||||||
r_state <= MEMR;
|
r_state <= MEMR;
|
||||||
r_mem_trans <= 1;
|
r_mem_trans <= 1;
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`EBP: r_breakpoint = 1;
|
`EBP: r_breakpoint = 1;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
if (WORD_SIZE >= 16)
|
||||||
|
case (r_instr)
|
||||||
|
`ADD16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_registers [r_arg_regs[2]][0+:16]);
|
||||||
|
`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
|
||||||
|
@ -287,6 +308,17 @@ module Beepo #(
|
||||||
.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),
|
||||||
|
|
|
@ -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}
|
|
@ -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();
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue