Combine the instruction and data buses
This commit is contained in:
parent
7f81e495b3
commit
9b1e27cc0d
7 changed files with 176 additions and 20 deletions
4
Makefile
4
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 $@
|
||||
|
|
|
|||
63
bus_arbiter.sv
Normal file
63
bus_arbiter.sv
Normal file
|
|
@ -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
|
||||
3
ram.sv
3
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
|
||||
|
|
|
|||
27
rv32.sv
27
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 (
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
62
top.sv
62
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue