Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 63 additions & 44 deletions crush/rtl/crush_cpu.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,30 @@
module crush_cpu #(
parameter integer INITIAL_PC = 0
) (
input wire clk_i,
input wire[31:0] dat_i,
output reg[31:0] dat_o,
input wire rst_i,
input wire ack_i,
input wire err_i,
input wire rty_i,
output reg stb_o,
output reg cyc_o,
output reg[31:0] adr_o,
output reg[3:0] sel_o,
output reg we_o
input wire clk_i,
input wire rst_i,
// Instruction wishbone bus
input wire[31:0] wb_inst_dat_i,
output reg[31:0] wb_inst_dat_o,
input wire wb_inst_ack_i,
input wire wb_inst_err_i,
input wire wb_inst_rty_i,
output reg wb_inst_stb_o,
output reg wb_inst_cyc_o,
output reg[31:0] wb_inst_adr_o,
output reg[3:0] wb_inst_sel_o,
output reg wb_inst_we_o,
// Data wishbone bus
input wire[31:0] wb_data_dat_i,
output reg[31:0] wb_data_dat_o,
input wire wb_data_ack_i,
input wire wb_data_err_i,
input wire wb_data_rty_i,
output reg wb_data_stb_o,
output reg wb_data_cyc_o,
output reg[31:0] wb_data_adr_o,
output reg[3:0] wb_data_sel_o,
output reg wb_data_we_o
);

`include "params.vh"
Expand Down Expand Up @@ -132,19 +144,19 @@ always @(posedge(clk_i)) begin
end else begin
case(state)
STATE_FETCH:
if(ack_i) begin
if(wb_inst_ack_i) begin
state <= STATE_REG_READ;
instruction <= dat_i;
instruction <= wb_inst_dat_i;
end
STATE_REG_READ: state <= STATE_EXECUTE;
STATE_EXECUTE: begin
state <= STATE_MEMORY;
state_change <= 0;
end
STATE_MEMORY:
if(ack_i | (!mem_r_en & !mem_w_en)) begin
if(wb_data_ack_i | (!mem_r_en & !mem_w_en)) begin
state <= STATE_REG_WRITE;
read_data <= dat_i;
read_data <= wb_data_dat_i;
end else state_change <= 0;
STATE_REG_WRITE: state <= STATE_FETCH;
default: state <= STATE_FETCH;
Expand Down Expand Up @@ -190,12 +202,19 @@ always @(*) begin
pc_load = 0;
pc_value = 32'hxxxx_xxxx;

stb_o = 0;
cyc_o = 0;
sel_o = 4'hx;
dat_o = 32'hxxxx_xxxx;
adr_o = 32'hxxxx_xxxx;
we_o = 1'hx;
wb_inst_stb_o = 0;
wb_inst_cyc_o = 0;
wb_inst_sel_o = 4'hx;
wb_inst_dat_o = 32'hxxxx_xxxx;
wb_inst_adr_o = 32'hxxxx_xxxx;
wb_inst_we_o = 1'hx;

wb_data_stb_o = 0;
wb_data_cyc_o = 0;
wb_data_sel_o = 4'hx;
wb_data_dat_o = 32'hxxxx_xxxx;
wb_data_adr_o = 32'hxxxx_xxxx;
wb_data_we_o = 1'hx;

alu_op_a = 32'hxxxx_xxxx;
alu_op_b = 32'hxxxx_xxxx;
Expand All @@ -205,11 +224,11 @@ always @(*) begin

case(state)
STATE_FETCH: begin
stb_o = 1;
cyc_o = 1;
adr_o = pc;
we_o = 0;
sel_o = 4'b1111;
wb_inst_stb_o = 1;
wb_inst_cyc_o = 1;
wb_inst_adr_o = pc;
wb_inst_we_o = 0;
wb_inst_sel_o = 4'b1111;
end
STATE_REG_READ: begin
end
Expand All @@ -219,29 +238,29 @@ always @(*) begin
end
STATE_MEMORY: begin
if(mem_r_en) begin
stb_o = 1;
cyc_o = 1;
adr_o = alu_out_r & ~32'h0000_0003;
we_o = 0;
sel_o = 4'b1111;
wb_data_stb_o = 1;
wb_data_cyc_o = 1;
wb_data_adr_o = alu_out_r & ~32'h0000_0003;
wb_data_we_o = 0;
wb_data_sel_o = 4'b1111;
end

if(mem_w_en) begin
stb_o = 1;
cyc_o = 1;
adr_o = alu_out_r & ~32'h0000_0003;
wb_data_stb_o = 1;
wb_data_cyc_o = 1;
wb_data_adr_o = alu_out_r & ~32'h0000_0003;
case(funct3)
FUNCT3_SW: dat_o = r_out2;
FUNCT3_SH: dat_o = r_out2 << (16 * alu_out_r[1]);
FUNCT3_SB: dat_o = r_out2 << (8 * alu_out_r[0 +: 2]);
default: dat_o = r_out2;
FUNCT3_SW: wb_data_dat_o = r_out2;
FUNCT3_SH: wb_data_dat_o = r_out2 << (16 * alu_out_r[1]);
FUNCT3_SB: wb_data_dat_o = r_out2 << (8 * alu_out_r[0 +: 2]);
default: wb_data_dat_o = r_out2;
endcase
we_o = 1;
wb_data_we_o = 1;
case(funct3)
FUNCT3_SW: sel_o = 4'b1111;
FUNCT3_SH: sel_o = 4'b0011 << (2 * alu_out_r[1]);
FUNCT3_SB: sel_o = 4'b0001 << alu_out_r[0 +: 2];
default: sel_o = 4'bxxxx;
FUNCT3_SW: wb_data_sel_o = 4'b1111;
FUNCT3_SH: wb_data_sel_o = 4'b0011 << (2 * alu_out_r[1]);
FUNCT3_SB: wb_data_sel_o = 4'b0001 << alu_out_r[0 +: 2];
default: wb_data_sel_o = 4'bxxxx;
endcase
end
end
Expand Down
172 changes: 115 additions & 57 deletions crush/sim/cpu_tb.v
Original file line number Diff line number Diff line change
Expand Up @@ -13,46 +13,68 @@ module cpu_tb;

reg clk = 1;
reg reset = 1;
wire stb_o;
wire cyc_o;
wire[31:0] adr_o;
wire[3:0] sel_o;
wire[31:0] dat_i;
wire[31:0] dat_o;
wire we_o;
wire ack_i;
wire err_i = 0;
wire rty_i = 0;

wire wb_inst_stb_o;
wire wb_inst_cyc_o;
wire[31:0] wb_inst_adr_o;
wire[3:0] wb_inst_sel_o;
wire[31:0] wb_inst_dat_i;
wire[31:0] wb_inst_dat_o;
wire wb_inst_we_o;
wire wb_inst_ack_i;
wire wb_inst_err_i = 0;
wire wb_inst_rty_i = 0;

wire wb_data_stb_o;
wire wb_data_cyc_o;
wire[31:0] wb_data_adr_o;
wire[3:0] wb_data_sel_o;
wire[31:0] wb_data_dat_i;
wire[31:0] wb_data_dat_o;
wire wb_data_we_o;
wire wb_data_ack_i;
wire wb_data_err_i = 0;
wire wb_data_rty_i = 0;

crush_cpu #(.INITIAL_PC('h1000_0000)) dut (
.clk_i(clk),
.dat_i(dat_i),
.dat_o(dat_o),
.rst_i(reset),
.ack_i(ack_i),
.err_i(err_i),
.rty_i(rty_i),
.stb_o(stb_o),
.cyc_o(cyc_o),
.adr_o(adr_o),
.sel_o(sel_o),
.we_o(we_o)
.wb_inst_dat_i(wb_inst_dat_i),
.wb_inst_dat_o(wb_inst_dat_o),
.wb_inst_ack_i(wb_inst_ack_i),
.wb_inst_err_i(wb_inst_err_i),
.wb_inst_rty_i(wb_inst_rty_i),
.wb_inst_stb_o(wb_inst_stb_o),
.wb_inst_cyc_o(wb_inst_cyc_o),
.wb_inst_adr_o(wb_inst_adr_o),
.wb_inst_sel_o(wb_inst_sel_o),
.wb_inst_we_o(wb_inst_we_o),
.wb_data_dat_i(wb_data_dat_i),
.wb_data_dat_o(wb_data_dat_o),
.wb_data_ack_i(wb_data_ack_i),
.wb_data_err_i(wb_data_err_i),
.wb_data_rty_i(wb_data_rty_i),
.wb_data_stb_o(wb_data_stb_o),
.wb_data_cyc_o(wb_data_cyc_o),
.wb_data_adr_o(wb_data_adr_o),
.wb_data_sel_o(wb_data_sel_o),
.wb_data_we_o(wb_data_we_o)
);

wire flash_ack_o;
wire wb_inst_flash_ack_o;
memory_infer #(.BASE_ADDRESS('h1000_0000), .SIZE('h20_0000)) flash_emulator (
.clk_i(clk),
.rst_i(reset),
.stb_i(stb_o),
.cyc_i(cyc_o),
.adr_i(adr_o),
.sel_i(sel_o),
.dat_i(dat_o),
.dat_o(dat_i),
.we_i(we_o),
.ack_o(flash_ack_o),
.err_o(err_i),
.rty_o(rty_i)
.stb_i(wb_inst_stb_o),
.cyc_i(wb_inst_cyc_o),
.adr_i(wb_inst_adr_o),
.sel_i(wb_inst_sel_o),
.dat_i(wb_inst_dat_o),
.dat_o(wb_inst_dat_i),
.we_i(wb_inst_we_o),
.ack_o(wb_inst_flash_ack_o),
.err_o(wb_inst_err_i),
.rty_o(wb_inst_rty_i)
);

initial begin
Expand All @@ -74,44 +96,80 @@ initial begin
end
end

wire memory_ack_o;
memory_infer #(.BASE_ADDRESS('h2000_0000), .SIZE('h4000)) memory (
wire wb_data_init_data_ack_o;
memory_infer #(.BASE_ADDRESS('h2000_0000), .SIZE('h4000)) init_data (
.clk_i(clk),
.rst_i(reset),
.stb_i(wb_data_stb_o),
.cyc_i(wb_data_cyc_o),
.adr_i(wb_data_adr_o),
.sel_i(wb_data_sel_o),
.dat_i(wb_data_dat_o),
.dat_o(wb_data_dat_i),
.we_i(wb_data_we_o),
.ack_o(wb_data_init_data_ack_o),
.err_o(wb_data_err_i),
.rty_o(wb_data_rty_i)
);

initial begin
string path;
if($value$plusargs("INIT_DATA_PATH=%s", path)) begin
integer file;
integer length;

$display("Reading initialised data memory contents from %s", path);

file = $fopen(path, "rb");
length = $fread(init_data.mem, file);
$fclose(file);

$display("Read %0d bytes", length);
end else begin
$error("The INIT_DATA_PATH plus arg must be set");
$stop;
end
end

wire wb_data_memory_ack_o;
memory_infer #(.BASE_ADDRESS('h3000_0000), .SIZE('h4000)) memory (
.clk_i(clk),
.rst_i(reset),
.stb_i(stb_o),
.cyc_i(cyc_o),
.adr_i(adr_o),
.sel_i(sel_o),
.dat_i(dat_o),
.dat_o(dat_i),
.we_i(we_o),
.ack_o(memory_ack_o),
.err_o(err_i),
.rty_o(rty_i)
.stb_i(wb_data_stb_o),
.cyc_i(wb_data_cyc_o),
.adr_i(wb_data_adr_o),
.sel_i(wb_data_sel_o),
.dat_i(wb_data_dat_o),
.dat_o(wb_data_dat_i),
.we_i(wb_data_we_o),
.ack_o(wb_data_memory_ack_o),
.err_o(wb_data_err_i),
.rty_o(wb_data_rty_i)
);

wire control_ack_o;
wire wb_data_control_ack_o;
control #(
.BASE_ADDRESS('h3000_0000),
.MEMORY_BASE_ADDRESS('h2000_0000),
.BASE_ADDRESS('h4000_0000),
.MEMORY_BASE_ADDRESS('h3000_0000),
.MEMORY_SIZE('h4000)
) control (
.clk_i(clk),
.rst_i(reset),
.stb_i(stb_o),
.cyc_i(cyc_o),
.adr_i(adr_o),
.sel_i(sel_o),
.dat_i(dat_o),
.dat_o(dat_i),
.we_i(we_o),
.ack_o(control_ack_o),
.err_o(err_i),
.rty_o(rty_i),
.stb_i(wb_data_stb_o),
.cyc_i(wb_data_cyc_o),
.adr_i(wb_data_adr_o),
.sel_i(wb_data_sel_o),
.dat_i(wb_data_dat_o),
.dat_o(wb_data_dat_i),
.we_i(wb_data_we_o),
.ack_o(wb_data_control_ack_o),
.err_o(wb_data_err_i),
.rty_o(wb_data_rty_i),
.memory(memory.mem)
);

assign ack_i = flash_ack_o | memory_ack_o | control_ack_o;
assign wb_inst_ack_i = wb_inst_flash_ack_o;
assign wb_data_ack_i = wb_data_init_data_ack_o | wb_data_memory_ack_o | wb_data_control_ack_o;

always begin
#0.5 clk <= !clk;
Expand Down
7 changes: 5 additions & 2 deletions crush_example/crush_example.core
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ name: ::crush_example:0.0.1
filesets:
rtl:
files:
- fw/binary/crush-blinky.data:
- fw/binary/crush-blinky-instruction.data:
file_type: user
copyto: fw.data
copyto: inst.data
- fw/binary/crush-blinky-data.data:
file_type: user
copyto: data.data
- rtl/memory.v
- rtl/memory_ice40_spram.v
- rtl/top.v
Expand Down
8 changes: 7 additions & 1 deletion crush_example/fw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ set_target_properties(crush-blinky PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURC

string(REPLACE "-gcc" "-objcopy" objcopy_name ${CMAKE_C_COMPILER})
find_program(objcopy_program ${objcopy_name} REQUIRED)

add_custom_command(TARGET crush-blinky POST_BUILD
COMMAND ${objcopy_program} -O verilog -j .mem -j .bss -j .stack --adjust-vma -0x10000000 --verilog-data-width 4 crush-blinky ${CMAKE_CURRENT_LIST_DIR}/binary/crush-blinky.data
COMMAND ${objcopy_program} -O verilog -j .instruction_memory --verilog-data-width 4 crush-blinky ${CMAKE_CURRENT_LIST_DIR}/binary/crush-blinky-instruction.data
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

add_custom_command(TARGET crush-blinky POST_BUILD
COMMAND ${objcopy_program} -O verilog -j .memory -j .stack --verilog-data-width 4 crush-blinky ${CMAKE_CURRENT_LIST_DIR}/binary/crush-blinky-data.data
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
Empty file.
Loading