optimize ifu and lsu

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-04-09 20:22:34 +08:00
parent e3667e0ddd
commit f1f09584ee
11 changed files with 611 additions and 509 deletions

View File

@ -32,6 +32,9 @@
../rtl/perips/uart.sv ../rtl/perips/uart.sv
../rtl/sys_bus/rib.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 ../rtl/top/tinyriscv_soc_top.sv

View File

@ -33,14 +33,13 @@ module exu(
// mem // mem
input wire[31:0] mem_rdata_i, // 内存输入数据 input wire[31:0] mem_rdata_i, // 内存输入数据
input wire mem_req_ready_i, input wire mem_gnt_i,
input wire mem_rsp_valid_i, input wire mem_rvalid_i,
output wire[31:0] mem_wdata_o, // 写内存数据 output wire[31:0] mem_wdata_o, // 写内存数据
output wire[31:0] mem_addr_o, // 读、写内存地址 output wire[31:0] mem_addr_o, // 读、写内存地址
output wire mem_we_o, // 是否要写内存 output wire mem_we_o, // 是否要写内存
output wire[3:0] mem_sel_o, // 字节位 output wire[3:0] mem_be_o, // 字节位
output wire mem_req_valid_o, output wire mem_req_o,
output wire mem_rsp_ready_o,
output wire mem_access_misaligned_o, output wire mem_access_misaligned_o,
// gpr_reg // gpr_reg
@ -291,8 +290,8 @@ module exu(
.req_mem_i(req_mem_o), .req_mem_i(req_mem_o),
.mem_addr_i(alu_res_o), .mem_addr_i(alu_res_o),
.mem_rs2_data_i(mem_rs2_data_o), .mem_rs2_data_i(mem_rs2_data_o),
.mem_req_ready_i(mem_req_ready_i), .mem_gnt_i(mem_gnt_i),
.mem_rsp_valid_i(mem_rsp_valid_i), .mem_rvalid_i(mem_rvalid_i),
.mem_rdata_i(mem_rdata_i), .mem_rdata_i(mem_rdata_i),
.mem_op_lb_i(mem_op_lb_o), .mem_op_lb_i(mem_op_lb_o),
.mem_op_lh_i(mem_op_lh_o), .mem_op_lh_i(mem_op_lh_o),
@ -308,9 +307,8 @@ module exu(
.mem_wdata_o(mem_wdata), .mem_wdata_o(mem_wdata),
.mem_reg_we_o(mem_reg_we_o), .mem_reg_we_o(mem_reg_we_o),
.mem_mem_we_o(mem_mem_we_o), .mem_mem_we_o(mem_mem_we_o),
.mem_sel_o(mem_sel_o), .mem_be_o(mem_be_o),
.mem_req_valid_o(mem_req_valid_o), .mem_req_o(mem_req_o)
.mem_rsp_ready_o(mem_rsp_ready_o)
); );
wire[31:0] muldiv_reg_wdata_o; wire[31:0] muldiv_reg_wdata_o;

View File

@ -26,8 +26,8 @@ module exu_mem(
input wire[31:0] mem_addr_i, input wire[31:0] mem_addr_i,
input wire[31:0] mem_rs2_data_i, input wire[31:0] mem_rs2_data_i,
input wire[31:0] mem_rdata_i, input wire[31:0] mem_rdata_i,
input wire mem_req_ready_i, input wire mem_gnt_i,
input wire mem_rsp_valid_i, input wire mem_rvalid_i,
input wire mem_op_lb_i, input wire mem_op_lb_i,
input wire mem_op_lh_i, input wire mem_op_lh_i,
input wire mem_op_lw_i, input wire mem_op_lw_i,
@ -43,9 +43,8 @@ module exu_mem(
output wire[31:0] mem_wdata_o, output wire[31:0] mem_wdata_o,
output wire mem_reg_we_o, output wire mem_reg_we_o,
output wire mem_mem_we_o, output wire mem_mem_we_o,
output wire[3:0] mem_sel_o, output wire[3:0] mem_be_o,
output wire mem_req_valid_o, output wire mem_req_o
output wire mem_rsp_ready_o
); );
@ -56,10 +55,10 @@ module exu_mem(
wire mem_addr_index10 = (mem_addr_index == 2'b10); wire mem_addr_index10 = (mem_addr_index == 2'b10);
wire mem_addr_index11 = (mem_addr_index == 2'b11); wire mem_addr_index11 = (mem_addr_index == 2'b11);
assign mem_sel_o[0] = mem_addr_index00 | mem_op_sw_i; assign mem_be_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_be_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_be_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[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i;
reg[31:0] sb_res; reg[31:0] sb_res;
@ -127,6 +126,68 @@ module exu_mem(
assign mem_wdata_o = mem_wdata; 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_req_hsked = (mem_req_valid_o & mem_req_ready_i);
wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o); 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]): 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]: (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]:
0; 0;
*/
endmodule endmodule

View File

@ -22,27 +22,127 @@ module ifu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire flush_i, input wire flush_i, // 跳转标志
input wire[31:0] flush_addr_i, // 跳转地址 input wire[31:0] flush_addr_i, // 跳转地址
input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志 input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志
input wire jtag_halt_i, input wire jtag_halt_i,
output wire[31:0] inst_o, output wire[31:0] inst_o,
output wire[31:0] pc_o, output wire[31:0] pc_o,
output wire inst_valid_o, output wire inst_valid_o,
output wire[31:0] ibus_addr_o, output wire instr_req_o,
input wire[31:0] ibus_data_i, input wire instr_gnt_i,
output wire[31:0] ibus_data_o, input wire instr_rvalid_i,
output wire[3:0] ibus_sel_o, output wire[31:0] instr_addr_o,
output wire ibus_we_o, input wire[31:0] instr_rdata_i,
output wire req_valid_o, input wire instr_err_i
input wire req_ready_i,
input wire rsp_valid_i,
output wire rsp_ready_o
); );
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: assign req_valid_o = (~rst_n)? 1'b0:
(flush_i)? 1'b0: (flush_i)? 1'b0:
stall_i[`STALL_PC]? 1'b0: stall_i[`STALL_PC]? 1'b0:
@ -122,5 +222,6 @@ module ifu(
assign ibus_sel_o = 4'b1111; assign ibus_sel_o = 4'b1111;
assign ibus_we_o = 1'b0; assign ibus_we_o = 1'b0;
assign ibus_data_o = 32'h0; assign ibus_data_o = 32'h0;
*/
endmodule endmodule

View File

@ -22,25 +22,22 @@ module tinyriscv_core(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
output wire[31:0] dbus_addr_o, output wire instr_req_o,
input wire[31:0] dbus_data_i, input wire instr_gnt_i,
output wire[31:0] dbus_data_o, input wire instr_rvalid_i,
output wire[3:0] dbus_sel_o, output wire[31:0] instr_addr_o,
output wire dbus_we_o, input wire[31:0] instr_rdata_i,
output wire dbus_req_valid_o, input wire instr_err_i,
input wire dbus_req_ready_i,
input wire dbus_rsp_valid_i,
output wire dbus_rsp_ready_o,
output wire[31:0] ibus_addr_o, // 取指地址 output wire data_req_o,
input wire[31:0] ibus_data_i, // 取到的指令内容 input wire data_gnt_i,
output wire[31:0] ibus_data_o, input wire data_rvalid_i,
output wire[3:0] ibus_sel_o, output wire data_we_o,
output wire ibus_we_o, output wire[3:0] data_be_o,
output wire ibus_req_valid_o, output wire[31:0] data_addr_o,
input wire ibus_req_ready_i, output wire[31:0] data_wdata_o,
input wire ibus_rsp_valid_i, input wire[31:0] data_rdata_i,
output wire ibus_rsp_ready_o, input wire data_err_i,
input wire jtag_halt_i, input wire jtag_halt_i,
input wire[`INT_WIDTH-1:0] int_i // 中断输入信号 input wire[`INT_WIDTH-1:0] int_i // 中断输入信号
@ -131,13 +128,6 @@ module tinyriscv_core(
wire[31:0] clint_int_addr_o; wire[31:0] clint_int_addr_o;
wire clint_int_assert_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( ifu u_ifu(
.clk(clk), .clk(clk),
@ -149,15 +139,13 @@ module tinyriscv_core(
.inst_o(ifetch_inst_o), .inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o), .pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o), .inst_valid_o(ifetch_inst_valid_o),
.ibus_addr_o(ibus_addr_o),
.ibus_data_i(ibus_data_i), .instr_req_o(instr_req_o),
.ibus_data_o(ibus_data_o), .instr_gnt_i(instr_gnt_i),
.ibus_sel_o(ibus_sel_o), .instr_rvalid_i(instr_rvalid_i),
.ibus_we_o(ibus_we_o), .instr_addr_o(instr_addr_o),
.req_valid_o(ibus_req_valid_o), .instr_rdata_i(instr_rdata_i),
.req_ready_i(ibus_req_ready_i), .instr_err_i(instr_err_i)
.rsp_valid_i(ibus_rsp_valid_i),
.rsp_ready_o(ibus_rsp_ready_o)
); );
pipe_ctrl u_pipe_ctrl( pipe_ctrl u_pipe_ctrl(
@ -265,15 +253,14 @@ module tinyriscv_core(
.rst_n(rst_n), .rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o), .reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o), .reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(dbus_data_i), .mem_rdata_i(data_rdata_i),
.mem_req_ready_i(dbus_req_ready_i), .mem_gnt_i(data_gnt_i),
.mem_rsp_valid_i(dbus_rsp_valid_i), .mem_rvalid_i(data_rvalid_i),
.mem_wdata_o(ex_mem_wdata_o), .mem_wdata_o(data_wdata_o),
.mem_addr_o(ex_mem_addr_o), .mem_addr_o(data_addr_o),
.mem_we_o(ex_mem_we_o), .mem_we_o(data_we_o),
.mem_sel_o(ex_mem_sel_o), .mem_be_o(data_be_o),
.mem_req_valid_o(ex_mem_req_valid_o), .mem_req_o(data_req_o),
.mem_rsp_ready_o(ex_mem_rsp_ready_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o), .mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o), .reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o), .reg_we_o(ex_reg_we_o),

View File

@ -581,6 +581,7 @@ module tracer(
$display("Writing execution trace to %s", file_name); $display("Writing execution trace to %s", file_name);
file_handle = $fopen(file_name, "w"); file_handle = $fopen(file_name, "w");
$fwrite(file_handle, "\t\t\tTime\t\tCycle\tPC\t\t\tInsn\t\tDecoded instruction\n"); $fwrite(file_handle, "\t\t\tTime\t\tCycle\tPC\t\t\tInsn\t\tDecoded instruction\n");
$fflush(file_handle);
end 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, "%15t\t%d\t\t%h\t%s\t%s", $time, cycle, pc_i, insn_str, decoded_str);
$fwrite(file_handle, "\n"); $fwrite(file_handle, "\n");
$fflush(file_handle);
endfunction endfunction
// log execution // log execution

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -36,399 +36,120 @@ module tinyriscv_soc_top(
); );
// 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 localparam int MASTERS = 2; //Number of master ports
wire[31:0] m2_addr_i; localparam int SLAVES = 2; //Number of slave ports
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 localparam int CoreD = 0;
wire[31:0] m3_addr_i; localparam int CoreI = 1;
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 localparam int Rom = 0;
wire[31:0] s0_data_i; localparam int Ram = 1;
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 master_req [MASTERS];
wire[31:0] s2_data_i; wire master_gnt [MASTERS];
wire s2_req_rdy_i; wire master_rvalid [MASTERS];
wire s2_rsp_vld_i; wire [31:0] master_addr [MASTERS];
wire[31:0] s2_addr_o; wire master_we [MASTERS];
wire[31:0] s2_data_o; wire [ 3:0] master_be [MASTERS];
wire[3:0] s2_sel_o; wire [31:0] master_rdata [MASTERS];
wire s2_req_vld_o; wire [31:0] master_wdata [MASTERS];
wire s2_rsp_rdy_o;
wire s2_we_o;
// slave 3 interface wire slave_req [SLAVES];
wire[31:0] s3_data_i; wire slave_gnt [SLAVES];
wire s3_req_rdy_i; wire slave_rvalid [SLAVES];
wire s3_rsp_vld_i; wire [31:0] slave_addr [SLAVES];
wire[31:0] s3_addr_o; wire slave_we [SLAVES];
wire[31:0] s3_data_o; wire [ 3:0] slave_be [SLAVES];
wire[3:0] s3_sel_o; wire [31:0] slave_rdata [SLAVES];
wire s3_req_vld_o; wire [31:0] slave_wdata [SLAVES];
wire s3_rsp_rdy_o;
wire s3_we_o;
// slave 4 interface wire [31:0] slave_addr_mask [SLAVES];
wire[31:0] s4_data_i; wire [31:0] slave_addr_base [SLAVES];
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( tinyriscv_core u_tinyriscv_core(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_ext_i),
// 指令总线 .instr_req_o(master_req[CoreI]),
.ibus_addr_o(m0_addr_i), .instr_gnt_i(master_gnt[CoreI]),
.ibus_data_i(m0_data_o), .instr_rvalid_i(master_rvalid[CoreI]),
.ibus_data_o(m0_data_i), .instr_addr_o(master_addr[CoreI]),
.ibus_we_o(m0_we_i), .instr_rdata_i(master_rdata[CoreI]),
.ibus_sel_o(m0_sel_i), .instr_err_i(1'b0),
.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),
// 数据总线 .data_req_o(master_req[CoreD]),
.dbus_addr_o(m1_addr_i), .data_gnt_i(master_gnt[CoreD]),
.dbus_data_i(m1_data_o), .data_rvalid_i(master_rvalid[CoreD]),
.dbus_data_o(m1_data_i), .data_we_o(master_we[CoreD]),
.dbus_we_o(m1_we_i), .data_be_o(master_be[CoreD]),
.dbus_sel_o(m1_sel_i), .data_addr_o(master_addr[CoreD]),
.dbus_req_valid_o(m1_req_vld_i), .data_wdata_o(master_wdata[CoreD]),
.dbus_req_ready_i(m1_req_rdy_o), .data_rdata_i(master_rdata[CoreD]),
.dbus_rsp_valid_i(m1_rsp_vld_o), .data_err_i(1'b0),
.dbus_rsp_ready_o(m1_rsp_rdy_i),
.jtag_halt_i(jtag_halt_req_o), .jtag_halt_i(1'b0),
.int_i(int_flag) .int_i(0)
); );
assign slave_addr_mask[Rom] = ~32'hfffff;
assign slave_addr_base[Rom] = 32'h00000000;
// 指令存储器 // 指令存储器
rom #( rom #(
.DP(`ROM_DEPTH) .DP(`ROM_DEPTH)
) u_rom( ) u_rom(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_ext_i),
.addr_i(s0_addr_o), .addr_i(slave_addr[Rom]),
.data_i(s0_data_o), .data_i(slave_wdata[Rom]),
.sel_i(s0_sel_o), .sel_i(slave_be[Rom]),
.we_i(s0_we_o), .we_i(slave_we[Rom]),
.data_o(s0_data_i), .data_o(slave_rdata[Rom])
.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)
); );
assign slave_addr_mask[Ram] = ~32'hfffff;
assign slave_addr_base[Ram] = 32'h10000000;
// 数据存储器 // 数据存储器
ram #( ram #(
.DP(`RAM_DEPTH) .DP(`RAM_DEPTH)
) u_ram( ) u_ram(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_ext_i),
.addr_i(s1_addr_o), .addr_i(slave_addr[Ram]),
.data_i(s1_data_o), .data_i(slave_wdata[Ram]),
.sel_i(s1_sel_o), .sel_i(slave_be[Ram]),
.we_i(s1_we_o), .we_i(slave_we[Ram]),
.data_o(s1_data_i), .data_o(slave_rdata[Ram])
.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模块例化 obi_interconnect #(
timer timer_0( .MASTERS(MASTERS),
.clk(clk), .SLAVES(SLAVES)
.rst_n(rst_n), ) bus (
.addr_i(s2_addr_o), .clk_i(clk),
.data_i(s2_data_o), .rst_ni(rst_ext_i),
.sel_i(s2_sel_o), .master_req_i(master_req),
.we_i(s2_we_o), .master_gnt_o(master_gnt),
.data_o(s2_data_i), .master_rvalid_o(master_rvalid),
.req_valid_i(s2_req_vld_o), .master_we_i(master_we),
.req_ready_o(s2_req_rdy_i), .master_be_i(master_be),
.rsp_valid_o(s2_rsp_vld_i), .master_addr_i(master_addr),
.rsp_ready_i(s2_rsp_rdy_o), .master_wdata_i(master_wdata),
.int_sig_o(timer0_int) .master_rdata_o(master_rdata),
); .slave_addr_mask_i(slave_addr_mask),
.slave_addr_base_i(slave_addr_base),
// uart模块例化 .slave_req_o(slave_req),
uart uart_0( .slave_gnt_i(slave_gnt),
.clk(clk), .slave_rvalid_i(slave_rvalid),
.rst_n(rst_n), .slave_we_o(slave_we),
.addr_i(s3_addr_o), .slave_be_o(slave_be),
.data_i(s3_data_o), .slave_addr_o(slave_addr),
.sel_i(s3_sel_o), .slave_wdata_o(slave_wdata),
.we_i(s3_we_o), .slave_rdata_i(slave_rdata)
.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 endmodule

View File

@ -66,7 +66,7 @@ int main(int argc, char **argv, char **env)
tfp->dump(t); tfp->dump(t);
#endif #endif
t += 5; t += 5;
//if (t > 5000) //if (t > 2000)
// break; // break;
} }
#ifdef VCD_TRACE #ifdef VCD_TRACE