start implementing the bus controller

This commit is contained in:
Raphael Jacquot 2019-02-17 08:35:26 +01:00
parent 500e013bf5
commit 128921c364
5 changed files with 131 additions and 64 deletions

View file

@ -6,6 +6,7 @@
`define PH_BUS_SEND 0 `define PH_BUS_SEND 0
`define PH_BUS_RECV 1 `define PH_BUS_RECV 1
`define PH_BUS_ECMD 3
`define PH_INST_DEC 2 `define PH_INST_DEC 2
`define PH_INST_EXE 3 `define PH_INST_EXE 3

View file

@ -33,3 +33,4 @@ second delay is posedge $glbnet$clk -> <async>
2019-02-15 17:12 1544 70.76MHz 33.39ns 12.77ns 10374 75.73MHz 16.74ns 3.99ns 2019-02-15 17:12 1544 70.76MHz 33.39ns 12.77ns 10374 75.73MHz 16.74ns 3.99ns
2019-02-16 11:18 1552 72.00MHz 34.10ns 10.85ns 10072 75.65MHz 17.35ns 3.46ns 2019-02-16 11:18 1552 72.00MHz 34.10ns 10.85ns 10072 75.65MHz 17.35ns 3.46ns
2019-02-16 12:18 1453 62.31MHz 33.86ns 12.05ns 10323 70.66MHz 16.96ns 3.59ns 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

View file

@ -247,7 +247,8 @@ assign alu_active = !i_reset && !i_stalled;
`ifdef SIM `ifdef SIM
wire do_reg_dump; wire do_reg_dump;
wire do_alu_shpc; wire do_alu_shpc;
assign do_reg_dump = alu_active && i_en_alu_dump && i_ins_decoded && !o_alu_stall_dec; assign do_reg_dump = alu_active && i_en_alu_dump && !o_bus_load_pc &&
i_ins_decoded && !o_alu_stall_dec;
assign do_alu_shpc = alu_active && i_en_alu_dump; assign do_alu_shpc = alu_active && i_en_alu_dump;
`endif `endif

View file

@ -11,6 +11,7 @@ module saturn_bus_ctrl (
i_cycle_ctr, i_cycle_ctr,
i_en_bus_send, i_en_bus_send,
i_en_bus_recv, i_en_bus_recv,
i_en_bus_ecmd,
i_stalled, i_stalled,
i_read_stall, i_read_stall,
@ -36,8 +37,10 @@ input wire [0:0] i_reset;
input wire [31:0] i_cycle_ctr; input wire [31:0] i_cycle_ctr;
input wire [0:0] i_en_bus_send; input wire [0:0] i_en_bus_send;
input wire [0:0] i_en_bus_recv; input wire [0:0] i_en_bus_recv;
input wire [0:0] i_en_bus_ecmd;
input wire [0:0] i_stalled; input wire [0:0] i_stalled;
input wire [0:0] i_read_stall; input wire [0:0] i_read_stall;
output reg [0:0] o_stalled_by_bus; output reg [0:0] o_stalled_by_bus;
input wire [3:0] i_bus_data; input wire [3:0] i_bus_data;
@ -61,6 +64,8 @@ wire en_bus_send;
assign en_bus_send = i_en_bus_send && !i_stalled; assign en_bus_send = i_en_bus_send && !i_stalled;
wire en_bus_recv; wire en_bus_recv;
assign en_bus_recv = i_en_bus_recv && !i_stalled; assign en_bus_recv = i_en_bus_recv && !i_stalled;
wire en_bus_ecmd;
assign en_bus_ecmd = i_en_bus_ecmd && !i_stalled;
/* /*
* test rom... * test rom...
@ -77,31 +82,85 @@ initial begin
`ifdef SIM `ifdef SIM
$readmemh("rom-gx-r.hex", rom); $readmemh("rom-gx-r.hex", rom);
// $readmemh( "testrom-2.hex", rom); // $readmemh( "testrom-2.hex", rom);
// $monitor("addr %5h | strb %b | c/d %b | cnt %0d | odata %h | idata %h",
// i_address, o_bus_strobe, o_bus_cmd_data, addr_cnt, o_bus_data, i_bus_data);
`endif `endif
end end
reg [2:0] addr_cnt;
reg [0:0] send_addr;
reg [19:0] local_pc;
always @(posedge i_clk) begin always @(posedge i_clk) begin
if (i_reset) if (i_reset) begin
o_stalled_by_bus <= 0; o_stalled_by_bus <= 0;
o_bus_strobe <= 0;
if (en_bus_send) begin o_bus_cmd_data <= 1; // 1 is the default level
if (i_load_pc) begin addr_cnt <= 0;
$display("BUS_SEND %0d: loading pc %h", `PH_BUS_SEND, i_address);
o_stalled_by_bus <= 1;
end
o_bus_strobe <= 1;
end end
/*
*
* sending commands or data to the bus
*
*/
if (en_bus_send) begin
if (i_load_pc) begin
$display("BUS_SEND %0d: loading pc %h", `PH_BUS_SEND, i_address);
o_bus_data <= `BUSCMD_LOAD_PC;
end
if (i_load_dp) begin
$display("BUS_SEND %0d: loading dp %h", `PH_BUS_SEND, i_address);
o_bus_data <= `BUSCMD_LOAD_DP;
end
if (i_load_pc || i_load_dp) begin
o_stalled_by_bus <= 1;
o_bus_cmd_data <= 0;
addr_cnt <= 0;
send_addr <= 1;
end
if (send_addr) begin
$display("BUS_SEND %0d: send addr nibble %0d [%h]", `PH_BUS_SEND, addr_cnt, i_address[addr_cnt*4+:4]);
o_bus_data <= i_address[addr_cnt*4+:4];
addr_cnt <= addr_cnt + 1;
end
if (!i_read_stall || send_addr)
o_bus_strobe <= 1;
end
if (en_bus_ecmd && send_addr && (addr_cnt == 5)) begin
$display("BUS_ECMD %0d: releasing stall after sending addr", `PH_BUS_ECMD);
send_addr <= 0;
o_stalled_by_bus = 0;
end
/*
*
* reading data from the bus
*
*/
if (en_bus_recv && !i_read_stall) begin if (en_bus_recv && !i_read_stall) begin
$display("BUS_RECV %0d: [%d] nibble %h", `PH_BUS_RECV, i_cycle_ctr, rom[i_alu_pc[`ROMBITS-1:0]]); $display("BUS_RECV %0d: [%d] nibble %h", `PH_BUS_RECV, i_cycle_ctr, rom[i_alu_pc[`ROMBITS-1:0]]);
o_nibble <= rom[i_alu_pc[`ROMBITS-1:0]]; o_nibble <= rom[i_alu_pc[`ROMBITS-1:0]];
end end
// this is always done to lower the strobe signal /*
if (en_bus_recv) *
* resets the bus automatically
*
*/
if (en_bus_recv) begin
o_bus_strobe <= 0; o_bus_strobe <= 0;
o_bus_cmd_data <= 1;
end
end end
endmodule endmodule

View file

@ -46,19 +46,20 @@ assign reset = btn[1];
reg [1:0] clk_phase; reg [1:0] clk_phase;
reg [0:0] en_reset; reg [0:0] en_reset;
reg [0:0] en_debugger; // phase 0 reg [0:0] ck_debugger; // phase 0
reg [0:0] en_bus_send; // phase 0 reg [0:0] ck_bus_send; // phase 0
reg [0:0] en_bus_recv; // phase 1 reg [0:0] ck_bus_recv; // phase 1
reg [0:0] ck_bus_ecmd; // phase 3
reg [0:0] en_inst_dec; // phase 2 reg [0:0] ck_inst_dec; // phase 2
reg [0:0] en_inst_exe; // phase 3 reg [0:0] ck_inst_exe; // phase 3
reg [0:0] en_alu_dump; // phase 0 reg [0:0] ck_alu_dump; // phase 0
reg [0:0] en_alu_init; // phase 3 reg [0:0] ck_alu_init; // phase 3
reg [0:0] en_alu_prep; // phase 1 reg [0:0] ck_alu_prep; // phase 1
reg [0:0] en_alu_calc; // phase 2 reg [0:0] ck_alu_calc; // phase 2
reg [0:0] en_alu_save; // phase 3 reg [0:0] ck_alu_save; // phase 3
reg [0:0] clock_end; reg [0:0] clock_end;
reg [31:0] cycle_ctr; reg [31:0] cycle_ctr;
@ -82,8 +83,8 @@ saturn_decoder m_decoder (
.i_clk (clk), .i_clk (clk),
.i_reset (reset), .i_reset (reset),
.i_cycles (cycle_ctr), .i_cycles (cycle_ctr),
.i_en_dbg (en_debugger), .i_en_dbg (ck_debugger),
.i_en_dec (en_inst_dec), .i_en_dec (ck_inst_dec),
.i_pc (reg_pc), .i_pc (reg_pc),
.i_stalled (dec_stalled), .i_stalled (dec_stalled),
.i_nibble (bus_nibble_in), .i_nibble (bus_nibble_in),
@ -155,11 +156,11 @@ wire [0:0] ins_test_go;
saturn_alu m_alu ( saturn_alu m_alu (
.i_clk (clk), .i_clk (clk),
.i_reset (reset), .i_reset (reset),
.i_en_alu_dump (en_alu_dump), .i_en_alu_dump (ck_alu_dump),
.i_en_alu_prep (en_alu_prep), .i_en_alu_prep (ck_alu_prep),
.i_en_alu_calc (en_alu_calc), .i_en_alu_calc (ck_alu_calc),
.i_en_alu_init (en_alu_init), .i_en_alu_init (ck_alu_init),
.i_en_alu_save (en_alu_save), .i_en_alu_save (ck_alu_save),
.i_stalled (alu_stalled), .i_stalled (alu_stalled),
.o_bus_address (bus_address), .o_bus_address (bus_address),
@ -222,8 +223,9 @@ saturn_bus_ctrl m_bus_ctrl (
.i_clk (clk), .i_clk (clk),
.i_reset (reset), .i_reset (reset),
.i_cycle_ctr (cycle_ctr), .i_cycle_ctr (cycle_ctr),
.i_en_bus_send (en_bus_send), .i_en_bus_send (ck_bus_send),
.i_en_bus_recv (en_bus_recv), .i_en_bus_recv (ck_bus_recv),
.i_en_bus_ecmd (ck_bus_ecmd),
.i_stalled (mem_ctrl_stall), .i_stalled (mem_ctrl_stall),
.i_read_stall (dec_stalled), .i_read_stall (dec_stalled),
.o_stalled_by_bus (bus_stalls_core), .o_stalled_by_bus (bus_stalls_core),
@ -256,19 +258,20 @@ wire [0:0] bus_cmd_data;
initial begin initial begin
clk_phase = 0; clk_phase = 0;
en_debugger = 0; // phase 0 ck_debugger = 0; // phase 0
en_bus_send = 0; // phase 0 ck_bus_send = 0; // phase 0
en_bus_recv = 0; // phase 1 ck_bus_recv = 0; // phase 1
ck_bus_ecmd = 0; // phase 3
en_inst_dec = 0; // phase 2 ck_inst_dec = 0; // phase 2
en_inst_exe = 0; // phase 3 ck_inst_exe = 0; // phase 3
en_alu_dump = 0; ck_alu_dump = 0;
en_alu_prep = 0; // phase 1 ck_alu_prep = 0; // phase 1
en_alu_calc = 0; // phase 2 ck_alu_calc = 0; // phase 2
en_alu_init = 0; // phase 0 ck_alu_init = 0; // phase 0
en_alu_save = 0; // phase 3 ck_alu_save = 0; // phase 3
clock_end = 0; clock_end = 0;
cycle_ctr = 0; cycle_ctr = 0;
@ -294,19 +297,20 @@ initial begin
always @(posedge clk) begin always @(posedge clk) begin
if (!reset) begin if (!reset) begin
clk_phase <= clk_phase + 1; clk_phase <= clk_phase + 1;
en_debugger <= clk_phase[1:0] == `PH_DEBUGGER; ck_debugger <= clk_phase[1:0] == `PH_DEBUGGER;
en_bus_send <= clk_phase[1:0] == `PH_BUS_SEND; ck_bus_send <= clk_phase[1:0] == `PH_BUS_SEND;
en_bus_recv <= clk_phase[1:0] == `PH_BUS_RECV; ck_bus_recv <= clk_phase[1:0] == `PH_BUS_RECV;
ck_bus_ecmd <= clk_phase[1:0] == `PH_BUS_ECMD;
en_inst_dec <= clk_phase[1:0] == `PH_INST_DEC; ck_inst_dec <= clk_phase[1:0] == `PH_INST_DEC;
en_inst_exe <= clk_phase[1:0] == `PH_INST_EXE; ck_inst_exe <= clk_phase[1:0] == `PH_INST_EXE;
en_alu_dump <= clk_phase[1:0] == `PH_ALU_DUMP; ck_alu_dump <= clk_phase[1:0] == `PH_ALU_DUMP;
en_alu_init <= clk_phase[1:0] == `PH_ALU_INIT; ck_alu_init <= clk_phase[1:0] == `PH_ALU_INIT;
en_alu_prep <= clk_phase[1:0] == `PH_ALU_PREP; ck_alu_prep <= clk_phase[1:0] == `PH_ALU_PREP;
en_alu_calc <= clk_phase[1:0] == `PH_ALU_CALC; ck_alu_calc <= clk_phase[1:0] == `PH_ALU_CALC;
en_alu_save <= clk_phase[1:0] == `PH_ALU_SAVE; ck_alu_save <= clk_phase[1:0] == `PH_ALU_SAVE;
cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) }; cycle_ctr <= cycle_ctr + { {31{1'b0}}, (clk_phase[1:0] == `PH_BUS_SEND) };
// stop after 50 clocks // stop after 50 clocks
@ -319,19 +323,20 @@ always @(posedge clk) begin
end else begin end else begin
clk_phase <= ~0; clk_phase <= ~0;
en_debugger <= 0; ck_debugger <= 0;
en_bus_send <= 0; ck_bus_send <= 0;
en_bus_recv <= 0; ck_bus_recv <= 0;
ck_bus_ecmd <= 0;
en_inst_dec <= 0; ck_inst_dec <= 0;
en_inst_exe <= 0; ck_inst_exe <= 0;
en_alu_dump <= 0; ck_alu_dump <= 0;
en_alu_init <= 0; ck_alu_init <= 0;
en_alu_prep <= 0; ck_alu_prep <= 0;
en_alu_calc <= 0; ck_alu_calc <= 0;
en_alu_save <= 0; ck_alu_save <= 0;
clock_end <= 0; clock_end <= 0;
cycle_ctr <= ~0; cycle_ctr <= ~0;
@ -356,11 +361,11 @@ assign dec_stalled = alu_stalls_dec || bus_stalls_core;
assign alu_stalled = bus_stalls_core; assign alu_stalled = bus_stalls_core;
wire read_nibble_to_dec; wire read_nibble_to_dec;
assign read_nibble_to_dec = en_bus_recv && !dec_stalled; assign read_nibble_to_dec = ck_bus_recv && !dec_stalled;
wire dec_stalled_no_read; wire dec_stalled_no_read;
assign dec_stalled_no_read = en_bus_recv && !bus_stalls_core && dec_stalled; assign dec_stalled_no_read = ck_bus_recv && !bus_stalls_core && dec_stalled;
wire bus_is_stalled; wire bus_is_stalled;
assign bus_is_stalled = en_bus_recv && bus_stalls_core; assign bus_is_stalled = ck_bus_recv && bus_stalls_core;
assign halt = clock_end || inv_opcode; assign halt = clock_end || inv_opcode;