From f1f09584eed269370a6fceee0be4d35f04b15b56 Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Fri, 9 Apr 2021 20:22:34 +0800 Subject: [PATCH] optimize ifu and lsu Signed-off-by: liangkangnan --- rtl.flist | 3 + rtl/core/exu.sv | 18 +- rtl/core/exu_mem.sv | 81 ++- rtl/core/ifu.sv | 123 ++++- rtl/core/tinyriscv_core.sv | 73 ++- rtl/core/tracer.sv | 2 + rtl/sys_bus/obi_interconnect.sv | 120 +++++ rtl/sys_bus/obi_interconnect_master_sel.sv | 65 +++ rtl/sys_bus/obi_interconnect_slave_sel.sv | 44 ++ rtl/top/tinyriscv_soc_top.sv | 589 ++++++--------------- sim/tb_top_verilator.cpp | 2 +- 11 files changed, 611 insertions(+), 509 deletions(-) create mode 100644 rtl/sys_bus/obi_interconnect.sv create mode 100644 rtl/sys_bus/obi_interconnect_master_sel.sv create mode 100644 rtl/sys_bus/obi_interconnect_slave_sel.sv diff --git a/rtl.flist b/rtl.flist index 26642d0..bc43e0d 100644 --- a/rtl.flist +++ b/rtl.flist @@ -32,6 +32,9 @@ ../rtl/perips/uart.sv ../rtl/sys_bus/rib.sv +../rtl/sys_bus/obi_interconnect.sv +../rtl/sys_bus/obi_interconnect_master_sel.sv +../rtl/sys_bus/obi_interconnect_slave_sel.sv ../rtl/top/tinyriscv_soc_top.sv diff --git a/rtl/core/exu.sv b/rtl/core/exu.sv index bec4c32..024d2c9 100644 --- a/rtl/core/exu.sv +++ b/rtl/core/exu.sv @@ -33,14 +33,13 @@ module exu( // mem input wire[31:0] mem_rdata_i, // 内存输入数据 - input wire mem_req_ready_i, - input wire mem_rsp_valid_i, + input wire mem_gnt_i, + input wire mem_rvalid_i, output wire[31:0] mem_wdata_o, // 写内存数据 output wire[31:0] mem_addr_o, // 读、写内存地址 output wire mem_we_o, // 是否要写内存 - output wire[3:0] mem_sel_o, // 字节位 - output wire mem_req_valid_o, - output wire mem_rsp_ready_o, + output wire[3:0] mem_be_o, // 字节位 + output wire mem_req_o, output wire mem_access_misaligned_o, // gpr_reg @@ -291,8 +290,8 @@ module exu( .req_mem_i(req_mem_o), .mem_addr_i(alu_res_o), .mem_rs2_data_i(mem_rs2_data_o), - .mem_req_ready_i(mem_req_ready_i), - .mem_rsp_valid_i(mem_rsp_valid_i), + .mem_gnt_i(mem_gnt_i), + .mem_rvalid_i(mem_rvalid_i), .mem_rdata_i(mem_rdata_i), .mem_op_lb_i(mem_op_lb_o), .mem_op_lh_i(mem_op_lh_o), @@ -308,9 +307,8 @@ module exu( .mem_wdata_o(mem_wdata), .mem_reg_we_o(mem_reg_we_o), .mem_mem_we_o(mem_mem_we_o), - .mem_sel_o(mem_sel_o), - .mem_req_valid_o(mem_req_valid_o), - .mem_rsp_ready_o(mem_rsp_ready_o) + .mem_be_o(mem_be_o), + .mem_req_o(mem_req_o) ); wire[31:0] muldiv_reg_wdata_o; diff --git a/rtl/core/exu_mem.sv b/rtl/core/exu_mem.sv index ba794b6..025b0c5 100644 --- a/rtl/core/exu_mem.sv +++ b/rtl/core/exu_mem.sv @@ -26,8 +26,8 @@ module exu_mem( input wire[31:0] mem_addr_i, input wire[31:0] mem_rs2_data_i, input wire[31:0] mem_rdata_i, - input wire mem_req_ready_i, - input wire mem_rsp_valid_i, + input wire mem_gnt_i, + input wire mem_rvalid_i, input wire mem_op_lb_i, input wire mem_op_lh_i, input wire mem_op_lw_i, @@ -43,9 +43,8 @@ module exu_mem( output wire[31:0] mem_wdata_o, output wire mem_reg_we_o, output wire mem_mem_we_o, - output wire[3:0] mem_sel_o, - output wire mem_req_valid_o, - output wire mem_rsp_ready_o + output wire[3:0] mem_be_o, + output wire mem_req_o ); @@ -56,10 +55,10 @@ module exu_mem( wire mem_addr_index10 = (mem_addr_index == 2'b10); wire mem_addr_index11 = (mem_addr_index == 2'b11); - assign mem_sel_o[0] = mem_addr_index00 | mem_op_sw_i; - assign mem_sel_o[1] = mem_addr_index01 | (mem_op_sh_i & mem_addr_index00) | mem_op_sw_i; - assign mem_sel_o[2] = mem_addr_index10 | mem_op_sw_i; - assign mem_sel_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i; + assign mem_be_o[0] = mem_addr_index00 | mem_op_sw_i; + assign mem_be_o[1] = mem_addr_index01 | (mem_op_sh_i & mem_addr_index00) | mem_op_sw_i; + assign mem_be_o[2] = mem_addr_index10 | mem_op_sw_i; + assign mem_be_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i; reg[31:0] sb_res; @@ -127,6 +126,68 @@ module exu_mem( assign mem_wdata_o = mem_wdata; + + wire op_load = mem_op_lb_i | mem_op_lh_i | mem_op_lw_i | mem_op_lbu_i | mem_op_lhu_i; + wire op_store = mem_op_sb_i | mem_op_sh_i | mem_op_sw_i; + + localparam S_IDLE = 2'b01; + localparam S_MEM = 2'b10; + + reg[1:0] state; + reg[1:0] next_state; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + state <= S_IDLE; + end else begin + state <= next_state; + end + end + + always @ (*) begin + case (state) + S_IDLE: begin + if (mem_req_o & mem_gnt_i) begin + next_state = S_MEM; + end else begin + next_state = S_IDLE; + end + end + + S_MEM: begin + if (mem_rvalid_i) begin + next_state = S_IDLE; + end else begin + next_state = S_MEM; + end + end + + default: begin + next_state = S_IDLE; + end + endcase + end + + assign mem_req_o = req_mem_i; + assign mem_addr_o = mem_addr_i; + + // 暂停流水线 + assign mem_stall_o = ((state == S_IDLE) & req_mem_i) | + ((state == S_MEM) & (~mem_rvalid_i)); + + // 写内存使能 + assign mem_mem_we_o = op_store & (state == S_MEM) & mem_rvalid_i; + + // 写寄存器使能 + assign mem_reg_we_o = op_load & (state == S_MEM) & mem_rvalid_i; + + assign mem_access_misaligned_o = (mem_op_sw_i | mem_op_lw_i)? (mem_addr_i[0] | mem_addr_i[1]): + (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]: + 0; + + + +/* wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i); wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o); @@ -158,5 +219,5 @@ module exu_mem( assign mem_access_misaligned_o = (mem_op_sw_i | mem_op_lw_i)? (mem_addr_i[0] | mem_addr_i[1]): (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]: 0; - +*/ endmodule diff --git a/rtl/core/ifu.sv b/rtl/core/ifu.sv index eef34bd..1d77042 100644 --- a/rtl/core/ifu.sv +++ b/rtl/core/ifu.sv @@ -22,27 +22,127 @@ module ifu( input wire clk, input wire rst_n, - input wire flush_i, + input wire flush_i, // 跳转标志 input wire[31:0] flush_addr_i, // 跳转地址 input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志 input wire jtag_halt_i, - output wire[31:0] inst_o, output wire[31:0] pc_o, output wire inst_valid_o, - output wire[31:0] ibus_addr_o, - input wire[31:0] ibus_data_i, - output wire[31:0] ibus_data_o, - output wire[3:0] ibus_sel_o, - output wire ibus_we_o, - output wire req_valid_o, - input wire req_ready_i, - input wire rsp_valid_i, - output wire rsp_ready_o + output wire instr_req_o, + input wire instr_gnt_i, + input wire instr_rvalid_i, + output wire[31:0] instr_addr_o, + input wire[31:0] instr_rdata_i, + input wire instr_err_i ); + + assign instr_req_o = ((~rst_n) | stall_i[`STALL_PC])? 1'b0: 1'b1; + + + localparam S_FETCH = 2'b01; + localparam S_VALID = 2'b10; + + reg[1:0] state; + reg[1:0] next_state; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + state <= S_FETCH; + end else begin + state <= next_state; + end + end + + always @ (*) begin + case (state) + S_FETCH: begin + if (instr_gnt_i & (~stall_i[`STALL_PC]) & (~flush_i)) begin + next_state = S_VALID; + end else begin + next_state = S_FETCH; + end + end + + S_VALID: begin + if (stall_i[`STALL_PC] | flush_i) begin + next_state = S_FETCH; + end else begin + next_state = S_VALID; + end + end + + default: begin + next_state = S_FETCH; + end + endcase + end + + wire inst_valid = (state == S_VALID) & instr_rvalid_i; + assign inst_valid_o = inst_valid; + assign inst_o = inst_valid? instr_rdata_i: `INST_NOP; + + wire[31:0] fetch_addr_d; + reg[31:0] fetch_addr_q; + wire fetch_addr_en = instr_req_o & instr_gnt_i & (~stall_i[`STALL_PC]); + + assign fetch_addr_d = flush_i? flush_addr_i: + stall_i[`STALL_PC]? fetch_addr_q: + inst_valid? fetch_addr_q + 4'h4: + fetch_addr_q; + + always @ (posedge clk or negedge rst_n) begin + // 复位 + if (!rst_n) begin + fetch_addr_q <= `CPU_RESET_ADDR; + end else if (fetch_addr_en) begin + fetch_addr_q <= fetch_addr_d; + end + end + + assign instr_addr_o = {fetch_addr_d[31:2], 2'b00}; + assign pc_o = fetch_addr_q; + + + + + + + + +/* + assign instr_req_o = (~rst_n)? 1'b0: 1'b1; + + wire[31:0] fetch_addr_d; + reg[31:0] fetch_addr_q; + wire fetch_addr_en = instr_req_o & instr_gnt_i & (~stall_i[`STALL_PC]); + + assign fetch_addr_d = flush_i? flush_addr_i: + instr_rvalid_i? fetch_addr_q + 4'h4: + fetch_addr_q; + + always @ (posedge clk or negedge rst_n) begin + // 复位 + if (!rst_n) begin + fetch_addr_q <= `CPU_RESET_ADDR; + end else if (fetch_addr_en) begin + fetch_addr_q <= fetch_addr_d; + end + end + + assign instr_addr_o = {fetch_addr_d[31:2], 2'b00}; + assign pc_o = fetch_addr_q; + + wire inst_valid = instr_rvalid_i & (~flush_i); + assign inst_valid_o = inst_valid; + assign inst_o = inst_valid? instr_rdata_i: `INST_NOP; +*/ + + +/* assign req_valid_o = (~rst_n)? 1'b0: (flush_i)? 1'b0: stall_i[`STALL_PC]? 1'b0: @@ -122,5 +222,6 @@ module ifu( assign ibus_sel_o = 4'b1111; assign ibus_we_o = 1'b0; assign ibus_data_o = 32'h0; +*/ endmodule diff --git a/rtl/core/tinyriscv_core.sv b/rtl/core/tinyriscv_core.sv index ef7b43a..4b73638 100644 --- a/rtl/core/tinyriscv_core.sv +++ b/rtl/core/tinyriscv_core.sv @@ -22,25 +22,22 @@ module tinyriscv_core( input wire clk, input wire rst_n, - output wire[31:0] dbus_addr_o, - input wire[31:0] dbus_data_i, - output wire[31:0] dbus_data_o, - output wire[3:0] dbus_sel_o, - output wire dbus_we_o, - output wire dbus_req_valid_o, - input wire dbus_req_ready_i, - input wire dbus_rsp_valid_i, - output wire dbus_rsp_ready_o, + output wire instr_req_o, + input wire instr_gnt_i, + input wire instr_rvalid_i, + output wire[31:0] instr_addr_o, + input wire[31:0] instr_rdata_i, + input wire instr_err_i, - output wire[31:0] ibus_addr_o, // 取指地址 - input wire[31:0] ibus_data_i, // 取到的指令内容 - output wire[31:0] ibus_data_o, - output wire[3:0] ibus_sel_o, - output wire ibus_we_o, - output wire ibus_req_valid_o, - input wire ibus_req_ready_i, - input wire ibus_rsp_valid_i, - output wire ibus_rsp_ready_o, + output wire data_req_o, + input wire data_gnt_i, + input wire data_rvalid_i, + output wire data_we_o, + output wire[3:0] data_be_o, + output wire[31:0] data_addr_o, + output wire[31:0] data_wdata_o, + input wire[31:0] data_rdata_i, + input wire data_err_i, input wire jtag_halt_i, input wire[`INT_WIDTH-1:0] int_i // 中断输入信号 @@ -131,13 +128,6 @@ module tinyriscv_core( wire[31:0] clint_int_addr_o; wire clint_int_assert_o; - assign dbus_addr_o = ex_mem_addr_o; - assign dbus_data_o = ex_mem_wdata_o; - assign dbus_we_o = ex_mem_we_o; - assign dbus_sel_o = ex_mem_sel_o; - assign dbus_req_valid_o = ex_mem_req_valid_o; - assign dbus_rsp_ready_o = ex_mem_rsp_ready_o; - ifu u_ifu( .clk(clk), @@ -149,15 +139,13 @@ module tinyriscv_core( .inst_o(ifetch_inst_o), .pc_o(ifetch_pc_o), .inst_valid_o(ifetch_inst_valid_o), - .ibus_addr_o(ibus_addr_o), - .ibus_data_i(ibus_data_i), - .ibus_data_o(ibus_data_o), - .ibus_sel_o(ibus_sel_o), - .ibus_we_o(ibus_we_o), - .req_valid_o(ibus_req_valid_o), - .req_ready_i(ibus_req_ready_i), - .rsp_valid_i(ibus_rsp_valid_i), - .rsp_ready_o(ibus_rsp_ready_o) + + .instr_req_o(instr_req_o), + .instr_gnt_i(instr_gnt_i), + .instr_rvalid_i(instr_rvalid_i), + .instr_addr_o(instr_addr_o), + .instr_rdata_i(instr_rdata_i), + .instr_err_i(instr_err_i) ); pipe_ctrl u_pipe_ctrl( @@ -265,15 +253,14 @@ module tinyriscv_core( .rst_n(rst_n), .reg1_rdata_i(ie_rs1_rdata_o), .reg2_rdata_i(ie_rs2_rdata_o), - .mem_rdata_i(dbus_data_i), - .mem_req_ready_i(dbus_req_ready_i), - .mem_rsp_valid_i(dbus_rsp_valid_i), - .mem_wdata_o(ex_mem_wdata_o), - .mem_addr_o(ex_mem_addr_o), - .mem_we_o(ex_mem_we_o), - .mem_sel_o(ex_mem_sel_o), - .mem_req_valid_o(ex_mem_req_valid_o), - .mem_rsp_ready_o(ex_mem_rsp_ready_o), + .mem_rdata_i(data_rdata_i), + .mem_gnt_i(data_gnt_i), + .mem_rvalid_i(data_rvalid_i), + .mem_wdata_o(data_wdata_o), + .mem_addr_o(data_addr_o), + .mem_we_o(data_we_o), + .mem_be_o(data_be_o), + .mem_req_o(data_req_o), .mem_access_misaligned_o(ex_mem_access_misaligned_o), .reg_wdata_o(ex_reg_wdata_o), .reg_we_o(ex_reg_we_o), diff --git a/rtl/core/tracer.sv b/rtl/core/tracer.sv index 1df9584..12d9ad9 100644 --- a/rtl/core/tracer.sv +++ b/rtl/core/tracer.sv @@ -581,6 +581,7 @@ module tracer( $display("Writing execution trace to %s", file_name); file_handle = $fopen(file_name, "w"); $fwrite(file_handle, "\t\t\tTime\t\tCycle\tPC\t\t\tInsn\t\tDecoded instruction\n"); + $fflush(file_handle); end @@ -589,6 +590,7 @@ module tracer( $fwrite(file_handle, "%15t\t%d\t\t%h\t%s\t%s", $time, cycle, pc_i, insn_str, decoded_str); $fwrite(file_handle, "\n"); + $fflush(file_handle); endfunction // log execution diff --git a/rtl/sys_bus/obi_interconnect.sv b/rtl/sys_bus/obi_interconnect.sv new file mode 100644 index 0000000..131eb82 --- /dev/null +++ b/rtl/sys_bus/obi_interconnect.sv @@ -0,0 +1,120 @@ + +// obi总线交叉互联矩阵,支持一对多、多对一、多对多 +// master之间采用优先级总裁方式,LSB优先级最高,MSB优先级最低 +module obi_interconnect #( + parameter int MASTERS = 3, // number of masters + parameter int SLAVES = 5, // number of slaves + parameter MASTER_BITS = MASTERS == 1 ? 1 : $clog2(MASTERS), + parameter SLAVE_BITS = SLAVES == 1 ? 1 : $clog2(SLAVES) + )( + input logic clk_i, + input logic rst_ni, + + input logic master_req_i [MASTERS], + output logic master_gnt_o [MASTERS], + output logic master_rvalid_o [MASTERS], + input logic master_we_i [MASTERS], + input logic [ 3:0] master_be_i [MASTERS], + input logic [31:0] master_addr_i [MASTERS], + input logic [31:0] master_wdata_i [MASTERS], + output logic [31:0] master_rdata_o [MASTERS], + + input logic [31:0] slave_addr_mask_i [SLAVES], + input logic [31:0] slave_addr_base_i [SLAVES], + + output logic slave_req_o [SLAVES], + input logic slave_gnt_i [SLAVES], + input logic slave_rvalid_i [SLAVES], + output logic slave_we_o [SLAVES], + output logic [ 3:0] slave_be_o [SLAVES], + output logic [31:0] slave_addr_o [SLAVES], + output logic [31:0] slave_wdata_o [SLAVES], + input logic [31:0] slave_rdata_i [SLAVES] + ); + + genvar m, s; + + logic [MASTER_BITS-1:0] master_sel_int[SLAVES]; + logic [MASTERS-1:0] master_sel_vec[SLAVES]; + logic granted_master[SLAVES]; + + // 为每个slave选择一个master + generate + for (s = 0; s < SLAVES; s = s + 1) begin: master_sel + obi_interconnect_master_sel #( + .MASTERS(MASTERS) + ) master_sel ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(master_req_i), + .master_addr_i(master_addr_i), + .slave_addr_mask_i(slave_addr_mask_i[s]), + .slave_addr_base_i(slave_addr_base_i[s]), + .master_sel_int_o(master_sel_int[s]), + .master_sel_vec_o(master_sel_vec[s]), + .granted_master_o(granted_master[s]) + ); + end + endgenerate + + logic [SLAVE_BITS-1:0] slave_sel_int[MASTERS]; + + // 为每个master选择一个slave + generate + for (m = 0; m < MASTERS; m = m + 1) begin: slave_sel + obi_interconnect_slave_sel #( + .SLAVES(SLAVES) + ) slave_sel ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .master_req_i(master_req_i[m]), + .master_addr_i(master_addr_i[m]), + .slave_addr_mask_i(slave_addr_mask_i), + .slave_addr_base_i(slave_addr_base_i), + .slave_sel_int_o(slave_sel_int[m]) + ); + end + endgenerate + + // slave信号赋值 + generate + for (s = 0; s < SLAVES; s = s + 1) begin: slave_signal + assign slave_req_o[s] = master_req_i[master_sel_int[s]]; + assign slave_we_o[s] = master_we_i[master_sel_int[s]]; + assign slave_be_o[s] = master_be_i[master_sel_int[s]]; + assign slave_addr_o[s] = master_addr_i[master_sel_int[s]]; + assign slave_wdata_o[s] = master_wdata_i[master_sel_int[s]]; + end + endgenerate + + logic [MASTERS-1:0] master_sel_or; + + always_comb begin + master_sel_or = 'b0; + for (integer i = 0; i < SLAVES; i = i + 1) begin: gen_master_sel_or_vec + master_sel_or = master_sel_or | master_sel_vec[i]; + end + end + + // master信号赋值 + generate + for (m = 0; m < MASTERS; m = m + 1) begin: master_gnt_rdata + assign master_gnt_o[m] = master_sel_or[m]; + assign master_rdata_o[m] = slave_rdata_i[slave_sel_int[m]]; + end + endgenerate + + // master信号赋值 + generate + for (m = 0; m < MASTERS; m = m + 1) begin: master_rvalid + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + master_rvalid_o[m] <= 'b0; + end else begin + master_rvalid_o[m] <= master_sel_or[m]; + end + end + end + endgenerate + +endmodule diff --git a/rtl/sys_bus/obi_interconnect_master_sel.sv b/rtl/sys_bus/obi_interconnect_master_sel.sv new file mode 100644 index 0000000..21e7c4e --- /dev/null +++ b/rtl/sys_bus/obi_interconnect_master_sel.sv @@ -0,0 +1,65 @@ + + +// 从多个master之间选择一个 +module obi_interconnect_master_sel #( + parameter int unsigned MASTERS = 3, + parameter MASTER_BITS = MASTERS == 1 ? 1 : $clog2(MASTERS) + )( + input logic clk_i, + input logic rst_ni, + + input logic master_req_i [MASTERS], + input logic [ 31:0] master_addr_i [MASTERS], + input logic [ 31:0] slave_addr_mask_i, + input logic [ 31:0] slave_addr_base_i, + + output logic [MASTER_BITS-1:0] master_sel_int_o, + output logic [MASTERS-1:0] master_sel_vec_o, + output logic granted_master_o + ); + + function integer onehot2int; + input [MASTERS-1:0] onehot; + integer i; + + onehot2int = 0; // prevent latch behavior + + for (i = 1; i < MASTERS; i = i + 1) begin: gen_int + if (onehot[i]) begin + onehot2int = i; + end + end + endfunction + + genvar m; + + logic[MASTERS-1:0] master_req; + + generate + for (m = 0; m < MASTERS; m = m + 1) begin: gen_master_req_vec + assign master_req[m] = master_req_i[m]; + end + endgenerate + + logic[MASTERS-1:0] master_req_vec; + logic[MASTERS-1:0] master_sel_vec; + + generate + // 优先级仲裁机制,LSB优先级最高,MSB优先级最低 + for (m = 0; m < MASTERS; m = m + 1) begin: gen_master_sel_vec + if (m == 0) begin: m_is_0 + assign master_req_vec[m] = 1'b1; + end else begin: m_is_not_0 + assign master_req_vec[m] = ~(|master_req[m-1:0]); + end + assign master_sel_vec[m] = master_req_vec[m] & + master_req_i[m] & + ((master_addr_i[m] & slave_addr_mask_i) == slave_addr_base_i); + end + endgenerate + + assign master_sel_int_o = onehot2int(master_sel_vec); + assign master_sel_vec_o = master_sel_vec; + assign granted_master_o = |master_sel_vec; + +endmodule diff --git a/rtl/sys_bus/obi_interconnect_slave_sel.sv b/rtl/sys_bus/obi_interconnect_slave_sel.sv new file mode 100644 index 0000000..29891f8 --- /dev/null +++ b/rtl/sys_bus/obi_interconnect_slave_sel.sv @@ -0,0 +1,44 @@ + + +// 从多个slave之间选择一个 +module obi_interconnect_slave_sel #( + parameter int unsigned SLAVES = 3, + parameter SLAVE_BITS = SLAVES == 1 ? 1 : $clog2(SLAVES) + )( + input logic clk_i, + input logic rst_ni, + + input logic master_req_i, + input logic [ 31:0] master_addr_i, + input logic [ 31:0] slave_addr_mask_i[SLAVES], + input logic [ 31:0] slave_addr_base_i[SLAVES], + + output logic [SLAVE_BITS-1:0] slave_sel_int_o + ); + + function integer onehot2int; + input [SLAVES-1:0] onehot; + integer i; + + onehot2int = 0; // prevent latch behavior + + for (i = 1; i < SLAVES; i = i + 1) begin: gen_int + if (onehot[i]) begin + onehot2int = i; + end + end + endfunction + + genvar s; + + logic [SLAVES-1:0] slave_sel_vec; + + generate + for (s = 0; s < SLAVES; s = s + 1) begin: gen_slave_sel_vec + assign slave_sel_vec[s] = master_req_i & ((master_addr_i & slave_addr_mask_i[s]) == slave_addr_base_i[s]); + end + endgenerate + + assign slave_sel_int_o = onehot2int(slave_sel_vec); + +endmodule diff --git a/rtl/top/tinyriscv_soc_top.sv b/rtl/top/tinyriscv_soc_top.sv index 8de9457..c0a94e6 100644 --- a/rtl/top/tinyriscv_soc_top.sv +++ b/rtl/top/tinyriscv_soc_top.sv @@ -1,434 +1,155 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -`include "../core/defines.sv" - -// tinyriscv soc顶层模块 -module tinyriscv_soc_top( - - input wire clk, - input wire rst_ext_i, - - output wire halted_ind, // jtag是否已经halt住CPU信号 - - output wire uart_tx_pin, // UART发送引脚 - input wire uart_rx_pin, // UART接收引脚 - - inout wire[1:0] gpio, // GPIO引脚 - - input wire jtag_TCK, // JTAG TCK引脚 - input wire jtag_TMS, // JTAG TMS引脚 - input wire jtag_TDI, // JTAG TDI引脚 - output wire jtag_TDO // JTAG TDO引脚 - - ); - - // master 0 interface - wire[31:0] m0_addr_i; - wire[31:0] m0_data_i; - wire[3:0] m0_sel_i; - wire m0_req_vld_i; - wire m0_rsp_rdy_i; - wire m0_we_i; - wire m0_req_rdy_o; - wire m0_rsp_vld_o; - wire[31:0] m0_data_o; - - // master 1 interface - wire[31:0] m1_addr_i; - wire[31:0] m1_data_i; - wire[3:0] m1_sel_i; - wire m1_req_vld_i; - wire m1_rsp_rdy_i; - wire m1_we_i; - wire m1_req_rdy_o; - wire m1_rsp_vld_o; - wire[31:0] m1_data_o; - - // master 2 interface - wire[31:0] m2_addr_i; - wire[31:0] m2_data_i; - wire[3:0] m2_sel_i; - wire m2_req_vld_i; - wire m2_rsp_rdy_i; - wire m2_we_i; - wire m2_req_rdy_o; - wire m2_rsp_vld_o; - wire[31:0] m2_data_o; - - // master 3 interface - wire[31:0] m3_addr_i; - wire[31:0] m3_data_i; - wire[3:0] m3_sel_i; - wire m3_req_vld_i; - wire m3_rsp_rdy_i; - wire m3_we_i; - wire m3_req_rdy_o; - wire m3_rsp_vld_o; - wire[31:0] m3_data_o; - - // slave 0 interface - wire[31:0] s0_data_i; - wire s0_req_rdy_i; - wire s0_rsp_vld_i; - wire[31:0] s0_addr_o; - wire[31:0] s0_data_o; - wire[3:0] s0_sel_o; - wire s0_req_vld_o; - wire s0_rsp_rdy_o; - wire s0_we_o; - - // slave 1 interface - wire[31:0] s1_data_i; - wire s1_req_rdy_i; - wire s1_rsp_vld_i; - wire[31:0] s1_addr_o; - wire[31:0] s1_data_o; - wire[3:0] s1_sel_o; - wire s1_req_vld_o; - wire s1_rsp_rdy_o; - wire s1_we_o; - - // slave 2 interface - wire[31:0] s2_data_i; - wire s2_req_rdy_i; - wire s2_rsp_vld_i; - wire[31:0] s2_addr_o; - wire[31:0] s2_data_o; - wire[3:0] s2_sel_o; - wire s2_req_vld_o; - wire s2_rsp_rdy_o; - wire s2_we_o; - - // slave 3 interface - wire[31:0] s3_data_i; - wire s3_req_rdy_i; - wire s3_rsp_vld_i; - wire[31:0] s3_addr_o; - wire[31:0] s3_data_o; - wire[3:0] s3_sel_o; - wire s3_req_vld_o; - wire s3_rsp_rdy_o; - wire s3_we_o; - - // slave 4 interface - wire[31:0] s4_data_i; - wire s4_req_rdy_i; - wire s4_rsp_vld_i; - wire[31:0] s4_addr_o; - wire[31:0] s4_data_o; - wire[3:0] s4_sel_o; - wire s4_req_vld_o; - wire s4_rsp_rdy_o; - wire s4_we_o; - - // jtag - wire jtag_halt_req_o; - wire jtag_reset_req_o; - wire[4:0] jtag_reg_addr_o; - wire[31:0] jtag_reg_data_o; - wire jtag_reg_we_o; - wire[31:0] jtag_reg_data_i; - - // tinyriscv - wire[`INT_WIDTH-1:0] int_flag; - wire rst_n; - wire jtag_rst_n; - - // timer0 - wire timer0_int; - - // gpio - wire[1:0] io_in; - wire[31:0] gpio_ctrl; - wire[31:0] gpio_data; - - assign int_flag = {{(`INT_WIDTH-1){1'b0}}, timer0_int}; - - // 复位控制模块例化 - rst_ctrl u_rst_ctrl( - .clk(clk), - .rst_ext_i(rst_ext_i), - .rst_jtag_i(jtag_reset_req_o), - .core_rst_n_o(rst_n), - .jtag_rst_n_o(jtag_rst_n) - ); - - // 低电平点亮LED - // 低电平表示已经halt住CPU - assign halted_ind = ~jtag_halt_req_o; - - // tinyriscv处理器核模块例化 - tinyriscv_core u_tinyriscv_core( - .clk(clk), - .rst_n(rst_n), - - // 指令总线 - .ibus_addr_o(m0_addr_i), - .ibus_data_i(m0_data_o), - .ibus_data_o(m0_data_i), - .ibus_we_o(m0_we_i), - .ibus_sel_o(m0_sel_i), - .ibus_req_valid_o(m0_req_vld_i), - .ibus_req_ready_i(m0_req_rdy_o), - .ibus_rsp_valid_i(m0_rsp_vld_o), - .ibus_rsp_ready_o(m0_rsp_rdy_i), - - // 数据总线 - .dbus_addr_o(m1_addr_i), - .dbus_data_i(m1_data_o), - .dbus_data_o(m1_data_i), - .dbus_we_o(m1_we_i), - .dbus_sel_o(m1_sel_i), - .dbus_req_valid_o(m1_req_vld_i), - .dbus_req_ready_i(m1_req_rdy_o), - .dbus_rsp_valid_i(m1_rsp_vld_o), - .dbus_rsp_ready_o(m1_rsp_rdy_i), - - .jtag_halt_i(jtag_halt_req_o), - .int_i(int_flag) - ); - - // 指令存储器 - rom #( - .DP(`ROM_DEPTH) - ) u_rom( - .clk(clk), - .rst_n(rst_n), - .addr_i(s0_addr_o), - .data_i(s0_data_o), - .sel_i(s0_sel_o), - .we_i(s0_we_o), - .data_o(s0_data_i), - .req_valid_i(s0_req_vld_o), - .req_ready_o(s0_req_rdy_i), - .rsp_valid_o(s0_rsp_vld_i), - .rsp_ready_i(s0_rsp_rdy_o) - ); - - // 数据存储器 - ram #( - .DP(`RAM_DEPTH) - ) u_ram( - .clk(clk), - .rst_n(rst_n), - .addr_i(s1_addr_o), - .data_i(s1_data_o), - .sel_i(s1_sel_o), - .we_i(s1_we_o), - .data_o(s1_data_i), - .req_valid_i(s1_req_vld_o), - .req_ready_o(s1_req_rdy_i), - .rsp_valid_o(s1_rsp_vld_i), - .rsp_ready_i(s1_rsp_rdy_o) - ); - - // timer模块例化 - timer timer_0( - .clk(clk), - .rst_n(rst_n), - .addr_i(s2_addr_o), - .data_i(s2_data_o), - .sel_i(s2_sel_o), - .we_i(s2_we_o), - .data_o(s2_data_i), - .req_valid_i(s2_req_vld_o), - .req_ready_o(s2_req_rdy_i), - .rsp_valid_o(s2_rsp_vld_i), - .rsp_ready_i(s2_rsp_rdy_o), - .int_sig_o(timer0_int) - ); - - // uart模块例化 - uart uart_0( - .clk(clk), - .rst_n(rst_n), - .addr_i(s3_addr_o), - .data_i(s3_data_o), - .sel_i(s3_sel_o), - .we_i(s3_we_o), - .data_o(s3_data_i), - .req_valid_i(s3_req_vld_o), - .req_ready_o(s3_req_rdy_i), - .rsp_valid_o(s3_rsp_vld_i), - .rsp_ready_i(s3_rsp_rdy_o), - .tx_pin(uart_tx_pin), - .rx_pin(uart_rx_pin) - ); - - // io0 - assign gpio[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz; - assign io_in[0] = gpio[0]; - // io1 - assign gpio[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz; - assign io_in[1] = gpio[1]; - - // gpio模块例化 - gpio gpio_0( - .clk(clk), - .rst_n(rst_n), - .addr_i(s4_addr_o), - .data_i(s4_data_o), - .sel_i(s4_sel_o), - .we_i(s4_we_o), - .data_o(s4_data_i), - .req_valid_i(s4_req_vld_o), - .req_ready_o(s4_req_rdy_i), - .rsp_valid_o(s4_rsp_vld_i), - .rsp_ready_i(s4_rsp_rdy_o), - .io_pin_i(io_in), - .reg_ctrl(gpio_ctrl), - .reg_data(gpio_data) - ); - - // jtag模块例化 - jtag_top #( - .DMI_ADDR_BITS(6), - .DMI_DATA_BITS(32), - .DMI_OP_BITS(2) - ) u_jtag_top( - .clk(clk), - .jtag_rst_n(jtag_rst_n), - .jtag_pin_TCK(jtag_TCK), - .jtag_pin_TMS(jtag_TMS), - .jtag_pin_TDI(jtag_TDI), - .jtag_pin_TDO(jtag_TDO), - .reg_we_o(jtag_reg_we_o), - .reg_addr_o(jtag_reg_addr_o), - .reg_wdata_o(jtag_reg_data_o), - .reg_rdata_i(jtag_reg_data_i), - .mem_we_o(m2_we_i), - .mem_addr_o(m2_addr_i), - .mem_wdata_o(m2_data_i), - .mem_rdata_i(m2_data_o), - .mem_sel_o(m2_sel_i), - .req_valid_o(m2_req_vld_i), - .req_ready_i(m2_req_rdy_o), - .rsp_valid_i(m2_rsp_vld_o), - .rsp_ready_o(m2_rsp_rdy_i), - .halt_req_o(jtag_halt_req_o), - .reset_req_o(jtag_reset_req_o) - ); - - // rib总线模块例化 - rib #( - .MASTER_NUM(3), - .SLAVE_NUM(5) - ) u_rib( - .clk(clk), - .rst_n(rst_n), - - // master 0 interface - .m0_addr_i(m0_addr_i), - .m0_data_i(m0_data_i), - .m0_sel_i(m0_sel_i), - .m0_req_vld_i(m0_req_vld_i), - .m0_rsp_rdy_i(m0_rsp_rdy_i), - .m0_we_i(m0_we_i), - .m0_req_rdy_o(m0_req_rdy_o), - .m0_rsp_vld_o(m0_rsp_vld_o), - .m0_data_o(m0_data_o), - - // master 1 interface - .m1_addr_i(m1_addr_i), - .m1_data_i(m1_data_i), - .m1_sel_i(m1_sel_i), - .m1_req_vld_i(m1_req_vld_i), - .m1_rsp_rdy_i(m1_rsp_rdy_i), - .m1_we_i(m1_we_i), - .m1_req_rdy_o(m1_req_rdy_o), - .m1_rsp_vld_o(m1_rsp_vld_o), - .m1_data_o(m1_data_o), - - // master 2 interface - .m2_addr_i(m2_addr_i), - .m2_data_i(m2_data_i), - .m2_sel_i(m2_sel_i), - .m2_req_vld_i(m2_req_vld_i), - .m2_rsp_rdy_i(m2_rsp_rdy_i), - .m2_we_i(m2_we_i), - .m2_req_rdy_o(m2_req_rdy_o), - .m2_rsp_vld_o(m2_rsp_vld_o), - .m2_data_o(m2_data_o), - - // master 3 interface - .m3_addr_i(m3_addr_i), - .m3_data_i(m3_data_i), - .m3_sel_i(m3_sel_i), - .m3_req_vld_i(m3_req_vld_i), - .m3_rsp_rdy_i(m3_rsp_rdy_i), - .m3_we_i(m3_we_i), - .m3_req_rdy_o(m3_req_rdy_o), - .m3_rsp_vld_o(m3_rsp_vld_o), - .m3_data_o(m3_data_o), - - // slave 0 interface - .s0_data_i(s0_data_i), - .s0_req_rdy_i(s0_req_rdy_i), - .s0_rsp_vld_i(s0_rsp_vld_i), - .s0_addr_o(s0_addr_o), - .s0_data_o(s0_data_o), - .s0_sel_o(s0_sel_o), - .s0_req_vld_o(s0_req_vld_o), - .s0_rsp_rdy_o(s0_rsp_rdy_o), - .s0_we_o(s0_we_o), - - // slave 1 interface - .s1_data_i(s1_data_i), - .s1_req_rdy_i(s1_req_rdy_i), - .s1_rsp_vld_i(s1_rsp_vld_i), - .s1_addr_o(s1_addr_o), - .s1_data_o(s1_data_o), - .s1_sel_o(s1_sel_o), - .s1_req_vld_o(s1_req_vld_o), - .s1_rsp_rdy_o(s1_rsp_rdy_o), - .s1_we_o(s1_we_o), - - // slave 2 interface - .s2_data_i(s2_data_i), - .s2_req_rdy_i(s2_req_rdy_i), - .s2_rsp_vld_i(s2_rsp_vld_i), - .s2_addr_o(s2_addr_o), - .s2_data_o(s2_data_o), - .s2_sel_o(s2_sel_o), - .s2_req_vld_o(s2_req_vld_o), - .s2_rsp_rdy_o(s2_rsp_rdy_o), - .s2_we_o(s2_we_o), - - // slave 3 interface - .s3_data_i(s3_data_i), - .s3_req_rdy_i(s3_req_rdy_i), - .s3_rsp_vld_i(s3_rsp_vld_i), - .s3_addr_o(s3_addr_o), - .s3_data_o(s3_data_o), - .s3_sel_o(s3_sel_o), - .s3_req_vld_o(s3_req_vld_o), - .s3_rsp_rdy_o(s3_rsp_rdy_o), - .s3_we_o(s3_we_o), - - // slave 4 interface - .s4_data_i(s4_data_i), - .s4_req_rdy_i(s4_req_rdy_i), - .s4_rsp_vld_i(s4_rsp_vld_i), - .s4_addr_o(s4_addr_o), - .s4_data_o(s4_data_o), - .s4_sel_o(s4_sel_o), - .s4_req_vld_o(s4_req_vld_o), - .s4_rsp_rdy_o(s4_rsp_rdy_o), - .s4_we_o(s4_we_o) - ); - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +`include "../core/defines.sv" + +// tinyriscv soc顶层模块 +module tinyriscv_soc_top( + + input wire clk, + input wire rst_ext_i, + + output wire halted_ind, // jtag是否已经halt住CPU信号 + + output wire uart_tx_pin, // UART发送引脚 + input wire uart_rx_pin, // UART接收引脚 + + inout wire[1:0] gpio, // GPIO引脚 + + input wire jtag_TCK, // JTAG TCK引脚 + input wire jtag_TMS, // JTAG TMS引脚 + input wire jtag_TDI, // JTAG TDI引脚 + output wire jtag_TDO // JTAG TDO引脚 + + ); + + + + localparam int MASTERS = 2; //Number of master ports + localparam int SLAVES = 2; //Number of slave ports + + localparam int CoreD = 0; + localparam int CoreI = 1; + + localparam int Rom = 0; + localparam int Ram = 1; + + + wire master_req [MASTERS]; + wire master_gnt [MASTERS]; + wire master_rvalid [MASTERS]; + wire [31:0] master_addr [MASTERS]; + wire master_we [MASTERS]; + wire [ 3:0] master_be [MASTERS]; + wire [31:0] master_rdata [MASTERS]; + wire [31:0] master_wdata [MASTERS]; + + wire slave_req [SLAVES]; + wire slave_gnt [SLAVES]; + wire slave_rvalid [SLAVES]; + wire [31:0] slave_addr [SLAVES]; + wire slave_we [SLAVES]; + wire [ 3:0] slave_be [SLAVES]; + wire [31:0] slave_rdata [SLAVES]; + wire [31:0] slave_wdata [SLAVES]; + + wire [31:0] slave_addr_mask [SLAVES]; + wire [31:0] slave_addr_base [SLAVES]; + + + tinyriscv_core u_tinyriscv_core( + .clk(clk), + .rst_n(rst_ext_i), + + .instr_req_o(master_req[CoreI]), + .instr_gnt_i(master_gnt[CoreI]), + .instr_rvalid_i(master_rvalid[CoreI]), + .instr_addr_o(master_addr[CoreI]), + .instr_rdata_i(master_rdata[CoreI]), + .instr_err_i(1'b0), + + .data_req_o(master_req[CoreD]), + .data_gnt_i(master_gnt[CoreD]), + .data_rvalid_i(master_rvalid[CoreD]), + .data_we_o(master_we[CoreD]), + .data_be_o(master_be[CoreD]), + .data_addr_o(master_addr[CoreD]), + .data_wdata_o(master_wdata[CoreD]), + .data_rdata_i(master_rdata[CoreD]), + .data_err_i(1'b0), + + .jtag_halt_i(1'b0), + .int_i(0) + ); + + + assign slave_addr_mask[Rom] = ~32'hfffff; + assign slave_addr_base[Rom] = 32'h00000000; + // 指令存储器 + rom #( + .DP(`ROM_DEPTH) + ) u_rom( + .clk(clk), + .rst_n(rst_ext_i), + .addr_i(slave_addr[Rom]), + .data_i(slave_wdata[Rom]), + .sel_i(slave_be[Rom]), + .we_i(slave_we[Rom]), + .data_o(slave_rdata[Rom]) + ); + + assign slave_addr_mask[Ram] = ~32'hfffff; + assign slave_addr_base[Ram] = 32'h10000000; + // 数据存储器 + ram #( + .DP(`RAM_DEPTH) + ) u_ram( + .clk(clk), + .rst_n(rst_ext_i), + .addr_i(slave_addr[Ram]), + .data_i(slave_wdata[Ram]), + .sel_i(slave_be[Ram]), + .we_i(slave_we[Ram]), + .data_o(slave_rdata[Ram]) + ); + + obi_interconnect #( + .MASTERS(MASTERS), + .SLAVES(SLAVES) + ) bus ( + .clk_i(clk), + .rst_ni(rst_ext_i), + .master_req_i(master_req), + .master_gnt_o(master_gnt), + .master_rvalid_o(master_rvalid), + .master_we_i(master_we), + .master_be_i(master_be), + .master_addr_i(master_addr), + .master_wdata_i(master_wdata), + .master_rdata_o(master_rdata), + .slave_addr_mask_i(slave_addr_mask), + .slave_addr_base_i(slave_addr_base), + .slave_req_o(slave_req), + .slave_gnt_i(slave_gnt), + .slave_rvalid_i(slave_rvalid), + .slave_we_o(slave_we), + .slave_be_o(slave_be), + .slave_addr_o(slave_addr), + .slave_wdata_o(slave_wdata), + .slave_rdata_i(slave_rdata) + ); + +endmodule diff --git a/sim/tb_top_verilator.cpp b/sim/tb_top_verilator.cpp index 5e4ce47..047e90d 100644 --- a/sim/tb_top_verilator.cpp +++ b/sim/tb_top_verilator.cpp @@ -66,7 +66,7 @@ int main(int argc, char **argv, char **env) tfp->dump(t); #endif t += 5; - //if (t > 5000) + //if (t > 2000) // break; } #ifdef VCD_TRACE