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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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