Compare commits
No commits in common. "c8f66935c3d9688e5eea3d33b018ec370011310f" and "2e4cd0240c0988fdddf8992d8b1d1d255bb37918" have entirely different histories.
c8f66935c3
...
2e4cd0240c
296
src/beepo.v
296
src/beepo.v
|
@ -1,17 +1,15 @@
|
||||||
// `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
|
||||||
|
@ -32,28 +30,28 @@ module Beepo #(
|
||||||
localparam [3:0] ARG_A = 7; // Absolute address immediate, 64 bit
|
localparam [3:0] ARG_A = 7; // Absolute address immediate, 64 bit
|
||||||
localparam [3:0] ARG_N = 8; // No argument
|
localparam [3:0] ARG_N = 8; // No argument
|
||||||
|
|
||||||
localparam [0:31] ARG_SIZES = {4'h1, 4'h4, 4'h2, 4'h1, 4'h2, 4'h4, 4'h8, 4'h8};
|
localparam [0:31] ARG_SIZES = {4'd1, 4'd4, 4'd2, 4'd1, 4'd2, 4'd4, 4'd8, 4'd8};
|
||||||
|
|
||||||
localparam PC_START = 0;
|
localparam PC_START = 0;
|
||||||
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;
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
reg [WORD_SIZE-1:0] r_pc = PC_START; // program counter
|
reg [63:0] r_pc = PC_START; // program counter
|
||||||
reg [3:0] r_inc_pc = 1;
|
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;
|
||||||
|
@ -61,24 +59,12 @@ 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 [WORD_SIZE-1:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc;
|
wire [63:0] w_mem_addr = r_mem_trans ? r_arg_addr : r_pc;
|
||||||
// wire [7:0] w_mem_fetch;
|
wire [7:0] w_mem_fetch;
|
||||||
wire [255:0] w_mem_fetch;
|
|
||||||
|
|
||||||
reg [7:0] r_mem_tx_size = 1;
|
|
||||||
reg r_mem_start = 0;
|
|
||||||
wire [0:0] w_mem_flags = r_mem_wre;
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -87,13 +73,13 @@ module Beepo #(
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
always @(posedge i_clk) r_tick <= r_tick + 1;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (r_breakpoint == 1) begin
|
if (r_breakpoint == 1) begin
|
||||||
r_breakpoint = ~i_resume;
|
r_breakpoint = ~i_resume;
|
||||||
end else if (r_mem_busy == 1) begin
|
end else if (r_mem_busy == 1) begin
|
||||||
r_pc <= r_pc + r_inc_pc;
|
r_mem_busy = 0;
|
||||||
r_inc_pc <= 0;
|
|
||||||
r_mem_busy <= ~w_mem_ready;
|
|
||||||
end else case (r_state)
|
end else case (r_state)
|
||||||
IDLE: begin
|
IDLE: begin
|
||||||
r_state <= FETCHI;
|
r_state <= FETCHI;
|
||||||
|
@ -106,6 +92,7 @@ module Beepo #(
|
||||||
r_arg_bit <= 0;
|
r_arg_bit <= 0;
|
||||||
r_mem_trans <= 0;
|
r_mem_trans <= 0;
|
||||||
|
|
||||||
|
|
||||||
case (w_mem_fetch)
|
case (w_mem_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;
|
||||||
|
@ -127,14 +114,14 @@ module Beepo #(
|
||||||
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
|
||||||
|
|
||||||
r_inc_pc <= 1;
|
r_pc = r_pc + 1;
|
||||||
r_mem_busy <= 1;
|
r_mem_busy = 1;
|
||||||
|
|
||||||
if (r_arg_types_packed[15:12] != ARG_N) begin
|
if (r_arg_types_packed[15:12] != ARG_N) begin
|
||||||
r_state <= FETCHA;
|
r_state <= FETCHA;
|
||||||
|
|
||||||
r_arg_current_type = r_arg_types_packed[15:12];
|
r_arg_bytes <= ARG_SIZES[r_arg_types_packed[15:12]*4+:4];
|
||||||
r_mem_tx_size = ARG_SIZES[r_arg_current_type*4+:4];
|
r_arg_current_type <= r_arg_types_packed[15:12];
|
||||||
|
|
||||||
r_arg_types[0] <= r_arg_types_packed[15:12];
|
r_arg_types[0] <= r_arg_types_packed[15:12];
|
||||||
r_arg_types[1] <= r_arg_types_packed[11:8];
|
r_arg_types[1] <= r_arg_types_packed[11:8];
|
||||||
|
@ -147,135 +134,116 @@ module Beepo #(
|
||||||
r_arg_regs[3] <= 0;
|
r_arg_regs[3] <= 0;
|
||||||
r_arg_imm <= 0;
|
r_arg_imm <= 0;
|
||||||
r_arg_addr <= 0;
|
r_arg_addr <= 0;
|
||||||
|
|
||||||
end else r_state <= EXEC;
|
end else r_state <= EXEC;
|
||||||
end
|
end
|
||||||
FETCHA: begin
|
FETCHA: begin
|
||||||
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_mem_fetch;
|
||||||
ARG_O: r_arg_addr <= w_mem_fetch;
|
ARG_O: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_P: r_arg_addr <= w_mem_fetch;
|
ARG_P: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_B: r_arg_imm <= w_mem_fetch;
|
ARG_B: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_H: r_arg_imm <= w_mem_fetch;
|
ARG_H: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_W: r_arg_imm <= w_mem_fetch;
|
ARG_W: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_D: r_arg_imm <= w_mem_fetch;
|
ARG_D: r_arg_imm[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
ARG_A: r_arg_addr <= w_mem_fetch;
|
ARG_A: r_arg_addr[r_arg_bit+:8] <= w_mem_fetch;
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
r_pc <= r_pc + 1;
|
||||||
|
r_mem_busy <= 1;
|
||||||
|
|
||||||
r_arg_index = r_arg_index + 1;
|
r_arg_bytes = r_arg_bytes - 1;
|
||||||
r_inc_pc = ARG_SIZES[r_arg_current_type*4+:4];
|
r_arg_bit <= r_arg_bit + 8;
|
||||||
r_arg_current_type = r_arg_types[r_arg_index];
|
|
||||||
|
if (r_arg_bytes == 0) begin
|
||||||
|
r_arg_index = r_arg_index + 1;
|
||||||
|
r_arg_current_type = r_arg_types[r_arg_index];
|
||||||
|
|
||||||
// Execute when there is no next argument or r_arg_index has overflowed
|
// Execute when there is no next argument or r_arg_index has overflowed
|
||||||
if (r_arg_current_type == ARG_N || r_arg_index == 0) begin
|
if (r_arg_current_type == ARG_N || r_arg_index == 0) r_state <= EXEC;
|
||||||
r_state <= EXEC;
|
else begin
|
||||||
r_pc <= r_pc + r_inc_pc;
|
r_arg_bit <= 0;
|
||||||
r_inc_pc <= 0;
|
r_arg_bytes <= ARG_SIZES[r_arg_current_type*4+:4];
|
||||||
end else begin
|
end
|
||||||
r_mem_busy <= 1;
|
|
||||||
r_mem_tx_size = ARG_SIZES[(r_arg_current_type)*4+:4];
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
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]);
|
||||||
`ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [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]);
|
||||||
`LI8: set_reg_byte (r_arg_regs[0], r_arg_imm);
|
`ADD64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_registers [r_arg_regs[2]][0+:64]);
|
||||||
`LD: begin
|
`ADDI8: set_reg_byte (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:8] + r_arg_imm [0+:8]);
|
||||||
if (r_arg_imm > 0) begin
|
`ADDI16: set_reg_hword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:16] + r_arg_imm [0+:16]);
|
||||||
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
|
`ADDI32: set_reg_word (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:32] + r_arg_imm [0+:32]);
|
||||||
r_mem_index <= 0;
|
`ADDI64: set_reg_dword (r_arg_regs[0], r_registers[r_arg_regs[1]][0+:64] + r_arg_imm [0+:64]);
|
||||||
r_mem_reg <= r_arg_regs[0];
|
`LI8: set_reg_byte (r_arg_regs[0], r_arg_imm);
|
||||||
r_state <= MEMR;
|
`LI16: set_reg_hword (r_arg_regs[0], r_arg_imm);
|
||||||
r_mem_tx_size <= r_arg_imm;
|
`LI32: set_reg_word (r_arg_regs[0], r_arg_imm);
|
||||||
r_mem_busy <= 1;
|
`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
|
||||||
`ST: begin
|
end
|
||||||
if (r_arg_imm > 0) begin
|
`ST: begin
|
||||||
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
|
if (r_arg_imm > 0) begin
|
||||||
r_mem_reg <= r_arg_regs[0];
|
r_arg_addr <= r_arg_addr + r_registers[r_arg_regs[1]];
|
||||||
r_mem_wre <= 1;
|
r_mem_index <= 1;
|
||||||
r_mem_tx_size <= r_arg_imm;
|
r_mem_reg <= r_arg_regs[0];
|
||||||
r_mem_in <= r_registers[r_arg_regs[0]];
|
r_mem_wre <= 1;
|
||||||
r_mem_busy <= 1;
|
r_mem_in <= r_registers[r_arg_regs[0]][0+:8];
|
||||||
|
r_mem_busy <= 1;
|
||||||
|
r_state <= MEMR;
|
||||||
|
r_mem_trans <= 1;
|
||||||
|
|
||||||
// r_mem_index <= 1;
|
|
||||||
// r_mem_in <= r_registers[r_arg_regs[0]][0+:8];
|
|
||||||
// r_mem_busy <= 1;
|
|
||||||
// r_state <= MEMR;
|
|
||||||
// r_mem_trans <= 1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
`EBP: r_breakpoint = 1;
|
end
|
||||||
endcase
|
`EBP: r_breakpoint = 1;
|
||||||
|
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)
|
||||||
`LD: set_reg_dword(r_mem_reg, w_mem_fetch);
|
`LD: set_reg_part(r_mem_reg, w_mem_fetch, r_mem_index*8);
|
||||||
endcase
|
`ST: r_mem_in <= r_registers[r_mem_reg][r_mem_index*8+:8];
|
||||||
|
endcase
|
||||||
|
|
||||||
// case (r_instr)
|
r_mem_busy <= 1;
|
||||||
// `LD: set_reg_part(r_mem_reg, w_mem_fetch, r_mem_index*8);
|
|
||||||
// `ST: r_mem_in <= r_registers[r_mem_reg][r_mem_index*8+:8];
|
|
||||||
// endcase
|
|
||||||
|
|
||||||
// r_mem_busy <= 1;
|
if (r_arg_imm == 1) begin
|
||||||
|
// reached the end of the transfer
|
||||||
|
r_mem_wre <= 0;
|
||||||
|
r_mem_trans <= 0;
|
||||||
|
r_state <= FETCHI;
|
||||||
|
end else begin
|
||||||
|
r_mem_index = r_mem_index + 1;
|
||||||
|
|
||||||
// if (r_arg_imm == 1) begin
|
if (r_mem_index == 8) begin
|
||||||
// // reached the end of the transfer
|
// reached the end of this register
|
||||||
// r_mem_wre <= 0;
|
r_mem_reg <= r_mem_reg + 1;
|
||||||
// r_mem_trans <= 0;
|
r_mem_index <= 0;
|
||||||
// r_state <= FETCHI;
|
end
|
||||||
// end else begin
|
|
||||||
// r_mem_index = r_mem_index + 1;
|
|
||||||
|
|
||||||
// if (r_mem_index == WORD_SIZE / 8) begin
|
r_arg_addr <= r_arg_addr + 1;
|
||||||
// // reached the end of this register
|
r_arg_imm <= r_arg_imm - 1;
|
||||||
// r_mem_reg <= r_mem_reg + 1;
|
end
|
||||||
// r_mem_index <= 0;
|
|
||||||
// end
|
|
||||||
|
|
||||||
// r_arg_addr <= r_arg_addr + 1;
|
|
||||||
// r_arg_imm <= r_arg_imm - 1;
|
|
||||||
// end
|
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
r_registers[0] <= 0;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
always @(r_registers[0]) r_registers[0] <= 0;
|
||||||
|
|
||||||
task automatic set_reg_byte(
|
task automatic set_reg_byte(
|
||||||
input [7:0] being_set,
|
input [7:0] being_set,
|
||||||
input [7:0] setting_to
|
input [7:0] setting_to
|
||||||
|
@ -299,7 +267,7 @@ module Beepo #(
|
||||||
|
|
||||||
task automatic set_reg_dword(
|
task automatic set_reg_dword(
|
||||||
input [7:0] being_set,
|
input [7:0] being_set,
|
||||||
input [WORD_SIZE-1:0] setting_to
|
input [63:0] setting_to
|
||||||
);
|
);
|
||||||
r_registers[being_set][0+:64] = setting_to;
|
r_registers[being_set][0+:64] = setting_to;
|
||||||
endtask
|
endtask
|
||||||
|
@ -312,43 +280,21 @@ 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_hex({r_registers[1][15:0]}),
|
|
||||||
.o_segments_drive(o_segments_drive),
|
|
||||||
.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 (
|
|
||||||
// .clk(i_clk),
|
|
||||||
// .ad(w_mem_addr),
|
|
||||||
// .din(r_mem_in),
|
|
||||||
// .dout(w_mem_fetch),
|
|
||||||
// .oce(0),
|
|
||||||
// .ce(1),
|
|
||||||
// .reset(0),
|
|
||||||
// .wre(r_mem_wre)
|
|
||||||
// );
|
|
||||||
|
|
||||||
Mmu mem (
|
|
||||||
.i_clk(i_clk),
|
.i_clk(i_clk),
|
||||||
.i_addr(w_mem_addr),
|
.i_hex({r_registers[1][15:0]}),
|
||||||
.i_in(r_mem_in),
|
.o_segments_drive(o_segments_drive),
|
||||||
.i_flags(w_mem_flags),
|
.o_displays_neg(o_displays_neg)
|
||||||
.i_size(r_mem_tx_size),
|
);
|
||||||
.i_start(r_mem_busy),
|
|
||||||
.o_ready(w_mem_ready),
|
spMem mem (
|
||||||
.o_out(w_mem_fetch)
|
.clk(i_clk),
|
||||||
|
.ad(w_mem_addr),
|
||||||
|
.din(r_mem_in),
|
||||||
|
.dout(w_mem_fetch),
|
||||||
|
.oce(0),
|
||||||
|
.ce(1),
|
||||||
|
.reset(0),
|
||||||
|
.wre(r_mem_wre)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
|
@ -11,7 +11,7 @@
|
||||||
// 3. Set i_flags.0 to 1
|
// 3. Set i_flags.0 to 1
|
||||||
// 4. Pulse i_start high
|
// 4. Pulse i_start high
|
||||||
// 5. When o_ready goes high, the transfer is complete
|
// 5. When o_ready goes high, the transfer is complete
|
||||||
module Mmu#(
|
module Bus#(
|
||||||
parameter ADDR_WIDTH = 16,
|
parameter ADDR_WIDTH = 16,
|
||||||
parameter DATA_WIDTH = 256
|
parameter DATA_WIDTH = 256
|
||||||
) (
|
) (
|
||||||
|
@ -30,61 +30,41 @@ module Mmu#(
|
||||||
localparam S_IDLE = 0;
|
localparam S_IDLE = 0;
|
||||||
localparam S_BUSY = 1;
|
localparam S_BUSY = 1;
|
||||||
|
|
||||||
reg r_status = S_IDLE;
|
reg r_status = S_IDLE;
|
||||||
reg r_enabled = 0;
|
reg r_enable = 0;
|
||||||
reg r_ready = 0;
|
|
||||||
reg [5:0] r_tx_size = 0;
|
reg [5:0] r_tx_size = 0;
|
||||||
reg [5:0] r_byte_index = 0;
|
reg [5:0] r_byte_index = 0;
|
||||||
reg [7:0] r_in = 0;
|
reg [7:0] r_in = 0;
|
||||||
reg [ADDR_WIDTH-1:0] r_mem_addr;
|
reg [ADDR_WIDTH-1:0] r_mem_addr;
|
||||||
reg [DATA_WIDTH-1:0] r_out = 0;
|
|
||||||
|
|
||||||
wire [7:0] w_mem_fetch;
|
assign o_ready = r_byte_index == 0 || r_byte_index > r_tx_size;
|
||||||
|
|
||||||
assign o_ready = r_ready;
|
|
||||||
assign o_out = r_out;
|
|
||||||
|
|
||||||
always @(posedge i_clk or posedge i_start) begin
|
always @(posedge i_clk or posedge i_start) begin
|
||||||
if (i_clk && r_ready) begin
|
if (i_start && !r_enable) begin
|
||||||
r_ready <= 0;
|
|
||||||
end else if (i_start && !r_enabled) begin
|
|
||||||
r_mem_addr <= i_addr;
|
r_mem_addr <= i_addr;
|
||||||
|
r_enable <= 1;
|
||||||
r_status <= S_BUSY;
|
r_status <= S_BUSY;
|
||||||
r_tx_size <= i_size;
|
r_tx_size <= i_size;
|
||||||
r_in <= i_in[0+:8];
|
r_in <= i_in[0+:8];
|
||||||
r_out <= 0;
|
|
||||||
r_byte_index <= 1; // 0 is transferring now
|
r_byte_index <= 1; // 0 is transferring now
|
||||||
r_enabled <= 1;
|
end else if (r_status == S_BUSY) r_status <= S_IDLE;
|
||||||
end else if (r_status == S_BUSY) begin
|
else if (r_enable && r_byte_index > r_tx_size) r_enable <= 0;
|
||||||
r_status <= S_IDLE;
|
else if (r_enable) begin
|
||||||
end else if (r_enabled) begin
|
// increment address, input next byte
|
||||||
if (r_tx_size == 1) begin
|
r_mem_addr <= r_mem_addr + 1;
|
||||||
r_out[(r_byte_index-1)*8+:8] = w_mem_fetch;
|
r_status <= S_BUSY;
|
||||||
r_ready <= 1;
|
r_in <= i_in[r_byte_index*8+:8];
|
||||||
r_enabled = 0;
|
r_byte_index <= r_byte_index + 1;
|
||||||
end else begin
|
|
||||||
// increment address, input next byte
|
|
||||||
r_status <= S_BUSY;
|
|
||||||
r_in <= i_in[r_byte_index*8+:8];
|
|
||||||
r_out[(r_byte_index-1)*8+:8] = w_mem_fetch;
|
|
||||||
r_mem_addr = r_mem_addr + 1;
|
|
||||||
r_byte_index = r_byte_index + 1;
|
|
||||||
|
|
||||||
if (r_byte_index >= r_tx_size) begin
|
|
||||||
r_ready <= 1;
|
|
||||||
r_enabled = 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
spMem memory (
|
spMem memory (
|
||||||
.dout(w_mem_fetch), //output [7:0] dout
|
.dout(o_out), //output [7:0] dout
|
||||||
.clk(i_clk), //input clk
|
.clk(i_clk), //input clk
|
||||||
.oce(1'b0), //input oce (unused)
|
.oce(1'b0), //input oce (unused)
|
||||||
.ce(r_enabled), //input ce
|
.ce(r_enable), //input ce
|
||||||
.reset(1'b0), //input reset
|
.reset(1'b0), //input reset
|
||||||
.wre(i_flags[0]), //input wre (write enabled)
|
.wre(i_flags[0]), //input wre (write enable)
|
||||||
.ad(r_mem_addr), //input [15:0] ad
|
.ad(r_mem_addr), //input [15:0] ad
|
||||||
.din(r_in) //input [7:0] din
|
.din(r_in) //input [7:0] din
|
||||||
);
|
);
|
|
@ -61,7 +61,5 @@
|
||||||
`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}
|
|
@ -5,7 +5,7 @@ HBASM = ./hbasm
|
||||||
SPMEM = spmem.v
|
SPMEM = spmem.v
|
||||||
|
|
||||||
INPUT_FILE = inputs.txt
|
INPUT_FILE = inputs.txt
|
||||||
BUILD_DEPS = ../src/beepo.v ../src/instructions.v ../src/uart_tx.v ../src/multi7.v ../src/mmu.v
|
BUILD_DEPS = ../src/beepo.v ../src/instructions.v ../src/uart_tx.v ../src/multi7.v ../src/bus.v
|
||||||
|
|
||||||
%.clean: %/build
|
%.clean: %/build
|
||||||
rm -r $<
|
rm -r $<
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
../src/instructions.v
|
../src/instructions.v
|
||||||
../src/uart_tx.v
|
../src/uart_tx.v
|
||||||
../src/multi7.v
|
../src/multi7.v
|
||||||
../src/mmu.v
|
../src/bus.v
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
li64 (r4, 0x1020304050607080);
|
li64 (r4, 0x1020304050607080);
|
||||||
st (r4, r0, 0x400, 8);
|
st (r4, r0, 0x400, 8);
|
||||||
ld (r1, r0, 0x400, 8);
|
ld (r1, r0, 0x400, 8); // 0x1020304050607080
|
||||||
ebp();
|
ebp();
|
||||||
|
|
||||||
ld (r2, r0, 0x404, 4);
|
ld (r2, r0, 0x404, 4); // 0x0000000010203040
|
||||||
ebp();
|
ebp();
|
||||||
|
|
||||||
li64 (r1, 0x1010202030304040);
|
li64 (r1, 0x1010202030304040);
|
||||||
li64 (r2, 0x5050606070708080);
|
li64 (r2, 0x5050606070708080);
|
||||||
st (r1, r0, 0x410, 16);
|
st (r1, r0, 0x410, 16);
|
||||||
ld (r3, r0, 0x410, 16);
|
ld (r3, r0, 0x410, 16);
|
||||||
tx();
|
ebp();
|
|
@ -21,8 +21,7 @@ module tb_beepo();
|
||||||
wire w_breakpoint;
|
wire w_breakpoint;
|
||||||
|
|
||||||
Beepo #(
|
Beepo #(
|
||||||
.FREQ(1),
|
.FREQ(1)
|
||||||
.WORD_SIZE(64)
|
|
||||||
) bep (
|
) bep (
|
||||||
.i_clk(r_clk),
|
.i_clk(r_clk),
|
||||||
.i_resume(r_resume),
|
.i_resume(r_resume),
|
||||||
|
@ -73,7 +72,7 @@ module tb_beepo();
|
||||||
end
|
end
|
||||||
|
|
||||||
initial #100000 begin
|
initial #100000 begin
|
||||||
$display("[MEM] Timeout");
|
$display("[ADDING] Timeout");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
Loading…
Reference in a new issue