From 9b1e27cc0dd0efa56302a6d3355e4e56915a6e4e Mon Sep 17 00:00:00 2001 From: Graham Edgecombe Date: Mon, 25 Dec 2017 23:12:55 +0000 Subject: [PATCH] Combine the instruction and data buses --- Makefile | 4 ++-- bus_arbiter.sv | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ ram.sv | 3 +++ rv32.sv | 27 ++++++++++++++++++++-- rv32_fetch.sv | 22 +++++++++++------- rv32_hazard.sv | 15 ++++++++++-- top.sv | 62 ++++++++++++++++++++++++++++++++++++++++++++----- 7 files changed, 176 insertions(+), 20 deletions(-) create mode 100644 bus_arbiter.sv diff --git a/Makefile b/Makefile index 1ed21e0..6397aec 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ DEVICE = 8k PACKAGE = ct256 PCF = ice40hx8k-b-evn.pcf FREQ_OSC = 12 -FREQ_PLL = 36 +FREQ_PLL = 32 TARGET = riscv64-unknown-elf AS = $(TARGET)-as ASFLAGS = -march=rv32i -mabi=ilp32 @@ -42,7 +42,7 @@ progmem: progmem.o start.o progmem.lds $(LD) $(LDFLAGS) -o $@ progmem.o start.o progmem_syn.hex: - icebram -g 32 256 > $@ + icebram -g 32 2048 > $@ $(PLL): icepll $(QUIET) -i $(FREQ_OSC) -o $(FREQ_PLL) -m -f $@ diff --git a/bus_arbiter.sv b/bus_arbiter.sv new file mode 100644 index 0000000..8cfebc2 --- /dev/null +++ b/bus_arbiter.sv @@ -0,0 +1,63 @@ +`ifndef BUS_ARBITER +`define BUS_ARBITER + +module bus_arbiter ( + /* instruction memory bus */ + input [31:0] instr_address_in, + input instr_read_in, + output logic [31:0] instr_read_value_out, + output logic instr_ready, + + /* data memory bus */ + input [31:0] data_address_in, + input data_read_in, + input data_write_in, + output logic [31:0] data_read_value_out, + input [3:0] data_write_mask_in, + input [31:0] data_write_value_in, + output logic data_ready, + + /* common memory bus */ + output logic [31:0] address_out, + output logic read_out, + output logic write_out, + input [31:0] read_value_in, + output logic [3:0] write_mask_out, + output logic [31:0] write_value_out +); + always_comb begin + if (data_read_in || data_write_in) begin + address_out = data_address_in; + read_out = data_read_in; + write_out = data_write_in; + instr_read_value_out = 32'bx; + data_read_value_out = read_value_in; + write_mask_out = data_write_mask_in; + write_value_out = data_write_value_in; + instr_ready = 1'b0; + data_ready = 1'b1; + end else if (instr_read_in) begin + address_out = instr_address_in; + read_out = instr_read_in; + write_out = 1'b0; + instr_read_value_out = read_value_in; + data_read_value_out = 32'bx; + write_mask_out = 4'b0; + write_value_out = 32'bx; + instr_ready = 1'b1; + data_ready = 1'b0; + end else begin + address_out = 32'bx; + read_out = 1'b0; + write_out = 1'b0; + instr_read_value_out = 32'bx; + data_read_value_out = 32'bx; + write_mask_out = 4'b0; + write_value_out = 32'bx; + instr_ready = 1'b0; + data_ready = 1'b0; + end + end +endmodule + +`endif diff --git a/ram.sv b/ram.sv index f964c17..a2e79b0 100644 --- a/ram.sv +++ b/ram.sv @@ -14,6 +14,9 @@ module ram ( logic [31:0] mem [2047:0]; logic [31:0] read_value; + initial + $readmemh("progmem_syn.hex", mem); + assign read_value_out = sel_in ? read_value : 0; always_ff @(negedge clk) begin diff --git a/rv32.sv b/rv32.sv index 8aa2024..9314a84 100644 --- a/rv32.sv +++ b/rv32.sv @@ -10,13 +10,20 @@ module rv32 ( input clk, + /* instruction memory bus */ + output logic [31:0] instr_address_out, + output logic instr_read_out, + input [31:0] instr_read_value_in, + input instr_ready_in, + /* data memory bus */ output logic [31:0] data_address_out, output logic data_read_out, output logic data_write_out, input [31:0] data_read_value_in, output logic [3:0] data_write_mask_out, - output logic [31:0] data_write_value_out + output logic [31:0] data_write_value_out, + input data_ready_in ); /* hazard -> fetch control */ logic fetch_stall; @@ -102,6 +109,13 @@ module rv32 ( .mem_branch_taken_in(mem_branch_taken), + .instr_read_in(instr_read_out), + .instr_ready_in(instr_ready_in), + + .data_read_in(data_read_out), + .data_write_in(data_write_out), + .data_ready_in(data_ready_in), + /* control out */ .fetch_stall_out(fetch_stall), .fetch_flush_out(fetch_flush), @@ -126,12 +140,21 @@ module rv32 ( /* control in (from mem) */ .branch_taken_in(mem_branch_taken), + /* control out (to memory bus) */ + .instr_read_out(instr_read_out), + /* data in (from mem) */ .branch_pc_in(mem_branch_pc), + /* data in (from memory bus) */ + .instr_read_value_in(instr_read_value_in), + /* data out */ .pc_out(fetch_pc), - .instr_out(fetch_instr) + .instr_out(fetch_instr), + + /* data out (to memory bus) */ + .instr_address_out(instr_address_out) ); rv32_decode decode ( diff --git a/rv32_fetch.sv b/rv32_fetch.sv index e194405..4aeaecd 100644 --- a/rv32_fetch.sv +++ b/rv32_fetch.sv @@ -16,23 +16,29 @@ module rv32_fetch ( /* data in (from mem) */ input [31:0] branch_pc_in, + /* data in (from memory bus) */ + input [31:0] instr_read_value_in, + + /* control out */ + output logic instr_read_out, + /* data out */ output logic [31:0] pc_out, - output logic [31:0] instr_out -); - logic [31:0] instr_mem [255:0]; - logic [31:0] next_pc; + output logic [31:0] instr_out, + /* data out (to memory bus) */ + output logic [31:0] instr_address_out +); + logic [31:0] next_pc; logic [31:0] pc; - initial - $readmemh("progmem_syn.hex", instr_mem); - assign pc = branch_taken_in ? branch_pc_in : next_pc; + assign instr_read_out = 1; + assign instr_address_out = pc; always_ff @(posedge clk) begin if (!stall_in) begin - instr_out <= instr_mem[pc[31:2]]; + instr_out <= instr_read_value_in; next_pc <= pc + 4; pc_out <= pc; diff --git a/rv32_hazard.sv b/rv32_hazard.sv index 5170282..f51f1d2 100644 --- a/rv32_hazard.sv +++ b/rv32_hazard.sv @@ -12,6 +12,13 @@ module rv32_hazard_unit ( input mem_branch_taken_in, + input instr_read_in, + input instr_ready_in, + + input data_read_in, + input data_write_in, + input data_ready_in, + /* control out */ output logic fetch_stall_out, output logic fetch_flush_out, @@ -25,11 +32,15 @@ module rv32_hazard_unit ( output logic mem_stall_out, output logic mem_flush_out ); + logic fetch_wait_for_bus; logic fetch_wait_for_mem_read; + logic mem_wait_for_bus; + assign fetch_wait_for_bus = instr_read_in && !instr_ready_in; assign fetch_wait_for_mem_read = (decode_rs1_in == decode_rd_in || decode_rs2_in == decode_rd_in) && |decode_rd_in && decode_mem_read_in && decode_rd_write_in; + assign mem_wait_for_bus = (data_read_in || data_write_in) && !data_ready_in; - assign fetch_stall_out = decode_stall_out || fetch_wait_for_mem_read; + assign fetch_stall_out = decode_stall_out || fetch_wait_for_mem_read || fetch_wait_for_bus; assign fetch_flush_out = 0; assign decode_stall_out = execute_stall_out; @@ -38,7 +49,7 @@ module rv32_hazard_unit ( assign execute_stall_out = mem_stall_out; assign execute_flush_out = decode_stall_out || mem_branch_taken_in; - assign mem_stall_out = 0; + assign mem_stall_out = mem_wait_for_bus; assign mem_flush_out = execute_stall_out; endmodule diff --git a/top.sv b/top.sv index f0e4885..2bcf28e 100644 --- a/top.sv +++ b/top.sv @@ -1,3 +1,4 @@ +`include "bus_arbiter.sv" `include "pll.sv" `include "ram.sv" `include "rv32.sv" @@ -57,24 +58,73 @@ module top ( .out(pll_locked) ); + /* instruction memory bus */ + logic [31:0] instr_address; + logic instr_read; + logic [31:0] instr_read_value; + logic instr_ready; + + /* data memory bus */ + logic [31:0] data_address; + logic data_read; + logic data_write; + logic [31:0] data_read_value; + logic [3:0] data_write_mask; + logic [31:0] data_write_value; + logic data_ready; + /* memory bus */ logic [31:0] mem_address; logic mem_read; + logic mem_write; logic [31:0] mem_read_value; logic [3:0] mem_write_mask; logic [31:0] mem_write_value; assign mem_read_value = ram_read_value | leds_read_value | uart_read_value; + bus_arbiter bus_arbiter ( + /* instruction memory bus */ + .instr_address_in(instr_address), + .instr_read_in(instr_read), + .instr_read_value_out(instr_read_value), + .instr_ready(instr_ready), + + /* data memory bus */ + .data_address_in(data_address), + .data_read_in(data_read), + .data_write_in(data_write), + .data_read_value_out(data_read_value), + .data_write_mask_in(data_write_mask), + .data_write_value_in(data_write_value), + .data_ready(data_ready), + + /* common memory bus */ + .address_out(mem_address), + .read_out(mem_read), + .write_out(mem_write), + .read_value_in(mem_read_value), + .write_mask_out(mem_write_mask), + .write_value_out(mem_write_value) + ); + rv32 rv32 ( .clk(pll_clk), - /* memory bus */ - .data_address_out(mem_address), - .data_read_out(mem_read), - .data_read_value_in(mem_read_value), - .data_write_mask_out(mem_write_mask), - .data_write_value_out(mem_write_value) + /* instruction memory bus */ + .instr_address_out(instr_address), + .instr_read_out(instr_read), + .instr_read_value_in(instr_read_value), + .instr_ready_in(instr_ready), + + /* data memory bus */ + .data_address_out(data_address), + .data_read_out(data_read), + .data_write_out(data_write), + .data_read_value_in(data_read_value), + .data_write_mask_out(data_write_mask), + .data_write_value_out(data_write_value), + .data_ready_in(data_ready) ); always_comb begin