From a9b7b339607df4aaf24611d3f1b56909377dbf8f Mon Sep 17 00:00:00 2001 From: jstalex <90794457+jstalex@users.noreply.github.com> Date: Wed, 14 Dec 2022 21:58:04 +0300 Subject: [PATCH] added lsu, modified prog.txt --- aps_.ip_user_files/mem_init_files/prog.txt | 14 +- aps_.srcs/sim_1/new/tb_miriscv_top.sv | 33 ++++ aps_.srcs/sources_1/new/decoder_riscv.sv | 4 +- aps_.srcs/sources_1/new/defines_riscv.v | 3 + aps_.srcs/sources_1/new/miriscv_core.sv | 195 +++++++++++++++++++++ aps_.srcs/sources_1/new/miriscv_lsu.sv | 92 ++++++++++ aps_.srcs/sources_1/new/miriscv_ram.sv | 64 +++++++ aps_.srcs/sources_1/new/miriscv_top.sv | 73 ++++++++ aps_.srcs/sources_1/new/oldprg.txt | 45 +++++ aps_.srcs/sources_1/new/prog.txt | 14 +- aps_.srcs/sources_1/new/tb_miriscv_top.sv | 0 aps_.xpr | 50 +++++- tb_miriscv_top_behav.wcfg | 61 +++++++ 13 files changed, 640 insertions(+), 8 deletions(-) create mode 100644 aps_.srcs/sim_1/new/tb_miriscv_top.sv create mode 100644 aps_.srcs/sources_1/new/miriscv_core.sv create mode 100644 aps_.srcs/sources_1/new/miriscv_lsu.sv create mode 100644 aps_.srcs/sources_1/new/miriscv_ram.sv create mode 100644 aps_.srcs/sources_1/new/miriscv_top.sv create mode 100644 aps_.srcs/sources_1/new/oldprg.txt create mode 100644 aps_.srcs/sources_1/new/tb_miriscv_top.sv create mode 100644 tb_miriscv_top_behav.wcfg diff --git a/aps_.ip_user_files/mem_init_files/prog.txt b/aps_.ip_user_files/mem_init_files/prog.txt index 34b1f70..974b6da 100644 --- a/aps_.ip_user_files/mem_init_files/prog.txt +++ b/aps_.ip_user_files/mem_init_files/prog.txt @@ -1,4 +1,4 @@ -00000413 +10000413 00000493 00000913 00a00a13 @@ -43,3 +43,15 @@ fc9ff06f 00000933 00148493 fb9ff06f +@40 +00000001 +00000004 +00000008 +00000005 +0000000b +00000003 +00000001 +00000004 +00000002 +00000007 + diff --git a/aps_.srcs/sim_1/new/tb_miriscv_top.sv b/aps_.srcs/sim_1/new/tb_miriscv_top.sv new file mode 100644 index 0000000..1c69e17 --- /dev/null +++ b/aps_.srcs/sim_1/new/tb_miriscv_top.sv @@ -0,0 +1,33 @@ +`timescale 1ns / 1ps + +module tb_miriscv_top(); + + parameter HF_CYCLE = 2.5; // 200 MHz clock + parameter RST_WAIT = 10; // 10 ns reset + parameter RAM_SIZE = 512; // in 32-bit words + + // clock, reset + reg clk; + reg rst_n; + + miriscv_top #( + .RAM_SIZE ( RAM_SIZE ), + .RAM_INIT_FILE ( "prog.txt" ) + ) dut ( + .clk_i ( clk ), + .rst_n_i ( rst_n ) + ); + + initial begin + clk = 1'b0; + rst_n = 1'b0; + #RST_WAIT; + rst_n = 1'b1; + end + + always begin + #HF_CYCLE; + clk = ~clk; + end + +endmodule \ No newline at end of file diff --git a/aps_.srcs/sources_1/new/decoder_riscv.sv b/aps_.srcs/sources_1/new/decoder_riscv.sv index 254b17b..2468832 100644 --- a/aps_.srcs/sources_1/new/decoder_riscv.sv +++ b/aps_.srcs/sources_1/new/decoder_riscv.sv @@ -1,5 +1,5 @@ `timescale 1ns / 1ps -`include "defines_riscv.v" +// `include "defines_riscv.v" module decoder_riscv ( input logic [31:0] fetched_instr_i, @@ -14,7 +14,7 @@ module decoder_riscv ( output logic illegal_instr_o, // превратится в output logic branch_o, // комбинационно устройство output logic jal_o, // без памяти - output logic jalr_o // + output logic jalr_o ); always_comb begin diff --git a/aps_.srcs/sources_1/new/defines_riscv.v b/aps_.srcs/sources_1/new/defines_riscv.v index fef3929..e179992 100644 --- a/aps_.srcs/sources_1/new/defines_riscv.v +++ b/aps_.srcs/sources_1/new/defines_riscv.v @@ -217,6 +217,9 @@ // old, updated `define WORD_LEN 32 + +`define BYTE_WIDTH 8 + `define ALU_OP_NUM 16 `define INSTR_WIDTH 32 diff --git a/aps_.srcs/sources_1/new/miriscv_core.sv b/aps_.srcs/sources_1/new/miriscv_core.sv new file mode 100644 index 0000000..2730bf7 --- /dev/null +++ b/aps_.srcs/sources_1/new/miriscv_core.sv @@ -0,0 +1,195 @@ +`timescale 1ns / 1ps + +module miriscv_core( + input clk_i, + input arstn_i, + + input [`WORD_LEN-1:0] instr_rdata_i, + output [`WORD_LEN-1:0] instr_addr_o, + + input [`WORD_LEN-1:0] data_rdata_i, + output data_req_o, + output data_we_o, + output [3:0] data_be_o, + output [`WORD_LEN-1:0] data_addr_o, + output [`WORD_LEN-1:0] data_wdata_o +); + +logic [`WORD_LEN-1:0] instruction; +assign instruction = instr_rdata_i; +logic en_pc_n; + +// main decoder connection +logic [1:0] ex_op_a_sel_o; +logic [2:0] ex_op_b_sel_o; +logic [`ALU_OP_WIDTH-1:0] alu_op_o; +logic mem_req_o; +logic mem_we_o; +logic [2:0] mem_size_o; + +logic gpr_we_a_o; +logic wb_src_sel_o; + +logic illegal_instr_o; +logic branch_o; +logic jal_o; +logic jalr_o; + +decoder_riscv main_decoder ( + .fetched_instr_i(instruction), + + .ex_op_a_sel_o(ex_op_a_sel_o), + .ex_op_b_sel_o(ex_op_b_sel_o), + .alu_op_o(alu_op_o), + + .mem_req_o (mem_req_o), + .mem_we_o (mem_we_o), + .mem_size_o(mem_size_o), + + .gpr_we_a_o (gpr_we_a_o), + .wb_src_sel_o(wb_src_sel_o), + + .illegal_instr_o(illegal_instr_o), + .branch_o(branch_o), + .jal_o(jal_o), + .jalr_o(jalr_o) +); + +// sign-extenders for I, S, J, B + +logic [`WORD_LEN-1:0] imm_I; +assign imm_I = {{(`WORD_LEN - 12) {instruction[31]}}, instruction[`I_TYPE_IMM]}; + +logic [`WORD_LEN-1:0] imm_S; +assign imm_S = {{(`WORD_LEN - 12) {instruction[31]}}, instruction[`S_TYPE_IMM_11_5], instruction[`S_TYPE_IMM_4_0]}; + +logic [`WORD_LEN-1:0] imm_J; +assign imm_J = {{(`WORD_LEN - 21) {instruction[31]}}, + instruction[`J_TYPE_IMM_20], + instruction[`J_TYPE_IMM_19_12], + instruction[`J_TYPE_IMM_11], + instruction[`J_TYPE_IMM_10_1], + 1'b0 +}; + +logic [`WORD_LEN-1:0] imm_B; +assign imm_B = {{(`WORD_LEN - 13) {instruction[31]}}, + instruction[`B_TYPE_IMM_12], + instruction[`B_TYPE_IMM_11], + instruction[`B_TYPE_IMM_10_5], + instruction[`B_TYPE_IMM_4_1], + 1'b0 +}; + + +// alu +logic ALU_flag; +logic [`WORD_LEN-1:0] ALU_res; +// pc +// parameter COUNTER_WIDTH = $clog2(`INSTR_DEPTH); +logic [`WORD_LEN-1:0] PC; + + +// rf & data memory + +logic [`WORD_LEN-1:0] memory_rd; // read data form data memory + +logic [`WORD_LEN-1:0] rd1; +logic [`WORD_LEN-1:0] rd2; +logic [`WORD_LEN-1:0] wd; + +// wd multiplexer +always_comb begin + case (wb_src_sel_o) + `WB_EX_RESULT: wd <= ALU_res; + `WB_LSU_DATA: wd <= memory_rd; + default: wd <= 0; + endcase +end + +// connection +rf_riscv rf ( + .clk (clk_i), + .adr_1(instruction[`RA1]), + .adr_2(instruction[`RA2]), + .adr_3(instruction[`WA]), + .wd (wd), + .we (gpr_we_a_o), + .rd_1(rd1), + .rd_2(rd2) +); + +// PC + +assign instr_addr_o = PC; + +logic [`WORD_LEN-1:0] pc_inc; +logic [`WORD_LEN-1:0] pc_inc_imm; +// muxes for pc +assign pc_inc_imm = branch_o ? imm_B : imm_J; +assign pc_inc = (jal_o || (branch_o && ALU_flag)) ? pc_inc_imm : 4; + +always_ff @(posedge clk_i, negedge arstn_i) begin + if (!arstn_i) begin + PC <= 0; + end else if (!en_pc_n) begin // pause from lsu for pc + if (jalr_o) PC <= rd1 + imm_I; + else PC = PC + pc_inc; + end +end + +// ALU +logic [`WORD_LEN-1:0] alu_A; +logic [`WORD_LEN-1:0] alu_B; + +// select A operand +always_comb begin + case (ex_op_a_sel_o) + `OP_A_RS1: alu_A <= rd1; + `OP_A_CURR_PC: alu_A <= PC; + `OP_A_ZERO: alu_A <= 0; + default: alu_A <= 0; + endcase +end + +// select B operand +always_comb begin + case (ex_op_b_sel_o) + `OP_B_RS2: alu_B <= rd2; + `OP_B_IMM_I: alu_B <= imm_I; + `OP_B_IMM_U: alu_B <= {instruction[`U_TYPE_IMM_31_12], {(`WORD_LEN - 20) {1'b0}}}; + `OP_B_IMM_S: alu_B <= imm_S; + `OP_B_INCR: alu_B <= 4; + default: alu_B <= 0; + endcase +end + +alu_riscv alu ( + .A(alu_A), + .B(alu_B), + .ALUOp(alu_op_o), + .Flag (ALU_flag), + .Result(ALU_res) +); + +miriscv_lsu lsu ( + .clk_i(clk_i), + // core protocol + .lsu_addr_i(ALU_res), + .lsu_we_i(mem_we_o), + .lsu_size_i(mem_size_o), + .lsu_data_i(rd2), + .lsu_req_i(mem_req_o), + .lsu_stall_req_o(en_pc_n), + .lsu_data_o(memory_rd), + + // memory protocol + .data_rdata_i(data_rdata_i), + .data_req_o(data_req_o), + .data_we_o(data_we_o), + .data_be_o(data_be_o), + .data_addr_o(data_addr_o), + .data_wdata_o(data_wdata_o) +); + +endmodule diff --git a/aps_.srcs/sources_1/new/miriscv_lsu.sv b/aps_.srcs/sources_1/new/miriscv_lsu.sv new file mode 100644 index 0000000..9f935e0 --- /dev/null +++ b/aps_.srcs/sources_1/new/miriscv_lsu.sv @@ -0,0 +1,92 @@ +`include "defines_riscv.v" + +module miriscv_lsu ( + input clk_i, + + // core protocol + input [`WORD_LEN-1:0] lsu_addr_i, // запрашиваемый адрес + input lsu_we_i, // разрешение записи + input [1:0] lsu_size_i, // для выбора размера записи + input [`WORD_LEN-1:0] lsu_data_i, // wd write data (RD2) + input logic lsu_req_i, // обращение к памяти + output logic lsu_stall_req_o, // подключен напрямую к en_pc + output logic [`WORD_LEN-1:0] lsu_data_o, // rd считанные данные + + // memory protocol + input [`WORD_LEN-1:0] data_rdata_i, // RD RAM данный из памяти + output logic data_req_o, // обращение + output data_we_o, // WE разрешение записи + output logic [3:0] data_be_o, // к каким байтам идет обращение 1-1111 + output logic [`WORD_LEN-1:0] data_addr_o, // адрес + output logic [`WORD_LEN-1:0] data_wdata_o // WD RAM данные для записи +); + +assign data_addr_o = lsu_addr_i; + +logic [1:0] offset; +assign offset = data_addr_o[1:0]; + +// data_req_o and data_we_o нужно поднять на 1 такт для записи/чтения +// by IlORDash +logic toggle_stall; + always_ff @(posedge clk_i) begin + if (lsu_req_i) begin + toggle_stall <= ~toggle_stall; + end else begin + toggle_stall <= 1'b0; + end +end +assign lsu_stall_req_o = lsu_req_i ^ toggle_stall; + +assign data_req_o = lsu_stall_req_o; +assign data_we_o = lsu_we_i && data_req_o; + +// core to lsu interface +always_comb begin + if (lsu_req_i)begin // если обращаемся + if (lsu_we_i) begin // запись + if (data_we_o) data_wdata_o <= lsu_data_i << (offset * 8); + else data_wdata_o <= 32'b0; + end else begin // чтение + case(lsu_size_i) + `LDST_B: lsu_data_o <= {{(`WORD_LEN - 8) {data_rdata_i[7]}}, data_rdata_i[7:0]}; + `LDST_H: lsu_data_o <= {{(`WORD_LEN - 16) {data_rdata_i[15]}}, data_rdata_i[15:0]}; + `LDST_W: lsu_data_o <= data_rdata_i; + `LDST_BU: lsu_data_o <= {24'b0, data_rdata_i[7:0]}; + `LDST_HU: lsu_data_o <= {16'b0, data_rdata_i[15:0]}; + default: lsu_data_o <= 32'b0; + endcase + end + end +end + +// memory to lsu interface + +always_comb begin + case (offset) + 2'b00: begin + if ((lsu_size_i == `LDST_B) || (lsu_size_i == `LDST_BU)) data_be_o <= 4'b0001; + else if ((lsu_size_i == `LDST_H) || (lsu_size_i == `LDST_HU)) data_be_o <= 4'b0011; + else if (lsu_size_i == `LDST_W) data_be_o <= 4'b1111; + end + 2'b01: begin + if ((lsu_size_i == `LDST_B) || (lsu_size_i == `LDST_BU)) data_be_o <= 4'b0010; + else if ((lsu_size_i == `LDST_H) || (lsu_size_i == `LDST_HU)) data_be_o <= 4'b0110; + end + 2'b10: begin + if ((lsu_size_i == `LDST_B) || (lsu_size_i == `LDST_BU)) data_be_o <= 4'b0100; + else if ((lsu_size_i == `LDST_H) || (lsu_size_i == `LDST_HU)) data_be_o <= 4'b1100; + end + 2'b11: if ((lsu_size_i == `LDST_B) || (lsu_size_i == `LDST_BU)) data_be_o <= 4'b1000; + default: data_be_o <= 4'b1111; + endcase +end + +endmodule + + + + + + + diff --git a/aps_.srcs/sources_1/new/miriscv_ram.sv b/aps_.srcs/sources_1/new/miriscv_ram.sv new file mode 100644 index 0000000..77153e5 --- /dev/null +++ b/aps_.srcs/sources_1/new/miriscv_ram.sv @@ -0,0 +1,64 @@ +module miriscv_ram +#( + parameter RAM_SIZE = 512, // bytes + parameter RAM_INIT_FILE = "prog.txt" +)( + // clock, reset + input clk_i, + input rst_n_i, + + // instruction memory interface + output logic [31:0] instr_rdata_o, + input [31:0] instr_addr_i, + + // data memory interface + output logic [31:0] data_rdata_o, + input data_req_i, + input data_we_i, + input [3:0] data_be_i, + input [31:0] data_addr_i, + input [31:0] data_wdata_i +); + + reg [31:0] mem [0:RAM_SIZE/4-1]; + reg [31:0] data_int; + + //Init RAM + integer ram_index; + + initial begin + if(RAM_INIT_FILE != "") + $readmemh(RAM_INIT_FILE, mem); + else + for (ram_index = 0; ram_index < RAM_SIZE/4-1; ram_index = ram_index + 1) + mem[ram_index] = {32{1'b0}}; + end + + + //Instruction port + assign instr_rdata_o = mem[(instr_addr_i % RAM_SIZE) / 4]; + + always@(posedge clk_i) begin + if(!rst_n_i) begin + data_rdata_o <= 32'b0; + end + else if(data_req_i) begin + data_rdata_o <= mem[(data_addr_i % RAM_SIZE) / 4]; + + if(data_we_i && data_be_i[0]) + mem [data_addr_i[31:2]] [7:0] <= data_wdata_i[7:0]; + + if(data_we_i && data_be_i[1]) + mem [data_addr_i[31:2]] [15:8] <= data_wdata_i[15:8]; + + if(data_we_i && data_be_i[2]) + mem [data_addr_i[31:2]] [23:16] <= data_wdata_i[23:16]; + + if(data_we_i && data_be_i[3]) + mem [data_addr_i[31:2]] [31:24] <= data_wdata_i[31:24]; + + end + end + + +endmodule \ No newline at end of file diff --git a/aps_.srcs/sources_1/new/miriscv_top.sv b/aps_.srcs/sources_1/new/miriscv_top.sv new file mode 100644 index 0000000..3099c23 --- /dev/null +++ b/aps_.srcs/sources_1/new/miriscv_top.sv @@ -0,0 +1,73 @@ +module miriscv_top +#( + parameter RAM_SIZE = 512, // bytes + parameter RAM_INIT_FILE = "prog.txt" +)( + // clock, reset + input clk_i, + input rst_n_i +); + + logic [31:0] instr_rdata_core; + logic [31:0] instr_addr_core; + + logic [31:0] data_rdata_core; + logic data_req_core; + logic data_we_core; + logic [3:0] data_be_core; + logic [31:0] data_addr_core; + logic [31:0] data_wdata_core; + + logic [31:0] data_rdata_ram; + logic data_req_ram; + logic data_we_ram; + logic [3:0] data_be_ram; + logic [31:0] data_addr_ram; + logic [31:0] data_wdata_ram; + + logic data_mem_valid; + assign data_mem_valid = (data_addr_core >= RAM_SIZE) ? 1'b0 : 1'b1; + + assign data_rdata_core = (data_mem_valid) ? data_rdata_ram : 1'b0; + assign data_req_ram = (data_mem_valid) ? data_req_core : 1'b0; + assign data_we_ram = data_we_core; + assign data_be_ram = data_be_core; + assign data_addr_ram = data_addr_core; + assign data_wdata_ram = data_wdata_core; + + miriscv_core core ( + .clk_i ( clk_i ), + .arstn_i(rst_n_i), + + .instr_rdata_i ( instr_rdata_core ), + .instr_addr_o ( instr_addr_core ), + + .data_rdata_i ( data_rdata_core ), + .data_req_o ( data_req_core ), + .data_we_o ( data_we_core ), + .data_be_o ( data_be_core ), + .data_addr_o ( data_addr_core ), + .data_wdata_o ( data_wdata_core ) + ); + + miriscv_ram + #( + .RAM_SIZE (RAM_SIZE), + .RAM_INIT_FILE (RAM_INIT_FILE) + ) ram ( + .clk_i ( clk_i ), + .rst_n_i ( rst_n_i ), + + .instr_rdata_o ( instr_rdata_core ), + .instr_addr_i ( instr_addr_core ), + + .data_rdata_o ( data_rdata_ram ), + .data_req_i ( data_req_ram ), + .data_we_i ( data_we_ram ), + .data_be_i ( data_be_ram ), + .data_addr_i ( data_addr_ram ), + .data_wdata_i ( data_wdata_ram ) + ); + + +endmodule \ No newline at end of file diff --git a/aps_.srcs/sources_1/new/oldprg.txt b/aps_.srcs/sources_1/new/oldprg.txt new file mode 100644 index 0000000..34b1f70 --- /dev/null +++ b/aps_.srcs/sources_1/new/oldprg.txt @@ -0,0 +1,45 @@ +00000413 +00000493 +00000913 +00a00a13 +0544d863 +00249293 +008282b3 +0002a303 +00135393 +00139393 +02638863 +00900933 +01495e63 +00291e13 +008e0e33 +004e2e83 +01de2023 +00190913 +fe9ff06f +000e2223 +fffa0a13 +fff48493 +00148493 +fb5ff06f +000004b3 +00000933 +0544d663 +409a0ab3 +03595c63 +00291393 +008383b3 +00438293 +0003ae03 +0002a303 +006e5863 +000e0613 +00030e13 +00060313 +0062a023 +01c3a023 +00190913 +fc9ff06f +00000933 +00148493 +fb9ff06f diff --git a/aps_.srcs/sources_1/new/prog.txt b/aps_.srcs/sources_1/new/prog.txt index 34b1f70..974b6da 100644 --- a/aps_.srcs/sources_1/new/prog.txt +++ b/aps_.srcs/sources_1/new/prog.txt @@ -1,4 +1,4 @@ -00000413 +10000413 00000493 00000913 00a00a13 @@ -43,3 +43,15 @@ fc9ff06f 00000933 00148493 fb9ff06f +@40 +00000001 +00000004 +00000008 +00000005 +0000000b +00000003 +00000001 +00000004 +00000002 +00000007 + diff --git a/aps_.srcs/sources_1/new/tb_miriscv_top.sv b/aps_.srcs/sources_1/new/tb_miriscv_top.sv new file mode 100644 index 0000000..e69de29 diff --git a/aps_.xpr b/aps_.xpr index 71f281f..a948b0c 100644 --- a/aps_.xpr +++ b/aps_.xpr @@ -32,7 +32,7 @@