implement CONFIG

cleanup the bus controller
This commit is contained in:
Raphael Jacquot 2019-02-17 19:29:39 +01:00
parent 7a3a36bd25
commit 0d3c3ecd3e
9 changed files with 228 additions and 75 deletions

View file

@ -69,6 +69,7 @@
`define ALU_REG_P 20
`define ALU_REG_M 21
`define ALU_REG_IMM 22
`define ALU_REG_ADDR 23
`define ALU_REG_ZERO 31

View file

@ -35,3 +35,4 @@ second delay is posedge $glbnet$clk -> <async>
2019-02-16 12:18 1453 62.31MHz 33.86ns 12.05ns 10323 70.66MHz 16.96ns 3.59ns
2019-02-16 22:54 1629 60.66MHz 33.62ns 12.05ns 11562 56.91MHz 17.11ns 3.84ns
2019-02-17 12:58 1679 68.43MHz 38.91ns 12.77ns 10906 70.19MHz 18.76ns 4.00ns
2019-02-17 15:11 1677 70.29MHz 34.92ns 13.01ns 11788 74.69MHz 17.42ns 3.88ns

View file

@ -25,10 +25,11 @@ module saturn_alu (
i_stalled,
o_bus_address,
o_bus_pc_read,
o_bus_dp_write,
o_bus_load_pc,
o_bus_load_dp,
o_bus_read_pc,
o_bus_write_dp,
o_bus_config,
o_bus_nibble_out,
i_push,
@ -52,6 +53,8 @@ module saturn_alu (
i_ins_test_go,
i_ins_set_mode,
i_ins_rtn,
i_ins_config,
i_ins_unconfig,
i_mode_dec,
i_set_xm,
@ -73,10 +76,11 @@ input wire [0:0] i_en_alu_save;
input wire [0:0] i_stalled;
output reg [19:0] o_bus_address;
output reg [0:0] o_bus_pc_read;
output reg [0:0] o_bus_dp_write;
output reg [0:0] o_bus_load_pc;
output reg [0:0] o_bus_load_dp;
output reg [0:0] o_bus_read_pc;
output reg [0:0] o_bus_write_dp;
output reg [0:0] o_bus_config;
output reg [3:0] o_bus_nibble_out;
input wire [0:0] i_push;
@ -109,6 +113,8 @@ input wire [0:0] i_ins_alu_op;
input wire [0:0] i_ins_test_go;
input wire [0:0] i_ins_set_mode;
input wire [0:0] i_ins_rtn;
input wire [0:0] i_ins_config;
input wire [0:0] i_ins_unconfig;
input wire [0:0] i_mode_dec;
input wire [0:0] i_set_xm;
@ -345,8 +351,8 @@ always @(posedge i_clk) begin
$display("D: %h R3: %h RSTK2: %5h", D, R3, RSTK[2]);
$display("D0: %h D1: %h R4: %h RSTK1: %5h",
D0, D1, R4, RSTK[1]);
$display(" RSTK0: %5h",
RSTK[0]);
$display(" ADDR: %5h RSTK0: %5h",
o_bus_address, RSTK[0]);
end
`endif
end
@ -394,7 +400,7 @@ end
always @(posedge i_clk) begin
if (do_alu_init) begin
$display("------------------------------------------------- DO_ALU_INIT");
// $display("------------------------------------------------- DO_ALU_INIT");
alu_run <= 1;
f_first <= i_field_start;
f_cur <= i_field_start;
@ -658,6 +664,7 @@ always @(posedge i_clk) begin
`ALU_REG_DAT0,
`ALU_REG_DAT1: o_bus_nibble_out <= c_res1;
`ALU_REG_HST: HST <= c_res1;
`ALU_REG_ADDR: begin end // done down below where o_bus_addr is accessible
default: $display("#### ALU_SAVE invalid register %0d for op %0d", reg_dest, alu_op);
endcase
`ALU_OP_RST_BIT,
@ -768,7 +775,7 @@ always @(posedge i_clk) begin
write_done <= 0;
extra_cycles <= 0;
o_bus_load_dp <= 0;
o_bus_write_dp <= 0;
o_bus_dp_write <= 0;
end
// setup the order to load DP in time
@ -778,8 +785,8 @@ always @(posedge i_clk) begin
// tell the bus to start the write cycle
// this will take 1 cycle because we need to send the DP_WRITE command
if (do_busclean && alu_run && !write_done && is_mem_write && !o_bus_write_dp)
o_bus_write_dp <= 1;
if (do_busclean && alu_run && !write_done && is_mem_write && !o_bus_dp_write)
o_bus_dp_write <= 1;
// writing takes 2 more cycles :
// - one used up above
@ -794,14 +801,14 @@ always @(posedge i_clk) begin
if (i_en_alu_calc && !no_extra_cycles) begin
extra_cycles <= cycles_to_go;
if (cycles_to_go == 1) begin
o_bus_write_dp <= 0;
o_bus_read_pc <= 1;
o_bus_dp_write <= 0;
o_bus_pc_read <= 1;
end
end
// once the PC_READ command has been sent, remove the stall on the decoder
if (i_en_alu_dump && no_extra_cycles && o_bus_read_pc) begin
o_bus_read_pc <= 0;
if (i_en_alu_dump && no_extra_cycles && o_bus_pc_read) begin
o_bus_pc_read <= 0;
write_done <= 0;
end
@ -810,6 +817,33 @@ always @(posedge i_clk) begin
end
/*****************************************************************************
*
* config and unconfig
*
****************************************************************************/
wire is_bus_config;
assign is_bus_config = (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR);
wire send_config;
assign send_config = alu_active && i_en_alu_calc && i_ins_alu_op && alu_run && alu_finish;
always @(posedge i_clk) begin
if (i_reset)
o_bus_config <= 0;
// $display("send_config %b | is_bus_cfg %b | i_ins_cfg %b", send_config, is_bus_config, i_ins_config);
if (send_config && is_bus_config && i_ins_config)
o_bus_config <= 1;
if (do_busclean && o_bus_config)
o_bus_config <= 0;
end
/*****************************************************************************
*
* Handles all changes to PC
@ -853,6 +887,11 @@ always @(posedge i_clk) begin
1: o_bus_address <= D1;
endcase
// this is moved here for access conflicts to o_bus_address
if (do_alu_save && (alu_op == `ALU_OP_COPY) && (reg_dest == `ALU_REG_ADDR)) begin
o_bus_address[f_cur*4+:4] <= c_res1;
end
/**
*
* Update the PC.
@ -871,12 +910,6 @@ always @(posedge i_clk) begin
!o_alu_stall_dec, next_pc, alu_done, alu_finish,
is_alu_op_jump, i_ins_rtn, i_push,
i_imm_value, jump_bse, goyes_off, goyes_pc);
// if (reload_pc) begin
// $display(".---------------------------------.");
// $display("| SHOULD TELL THE BUS CONTROLLER |");
// $display("| TO LOAD PC INTO MODULES' PC REG |");
// $display("`---------------------------------´");
// end
`endif
// this may do wierd things with C=RSTK...

View file

@ -31,6 +31,7 @@ module saturn_bus_ctrl (
i_read_pc,
i_write_dp,
i_cmd_reset,
i_cmd_config,
i_nibble,
o_nibble
);
@ -58,6 +59,8 @@ input wire [0:0] i_load_dp;
input wire [0:0] i_read_pc;
input wire [0:0] i_write_dp;
input wire [0:0] i_cmd_reset;
input wire [0:0] i_cmd_config;
input wire [3:0] i_nibble;
output reg [3:0] o_nibble;
@ -65,7 +68,6 @@ output reg [3:0] o_nibble;
* events
*/
wire en_bus_send;
assign en_bus_send = i_en_bus_send && !i_stalled;
wire en_bus_recv;
@ -73,6 +75,44 @@ assign en_bus_recv = i_en_bus_recv && !i_stalled;
wire en_bus_ecmd;
assign en_bus_ecmd = i_en_bus_ecmd && !i_stalled;
/*
* states
*/
wire [0:0] addr_s;
assign addr_s = addr_cnt == 5;
reg [0:0] cmd_pc_read_s;
reg [0:0] cmd_config_s;
reg [0:0] cmd_reset_s;
wire [0:0] do_pc_read;
wire [0:0] do_cmd_config;
wire [0:0] do_pc_read_after_config;
wire [0:0] cmd_config_sc;
wire [0:0] cmd_config_uc;
wire [0:0] do_cmd_reset;
wire [0:0] do_pc_read_after_reset;
wire [0:0] cmd_reset_sc;
wire [0:0] cmd_reset_uc;
assign do_cmd_config = i_cmd_config && !cmd_config_s;
assign do_pc_read_after_config = i_cmd_config && cmd_config_s && addr_s;
assign cmd_config_sc = !o_stalled_by_bus && i_cmd_config && !cmd_config_s;
assign cmd_config_uc = cmd_config_s && cmd_pc_read_s;
assign do_cmd_reset = i_cmd_reset && !cmd_reset_s;
assign do_pc_read_after_reset = i_cmd_reset && cmd_reset_s;
assign cmd_reset_sc = !o_stalled_by_bus && i_cmd_reset && !cmd_reset_s;
assign cmd_reset_uc = cmd_reset_s && cmd_pc_read_s;
assign do_pc_read = !cmd_pc_read_s &&
(do_pc_read_after_config ||
do_pc_read_after_reset);
/*
* test rom...
*/
@ -98,11 +138,13 @@ end
reg [3:0] last_cmd;
reg [2:0] addr_cnt;
reg [0:0] send_addr;
reg [0:0] reset_sent;
reg [0:0] send_pc_read;
reg [19:0] local_pc;
reg [19:0] local_dp;
reg [0:0] reset_sent;
reg [0:0] config_sent;
reg [0:0] send_pc_read;
always @(posedge i_clk) begin
if (i_reset) begin
last_cmd <= 0;
@ -112,7 +154,12 @@ always @(posedge i_clk) begin
addr_cnt <= 0;
send_addr <= 0;
reset_sent <= 0;
config_sent <= 0;
send_pc_read <= 0;
cmd_pc_read_s <= 0;
cmd_config_s <= 0;
cmd_reset_s <= 0;
end
/*
@ -122,6 +169,16 @@ always @(posedge i_clk) begin
*/
if (en_bus_send) begin
/*
* reset flags
*/
if (cmd_reset_uc || cmd_config_uc) begin
cmd_config_s <= 0;
cmd_reset_s <= 0;
cmd_pc_read_s <= 0;
end
/*
* Sending LOAD_PC or LOAD_DP
*/
@ -138,7 +195,24 @@ always @(posedge i_clk) begin
last_cmd <= `BUSCMD_LOAD_DP;
end
if (i_load_pc || i_load_dp) begin
if (do_cmd_config) begin
$display("BUS_SEND %0d: [%d] CONFIGURE %h", `PH_BUS_SEND, i_cycle_ctr, i_address);
o_bus_data <= `BUSCMD_CONFIGURE;
last_cmd <= `BUSCMD_CONFIGURE;
cmd_config_s <= 1;
end
if (do_cmd_reset) begin
$display("BUS_SEND %0d: [%d] RESET", `PH_BUS_SEND, i_cycle_ctr);
o_bus_data <= `BUSCMD_RESET;
last_cmd <= `BUSCMD_RESET;
cmd_reset_s <= 1;
o_bus_strobe <= 1;
end
// configure loop to send i_address to the bus
// used for LOAD_PC, LOAD_DP, CONFIGURE,
if (i_load_pc || i_load_dp || do_cmd_config) begin
o_stalled_by_bus <= 1;
o_bus_cmd_data <= 0;
addr_cnt <= 0;
@ -160,15 +234,11 @@ always @(posedge i_clk) begin
* after a data transfer
*/
if (i_read_pc || send_pc_read) begin
if (last_cmd != `BUSCMD_PC_READ) begin
$display("BUS_SEND %0d: [%d] PC_READ", `PH_BUS_SEND, i_cycle_ctr);
o_bus_data <= `BUSCMD_PC_READ;
last_cmd <= `BUSCMD_PC_READ;
send_pc_read <= 0;
end
o_bus_strobe <= 1;
if (do_pc_read) begin
$display("BUS_SEND %0d: [%d] PC_READ <<<<<", `PH_BUS_SEND, i_cycle_ctr);
o_bus_data <= `BUSCMD_PC_READ;
last_cmd <= `BUSCMD_PC_READ;
cmd_pc_read_s <= 1;
end
if ((last_cmd == `BUSCMD_PC_READ) && !i_read_stall)
@ -192,23 +262,15 @@ always @(posedge i_clk) begin
end
end
if (i_cmd_reset && !reset_sent) begin
$display("BUS_SEND %0d: [%d] RESET", `PH_BUS_SEND, i_cycle_ctr);
o_bus_data <= `BUSCMD_RESET;
last_cmd <= `BUSCMD_RESET;
reset_sent <= 1;
o_bus_strobe <= 1;
end
end
/*
*
* reading data from the bus
*
*/
if (en_bus_recv) begin
if (!i_read_stall)
@ -224,11 +286,13 @@ always @(posedge i_clk) begin
$write("BUS_RECV %0d: [%d] STALLED (last ", `PH_BUS_RECV, i_cycle_ctr);
case (last_cmd)
`BUSCMD_PC_READ: $write("PC_READ");
`BUSCMD_DP_READ: $write("DP_READ");
`BUSCMD_DP_WRITE: $write("DP_WRITE");
`BUSCMD_RESET: $write("RESET");
default: $write("%h", last_cmd);
endcase
$display(")");
end
end
/*
*
@ -241,20 +305,46 @@ always @(posedge i_clk) begin
end
if (en_bus_ecmd) begin
if (cmd_reset_sc)
o_stalled_by_bus <= 1;
if (cmd_reset_uc) begin
o_stalled_by_bus <= 0;
end
if (cmd_config_sc) begin
o_stalled_by_bus <= 1;
end
if (cmd_config_uc) begin
o_stalled_by_bus <= 0;
addr_cnt <= 0;
end
if (addr_s) begin
send_addr <= 0;
end
end
// command automatic switchover
if (en_bus_ecmd) begin
if (i_cmd_reset && !reset_sent)
o_stalled_by_bus <= 1;
case (last_cmd)
`BUSCMD_LOAD_PC,
`BUSCMD_LOAD_DP:
if (send_addr && (addr_cnt == 5)) begin
$display("BUS_ECMD %0d: [%d] <= %sC_READ mode",
// reset the addr count for next time
addr_cnt <= 0;
$display("BUS_ECMD %0d: [%d] <= %s_READ mode",
`PH_BUS_ECMD, i_cycle_ctr,
(last_cmd == `BUSCMD_LOAD_PC)?"P":"D");
(last_cmd == `BUSCMD_LOAD_PC)?"PC":"DP");
last_cmd <= (last_cmd == `BUSCMD_LOAD_PC)?`BUSCMD_PC_READ:`BUSCMD_DP_READ;
case (last_cmd)
`BUSCMD_LOAD_PC: local_pc <= i_address;
@ -263,18 +353,10 @@ always @(posedge i_clk) begin
send_addr <= 0;
o_stalled_by_bus <= 0;
end
`BUSCMD_PC_READ: begin
if (o_stalled_by_bus && reset_sent) begin
// $display("BUS_ECMD %0d: [%d] (pc_read unstall)", `PH_BUS_ECMD, i_cycle_ctr);
o_stalled_by_bus <= 0;
end
end
`BUSCMD_RESET: begin
if (o_stalled_by_bus && reset_sent) begin
// $display("BUS_ECMD %0d: [%d] (reset, send pc_read)", `PH_BUS_ECMD, i_cycle_ctr);
send_pc_read <= 1;
end
end
`BUSCMD_PC_READ: begin end
`BUSCMD_CONFIGURE: begin end
`BUSCMD_RESET: begin end
default: $display("------------ UNHANDLED BUSCMD %h", last_cmd);
endcase

View file

@ -121,7 +121,8 @@ saturn_decoder m_decoder (
.o_mode_dec (mode_dec),
.o_ins_alu_op (ins_alu_op),
.o_ins_test_go (ins_test_go),
.o_ins_reset (ins_reset)
.o_ins_reset (ins_reset),
.o_ins_config (ins_config)
);
wire [0:0] inc_pc;
@ -154,6 +155,8 @@ wire [0:0] mode_dec;
wire [0:0] ins_alu_op;
wire [0:0] ins_test_go;
wire [0:0] ins_reset;
wire [0:0] ins_config;
wire [0:0] ins_unconfig;
saturn_alu m_alu (
@ -170,8 +173,9 @@ saturn_alu m_alu (
.o_bus_address (bus_address),
.o_bus_load_pc (bus_load_pc),
.o_bus_load_dp (bus_load_dp),
.o_bus_read_pc (bus_read_pc),
.o_bus_write_dp (bus_write_dp),
.o_bus_pc_read (bus_pc_read),
.o_bus_dp_write (bus_dp_write),
.o_bus_config (bus_config),
.o_bus_nibble_out (bus_nibble_out),
.i_push (push),
@ -195,6 +199,8 @@ saturn_alu m_alu (
.i_ins_test_go (ins_test_go),
.i_ins_set_mode (ins_set_mode),
.i_ins_rtn (ins_rtn),
.i_ins_config (ins_config),
.i_ins_unconfig (ins_unconfig),
.i_mode_dec (mode_dec),
.i_set_xm (set_xm),
@ -210,8 +216,9 @@ saturn_alu m_alu (
wire [19:0] bus_address;
wire [0:0] bus_load_pc;
wire [0:0] bus_load_dp;
wire [0:0] bus_read_pc;
wire [0:0] bus_write_dp;
wire [0:0] bus_pc_read;
wire [0:0] bus_dp_write;
wire [0:0] bus_config;
wire [3:0] bus_nibble_in;
wire [3:0] bus_nibble_out;
@ -249,9 +256,10 @@ saturn_bus_ctrl m_bus_ctrl (
.i_address (bus_address),
.i_load_pc (bus_load_pc),
.i_load_dp (bus_load_dp),
.i_read_pc (bus_read_pc),
.i_write_dp (bus_write_dp),
.i_read_pc (bus_pc_read),
.i_write_dp (bus_dp_write),
.i_cmd_reset (ins_reset),
.i_cmd_config (bus_config),
.i_nibble (bus_nibble_out),
.o_nibble (bus_nibble_in)
);
@ -325,9 +333,9 @@ always @(posedge clk) begin
cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) };
if (cycle_ctr == (max_cycle + 1)) begin
$display(".-------------------.");
$display("| OUT OF CYCLES |");
$display("`-------------------´");
$display(".-----------------------------.");
$display("| OUT OF CYCLES %d |", cycle_ctr);
$display("`-----------------------------´");
clock_end <= 1;
end
end else begin
@ -350,7 +358,7 @@ always @(posedge clk) begin
clock_end <= 0;
cycle_ctr <= ~0;
max_cycle <= 155;
max_cycle <= 170;
mem_ctrl_stall <= 0;
`ifndef SIM

View file

@ -32,7 +32,7 @@ module saturn_decoder(
o_set_carry, o_test_carry, o_carry_val,
o_ins_set_mode, o_mode_dec,
o_ins_alu_op, o_ins_test_go,
o_ins_reset,
o_ins_reset, o_ins_config,
o_dbg_nibbles, o_dbg_nb_nbls, o_mem_load, o_mem_pos
);
@ -96,6 +96,7 @@ output reg [0:0] o_ins_test_go;
// bus operations
output reg [0:0] o_ins_reset;
output reg [0:0] o_ins_config;
/* data used by the debugger
*
@ -189,6 +190,7 @@ always @(posedge i_clk) begin
o_pop <= 0;
o_ins_set_mode <= 0;
o_ins_reset <= 0;
o_ins_config <= 0;
end
if (decoder_active) begin
@ -256,7 +258,9 @@ always @(posedge i_clk) begin
// bus instructions
o_ins_reset <= 0;
o_ins_config <= 0;
// counters for debugger info
o_dbg_nb_nbls <= 1;
o_mem_pos <= 0;
@ -274,7 +278,7 @@ always @(posedge i_clk) begin
block_jump_test <= 0;
end else begin
// assign block regs
$display("FIRST NIBBLE %h", i_nibble);
// $display("FIRST NIBBLE %h", i_nibble);
case (i_nibble)
4'h0: block_0x <= 1;
4'h1: block_1x <= 1;

View file

@ -51,13 +51,19 @@
`endif
case (i_nibble)
4'h5: begin // CONFIG
o_ins_alu_op <= 1;
o_alu_op <= `ALU_OP_COPY;
next_nibble <= 0;
o_ins_decoded <= 1;
o_ins_config <= 1;
end
4'hA: begin // RESET
o_ins_reset <= 1;
next_nibble <= 0;
o_ins_decoded <= 1;
`ifdef SIM
o_unimplemented <= 0;
`endif
end
4'hC: block_80Cx <= 1;
default: begin

View file

@ -6,7 +6,7 @@
*****************************************************************************/
`ifdef SIM
`define DEBUG_FIELDS_TABLE
// `define DEBUG_FIELDS_TABLE
`endif
reg fields_table_done;
@ -153,6 +153,15 @@ always @(posedge i_clk) begin
endcase
end
if (do_block_80x) begin
case (i_nibble)
4'h5: begin
o_field_start <= 0;
o_field_last <= 4;
end
endcase
end
if (do_block_80Cx) begin
o_field_start <= i_nibble;
o_field_last <= i_nibble;

View file

@ -161,6 +161,15 @@ always @(posedge i_clk) begin
endcase
end
if (do_block_80x) begin
case (i_nibble)
4'h5: begin
o_reg_dest <= `ALU_REG_ADDR;
o_reg_src1 <= `ALU_REG_C;
end
endcase
end
if (do_block_80Cx) begin
o_reg_dest <= `ALU_REG_C;
o_reg_src1 <= `ALU_REG_P;