parent
ceddc1af24
commit
f03f42fc9b
|
@ -7,16 +7,8 @@ set_property IOSTANDARD LVCMOS33 [get_ports clk]
|
|||
set_property PACKAGE_PIN N14 [get_ports clk]
|
||||
|
||||
# 复位引脚
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
|
||||
set_property PACKAGE_PIN L13 [get_ports rst_n]
|
||||
|
||||
# 程序执行完毕指示引脚
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports over]
|
||||
set_property PACKAGE_PIN M16 [get_ports over]
|
||||
|
||||
# 程序执行成功指示引脚
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports succ]
|
||||
set_property PACKAGE_PIN N16 [get_ports succ]
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports rst_ext_i]
|
||||
set_property PACKAGE_PIN L13 [get_ports rst_ext_i]
|
||||
|
||||
# CPU停住指示引脚
|
||||
set_property IOSTANDARD LVCMOS33 [get_ports halted_ind]
|
||||
|
|
|
@ -128,15 +128,23 @@ module exu_alu_datapath(
|
|||
wire[31:0] slt_res = (~op1_ge_op2_signed)? 32'h1: 32'h0;
|
||||
wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0;
|
||||
|
||||
wire[31:0] alu_datapath_res = ({32{op_xor}} & xor_res) |
|
||||
({32{op_or}} & or_res) |
|
||||
({32{op_and}} & and_res) |
|
||||
({32{op_add | op_sub}} & add_sub_res) |
|
||||
({32{op_sll}} & sll_res) |
|
||||
({32{op_srl}} & srl_res) |
|
||||
({32{op_sra}} & sra_res) |
|
||||
({32{op_slt}} & slt_res) |
|
||||
({32{op_sltu}} & sltu_res);
|
||||
reg[31:0] alu_datapath_res;
|
||||
|
||||
always @ (*) begin
|
||||
alu_datapath_res = 32'h0;
|
||||
case (1'b1)
|
||||
op_xor: alu_datapath_res = xor_res;
|
||||
op_or: alu_datapath_res = or_res;
|
||||
op_and: alu_datapath_res = and_res;
|
||||
op_add: alu_datapath_res = add_sub_res;
|
||||
op_sub: alu_datapath_res = add_sub_res;
|
||||
op_sll: alu_datapath_res = sll_res;
|
||||
op_srl: alu_datapath_res = srl_res;
|
||||
op_sra: alu_datapath_res = sra_res;
|
||||
op_slt: alu_datapath_res = slt_res;
|
||||
op_sltu: alu_datapath_res = sltu_res;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign alu_res_o = alu_datapath_res;
|
||||
|
||||
|
|
|
@ -59,16 +59,34 @@ module exu_commit(
|
|||
|
||||
assign reg_we_o = muldiv_reg_we_i | mem_reg_we_i | csr_reg_we_i | use_alu_res | bjp_reg_we_i;
|
||||
|
||||
assign reg_waddr_o = ({5{muldiv_reg_we_i}} & muldiv_reg_waddr_i) |
|
||||
({5{mem_reg_we_i}} & mem_reg_waddr_i) |
|
||||
({5{csr_reg_we_i}} & csr_reg_waddr_i) |
|
||||
({5{bjp_reg_we_i}} & bjp_reg_waddr_i) |
|
||||
({5{rd_we_i}} & rd_waddr_i);
|
||||
reg[4:0] reg_waddr;
|
||||
|
||||
assign reg_wdata_o = ({32{muldiv_reg_we_i}} & muldiv_reg_wdata_i) |
|
||||
({32{mem_reg_we_i}} & mem_reg_wdata_i) |
|
||||
({32{csr_reg_we_i}} & csr_reg_wdata_i) |
|
||||
({32{bjp_reg_we_i}} & bjp_reg_wdata_i) |
|
||||
({32{use_alu_res}} & alu_reg_wdata_i);
|
||||
always @ (*) begin
|
||||
reg_waddr = 5'h0;
|
||||
case (1'b1)
|
||||
muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i;
|
||||
mem_reg_we_i: reg_waddr = mem_reg_waddr_i;
|
||||
csr_reg_we_i: reg_waddr = csr_reg_waddr_i;
|
||||
bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i;
|
||||
rd_we_i: reg_waddr = rd_waddr_i;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign reg_waddr_o = reg_waddr;
|
||||
|
||||
reg[31:0] reg_wdata;
|
||||
|
||||
always @ (*) begin
|
||||
reg_wdata = 32'h0;
|
||||
case (1'b1)
|
||||
muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i;
|
||||
mem_reg_we_i: reg_wdata = mem_reg_wdata_i;
|
||||
csr_reg_we_i: reg_wdata = csr_reg_wdata_i;
|
||||
bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i;
|
||||
use_alu_res: reg_wdata = alu_reg_wdata_i;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign reg_wdata_o = reg_wdata;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -61,36 +61,71 @@ module exu_mem(
|
|||
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;
|
||||
|
||||
// store操作
|
||||
wire[31:0] sb_res = ({32{mem_addr_index00}} & {24'h0, mem_rs2_data_i[7:0]}) |
|
||||
({32{mem_addr_index01}} & {16'h0, mem_rs2_data_i[7:0], 8'h0}) |
|
||||
({32{mem_addr_index10}} & {8'h0, mem_rs2_data_i[7:0], 16'h0}) |
|
||||
({32{mem_addr_index11}} & {mem_rs2_data_i[7:0], 24'h0});
|
||||
reg[31:0] sb_res;
|
||||
|
||||
wire[31:0] sh_res = ({32{mem_addr_index00}} & {16'h0, mem_rs2_data_i[15:0]}) |
|
||||
({32{mem_addr_index10}} & {mem_rs2_data_i[15:0], 16'h0});
|
||||
always @ (*) begin
|
||||
sb_res = 32'h0;
|
||||
case (1'b1)
|
||||
mem_addr_index00: sb_res = {24'h0, mem_rs2_data_i[7:0]};
|
||||
mem_addr_index01: sb_res = {16'h0, mem_rs2_data_i[7:0], 8'h0};
|
||||
mem_addr_index10: sb_res = {8'h0, mem_rs2_data_i[7:0], 16'h0};
|
||||
mem_addr_index11: sb_res = {mem_rs2_data_i[7:0], 24'h0};
|
||||
endcase
|
||||
end
|
||||
|
||||
reg[31:0] sh_res;
|
||||
|
||||
always @ (*) begin
|
||||
sh_res = 32'h0;
|
||||
case (1'b1)
|
||||
mem_addr_index00: sh_res = {16'h0, mem_rs2_data_i[15:0]};
|
||||
mem_addr_index10: sh_res = {mem_rs2_data_i[15:0], 16'h0};
|
||||
endcase
|
||||
end
|
||||
|
||||
wire[31:0] sw_res = mem_rs2_data_i;
|
||||
|
||||
// load操作
|
||||
wire[31:0] lb_res = ({32{mem_addr_index00}} & {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]}) |
|
||||
({32{mem_addr_index01}} & {{24{mem_op_lb_i & mem_rdata_i[15]}}, mem_rdata_i[15:8]}) |
|
||||
({32{mem_addr_index10}} & {{24{mem_op_lb_i & mem_rdata_i[23]}}, mem_rdata_i[23:16]}) |
|
||||
({32{mem_addr_index11}} & {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]});
|
||||
reg[31:0] lb_res;
|
||||
|
||||
wire[31:0] lh_res = ({32{mem_addr_index00}} & {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]}) |
|
||||
({32{mem_addr_index10}} & {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]});
|
||||
always @ (*) begin
|
||||
lb_res = 32'h0;
|
||||
case (1'b1)
|
||||
mem_addr_index00: lb_res = {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]};
|
||||
mem_addr_index01: lb_res = {{24{mem_op_lb_i & mem_rdata_i[15]}}, mem_rdata_i[15:8]};
|
||||
mem_addr_index10: lb_res = {{24{mem_op_lb_i & mem_rdata_i[23]}}, mem_rdata_i[23:16]};
|
||||
mem_addr_index11: lb_res = {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]};
|
||||
endcase
|
||||
end
|
||||
|
||||
reg[31:0] lh_res;
|
||||
|
||||
always @ (*) begin
|
||||
lh_res = 32'h0;
|
||||
case (1'b1)
|
||||
mem_addr_index00: lh_res = {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]};
|
||||
mem_addr_index10: lh_res = {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]};
|
||||
endcase
|
||||
end
|
||||
|
||||
wire[31:0] lw_res = mem_rdata_i;
|
||||
|
||||
// 写回内存或者寄存器的数据
|
||||
assign mem_wdata_o = ({32{mem_op_sb_i}} & sb_res) |
|
||||
({32{mem_op_sh_i}} & sh_res) |
|
||||
({32{mem_op_sw_i}} & sw_res) |
|
||||
({32{mem_op_lb_i | mem_op_lbu_i}} & lb_res) |
|
||||
({32{mem_op_lh_i | mem_op_lhu_i}} & lh_res) |
|
||||
({32{mem_op_lw_i}} & lw_res);
|
||||
reg[31:0] mem_wdata;
|
||||
|
||||
always @ (*) begin
|
||||
mem_wdata = 32'h0;
|
||||
case (1'b1)
|
||||
mem_op_sb_i: mem_wdata = sb_res;
|
||||
mem_op_sh_i: mem_wdata = sh_res;
|
||||
mem_op_sw_i: mem_wdata = sw_res;
|
||||
mem_op_lb_i: mem_wdata = lb_res;
|
||||
mem_op_lbu_i: mem_wdata = lb_res;
|
||||
mem_op_lh_i: mem_wdata = lh_res;
|
||||
mem_op_lhu_i: mem_wdata = lh_res;
|
||||
mem_op_lw_i: mem_wdata = lw_res;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign mem_wdata_o = mem_wdata;
|
||||
|
||||
wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i);
|
||||
wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o);
|
||||
|
|
|
@ -86,10 +86,17 @@ module exu_muldiv(
|
|||
wire[31:0] mulh_res = (op1_is_signed ^ op2_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32];
|
||||
wire[31:0] mulhsu_res = (op1_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32];
|
||||
|
||||
wire[31:0] mul_op_res = ({32{muldiv_op_mul_i}} & mul_res) |
|
||||
({32{muldiv_op_mulhu_i}} & mulhu_res) |
|
||||
({32{muldiv_op_mulh_i}} & mulh_res) |
|
||||
({32{muldiv_op_mulhsu_i}} & mulhsu_res);
|
||||
reg[31:0] mul_op_res;
|
||||
|
||||
always @ (*) begin
|
||||
mul_op_res = 32'h0;
|
||||
case (1'b1)
|
||||
muldiv_op_mul_i: mul_op_res = mul_res;
|
||||
muldiv_op_mulhu_i: mul_op_res = mulhu_res;
|
||||
muldiv_op_mulh_i: mul_op_res = mulh_res;
|
||||
muldiv_op_mulhsu_i: mul_op_res = mulhsu_res;
|
||||
endcase
|
||||
end
|
||||
|
||||
// 运算结果
|
||||
assign muldiv_reg_wdata_o = div_result | mul_op_res;
|
||||
|
|
|
@ -46,6 +46,7 @@ module ifu(
|
|||
assign req_valid_o = (~rst_n)? 1'b0:
|
||||
(flush_i)? 1'b0:
|
||||
stall_i[`STALL_PC]? 1'b0:
|
||||
jtag_halt_i? 1'b0:
|
||||
1'b1;
|
||||
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
|
||||
|
||||
|
@ -53,7 +54,7 @@ module ifu(
|
|||
wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o);
|
||||
|
||||
// 在执行多周期指令或者请求不到总线时需要暂停
|
||||
wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked) | jtag_halt_i;
|
||||
wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked);
|
||||
|
||||
reg[31:0] pc;
|
||||
reg[31:0] pc_prev;
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// 复位控制模块
|
||||
module rst_ctrl(
|
||||
|
||||
input wire clk,
|
||||
|
||||
input wire rst_ext_i,
|
||||
input wire rst_jtag_i,
|
||||
|
||||
output wire core_rst_n_o,
|
||||
output wire jtag_rst_n_o
|
||||
|
||||
);
|
||||
|
||||
wire ext_rst_r;
|
||||
|
||||
gen_ticks_sync #(
|
||||
.DP(2),
|
||||
.DW(1)
|
||||
) ext_rst_sync(
|
||||
.rst_n(rst_ext_i),
|
||||
.clk(clk),
|
||||
.din(1'b1),
|
||||
.dout(ext_rst_r)
|
||||
);
|
||||
|
||||
reg jtag_rst_r;
|
||||
|
||||
always @ (posedge clk or posedge rst_jtag_i) begin
|
||||
if (rst_jtag_i) begin
|
||||
jtag_rst_r <= 1'b0;
|
||||
end else begin
|
||||
jtag_rst_r <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
assign core_rst_n_o = ext_rst_r & jtag_rst_r;
|
||||
assign jtag_rst_n_o = ext_rst_r;
|
||||
|
||||
endmodule
|
|
@ -20,10 +20,8 @@
|
|||
module tinyriscv_soc_top(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire rst_ext_i,
|
||||
|
||||
output reg over, // 测试是否完成信号
|
||||
output reg succ, // 测试是否成功信号
|
||||
output wire halted_ind, // jtag是否已经halt住CPU信号
|
||||
|
||||
output wire uart_tx_pin, // UART发送引脚
|
||||
|
@ -147,6 +145,8 @@ module tinyriscv_soc_top(
|
|||
|
||||
// tinyriscv
|
||||
wire[`INT_WIDTH-1:0] int_flag;
|
||||
wire rst_n;
|
||||
wire jtag_rst_n;
|
||||
|
||||
// timer0
|
||||
wire timer0_int;
|
||||
|
@ -158,20 +158,19 @@ module tinyriscv_soc_top(
|
|||
|
||||
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;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
over <= 1'b1;
|
||||
succ <= 1'b1;
|
||||
end else begin
|
||||
over <= ~u_tinyriscv_core.u_gpr_reg.regs[26]; // when = 1, run over
|
||||
succ <= ~u_tinyriscv_core.u_gpr_reg.regs[27]; // when = 1, run succ, otherwise fail
|
||||
end
|
||||
end
|
||||
|
||||
// tinyriscv处理器核模块例化
|
||||
tinyriscv_core u_tinyriscv_core(
|
||||
.clk(clk),
|
||||
|
@ -302,7 +301,7 @@ module tinyriscv_soc_top(
|
|||
.DMI_OP_BITS(2)
|
||||
) u_jtag_top(
|
||||
.clk(clk),
|
||||
.jtag_rst_n(rst_n),
|
||||
.jtag_rst_n(jtag_rst_n),
|
||||
.jtag_pin_TCK(jtag_TCK),
|
||||
.jtag_pin_TMS(jtag_TMS),
|
||||
.jtag_pin_TDI(jtag_TDI),
|
||||
|
|
|
@ -44,6 +44,7 @@ def main():
|
|||
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu_idu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/pipe_ctrl.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/tinyriscv_core.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/rst_ctrl.v')
|
||||
# ../rtl/perips
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/ram.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/rom.v')
|
||||
|
|
|
@ -44,14 +44,16 @@ module tinyriscv_soc_tb;
|
|||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst_n = 1'b0;
|
||||
rst_n = 1'b1;
|
||||
`ifdef TEST_JTAG
|
||||
TCK = 1;
|
||||
TMS = 1;
|
||||
TDI = 1;
|
||||
`endif
|
||||
$display("test running...");
|
||||
#40
|
||||
#100
|
||||
rst_n = 1'b0;
|
||||
#100
|
||||
rst_n = 1'b1;
|
||||
#200
|
||||
/*
|
||||
|
@ -520,7 +522,7 @@ module tinyriscv_soc_tb;
|
|||
|
||||
tinyriscv_soc_top tinyriscv_soc_top_0(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n)
|
||||
.rst_ext_i(rst_n)
|
||||
`ifdef TEST_JTAG
|
||||
,
|
||||
.jtag_TCK(TCK),
|
||||
|
|
|
@ -39,14 +39,16 @@ module tinyriscv_soc_tb;
|
|||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst_n = 1'b0;
|
||||
rst_n = 1'b1;
|
||||
`ifdef TEST_JTAG
|
||||
TCK = 1;
|
||||
TMS = 1;
|
||||
TDI = 1;
|
||||
`endif
|
||||
$display("test running...");
|
||||
#40
|
||||
#100
|
||||
rst_n = 1'b0;
|
||||
#100
|
||||
rst_n = 1'b1;
|
||||
#200
|
||||
|
||||
|
@ -506,7 +508,7 @@ module tinyriscv_soc_tb;
|
|||
|
||||
tinyriscv_soc_top tinyriscv_soc_top_0(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n)
|
||||
.rst_ext_i(rst_n)
|
||||
`ifdef TEST_JTAG
|
||||
,
|
||||
.jtag_TCK(TCK),
|
||||
|
|
Loading…
Reference in New Issue