From 4ca3c9d44e36d0546e743fc5b896cceed2f904a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@cern.ch> Date: Wed, 22 Apr 2015 14:18:01 +0200 Subject: [PATCH] xwb_lm32: first version of WR node profile --- modules/wishbone/wb_dpram/Manifest.py | 3 +- modules/wishbone/wb_lm32/README.txt | 1 + modules/wishbone/wb_lm32/gen_lmcores.py | 2 + .../wb_lm32/generated/lm32_allprofiles.v | 96468 ++++++++++++++-- .../wishbone/wb_lm32/generated/xwb_lm32.vhd | 81 + modules/wishbone/wb_lm32/lm32.profiles | 3 +- modules/wishbone/wb_lm32/src/lm32_cpu.v | 78 +- modules/wishbone/wb_lm32/src/lm32_include.v | 6 +- .../wb_lm32/src/lm32_instruction_unit.v | 78 +- .../wb_lm32/src/lm32_load_store_unit.v | 216 +- 10 files changed, 88586 insertions(+), 8350 deletions(-) diff --git a/modules/wishbone/wb_dpram/Manifest.py b/modules/wishbone/wb_dpram/Manifest.py index 4f1dc37c..61982715 100644 --- a/modules/wishbone/wb_dpram/Manifest.py +++ b/modules/wishbone/wb_dpram/Manifest.py @@ -1,2 +1 @@ -files = ["xwb_dpram.vhd", - "xwb_dpram_mixed.vhd"] +files = ["xwb_dpram.vhd"] diff --git a/modules/wishbone/wb_lm32/README.txt b/modules/wishbone/wb_lm32/README.txt index 555342f0..4b8531e0 100644 --- a/modules/wishbone/wb_lm32/README.txt +++ b/modules/wishbone/wb_lm32/README.txt @@ -11,6 +11,7 @@ Currently there are 6 different profiles (all support interrupts) - medium_(icache_)debug - the above 2 versions with full JTAG debugger - full - full LM32 core (all instructions + I/D caches + bus errors) - full_debug - full core with debug +- wrnode - special profile with internal single-cycle code/data RAM, for the WR node design The profiles are defined in lm32.profiles file. If you want to add/remove any, re-run gen_lmcores.py script afterwards (requires Modelsim vlog compiler for preprocessing Verilog sources). diff --git a/modules/wishbone/wb_lm32/gen_lmcores.py b/modules/wishbone/wb_lm32/gen_lmcores.py index 65135d70..44b2e387 100755 --- a/modules/wishbone/wb_lm32/gen_lmcores.py +++ b/modules/wishbone/wb_lm32/gen_lmcores.py @@ -87,6 +87,8 @@ def gen_customized_version(profile_name, feats): `define CFG_DCACHE_BYTES_PER_LINE 16\n\ `define CFG_DCACHE_BASE_ADDRESS 32'h0\n\ `define CFG_DCACHE_LIMIT 32'h7fffffff\n\ + `define CFG_IRAM_BASE_ADDRESS 0\n\ + `define CFG_IRAM_LIMIT 32'h000fffff\n\ `ifdef CFG_WITH_DEBUG\n\ `define CFG_JTAG_ENABLED\n\ `define CFG_JTAG_UART_ENABLED\n\ diff --git a/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v b/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v index 2300bebb..04e57d78 100644 --- a/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v +++ b/modules/wishbone/wb_lm32/generated/lm32_allprofiles.v @@ -1,15 +1,638 @@ -module lm32_top_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_full_debug ( + clk_i, rst_i, + + interrupt, + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -19,6 +642,9 @@ module lm32_top_full ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -29,19 +655,58 @@ module lm32_top_full ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -60,6 +725,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -78,6 +746,72 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + +wire [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_q; +wire jtag_update; +wire [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_q; +wire jtck; +wire jrstn; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -85,6 +819,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -97,22 +832,89 @@ begin clogb2_v1 = i-1; end endfunction -lm32_cpu_full + + + + + + + + +lm32_cpu_full_debug #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), + + + + + + + + + + + + .jtag_clk (jtck), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + + + .I_DAT_I (I_DAT_I), .I_ACK_I (I_ACK_I), .I_ERR_I (I_ERR_I), .I_RTY_I (I_RTY_I), + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d), + + + + + + + + + + + + .I_DAT_O (I_DAT_O), .I_ADR_O (I_ADR_O), .I_CYC_O (I_CYC_O), @@ -122,6 +924,9 @@ lm32_cpu_full .I_CTI_O (I_CTI_O), .I_LOCK_O (I_LOCK_O), .I_BTE_O (I_BTE_O), + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -132,42 +937,521 @@ lm32_cpu_full .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); + + + + +jtag_cores jtag_cores ( + + .reg_d (jtag_reg_d), + .reg_addr_d (jtag_reg_addr_d), + + .reg_update (jtag_update), + .reg_q (jtag_reg_q), + .reg_addr_q (jtag_reg_addr_q), + .jtck (jtck), + .jrstn (jrstn) + ); + + + endmodule -module lm32_mc_arithmetic_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_full_debug ( + clk_i, rst_i, stall_d, kill_x, + + divide_d, modulus_d, + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + divide_by_zero_x, + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + input divide_d; input modulus_d; + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + output divide_by_zero_x; reg divide_by_zero_x; + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + wire [32:0] t; + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + assign t = {p[ 32-2:0], a[ 32-1]} - b; + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -176,13 +1460,25 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + divide_by_zero_x <= 1'b0; + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + divide_by_zero_x <= 1'b0; + + case (state) 3'b000: begin @@ -192,12 +1488,42 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + if (divide_d == 1'b1) state <= 3'b011 ; if (modulus_d == 1'b1) state <= 3'b010 ; + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + 3'b011 : begin if (t[32] == 1'b0) @@ -213,6 +1539,7 @@ begin result_x <= a; if ((cycles == 32'd0) || (kill_x == 1'b1)) begin + divide_by_zero_x <= b == { 32{1'b0}}; state <= 3'b000; end @@ -233,27 +1560,517 @@ begin result_x <= p; if ((cycles == 32'd0) || (kill_x == 1'b1)) begin + divide_by_zero_x <= b == { 32{1'b0}}; state <= 3'b000; end cycles <= cycles - 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule -module lm32_cpu_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_full_debug ( + clk_i, + + + + rst_i, + + + interrupt, + + + + + + + + + + + + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + + + + + jtag_reg_d, + jtag_reg_addr_d, + + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -263,6 +2080,23 @@ module lm32_cpu_full ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -272,33 +2106,168 @@ module lm32_cpu_full ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; + + +parameter deba_reset = 32'h10000000; + + parameter sdb_address = 32'h00000000; + + + parameter icache_associativity = 1; parameter icache_sets = 256; parameter icache_bytes_per_line = 16; parameter icache_base_address = 32'h0; parameter icache_limit = 32'h7fffffff; + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 256; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 32'h0; parameter dcache_limit = 32'h7fffffff; -parameter watchpoints = 0; + + + + + + + + + + + +parameter watchpoints = 32'h4; + + + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; + + + + + + + + + + + +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + +output [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -317,6 +2286,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -335,12 +2307,33 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + reg valid_a; + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -377,30 +2370,57 @@ reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; + + wire q_d; wire x_result_sel_mc_arith_d; reg x_result_sel_mc_arith_x; + + + + + + + + + wire x_result_sel_sext_d; reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + wire m_result_sel_shift_d; reg m_result_sel_shift_x; reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + wire w_result_sel_mul_d; reg w_result_sel_mul_x; reg w_result_sel_mul_m; reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -423,126 +2443,409 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (4 -1):0] csr_d; -reg [ (4 -1):0] csr_x; +wire [ (5-1):0] csr_d; +reg [ (5-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + +wire break_d; +reg break_x; + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; + + + + + + + +wire bret_d; +reg bret_x; +wire bret_q_x; + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + wire bus_error_d; reg bus_error_x; reg data_bus_error_exception_m; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] memop_pc_w; + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; + + + + wire [ (32-1):0] sextb_result_x; wire [ (32-1):0] sexth_result_x; wire [ (32-1):0] sext_result_x; + + + + + + + + + + + wire direction_d; reg direction_x; wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + wire divide_d; wire divide_q_d; wire modulus_d; wire modulus_q_d; wire divide_by_zero_x; + + + + + + wire mc_stall_request_x; wire [ (32-1):0] mc_result_x; + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; + + wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; + + wire iflush; wire icache_stall_request; wire icache_restart_request; wire icache_refill_request; wire icache_refilling; + + + + + + wire dflush_x; reg dflush_m; wire dcache_stall_request; wire dcache_restart_request; wire dcache_refill_request; wire dcache_refilling; + + wire [ (32-1):0] load_data_w; wire stall_wb_load; + + + + + + +wire [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + + + + +wire jtag_csr_write_enable; +wire [ (32-1):0] jtag_csr_write_data; +wire [ (5-1):0] jtag_csr; +wire jtag_read_enable; +wire [ 7:0] jtag_read_data; +wire jtag_write_enable; +wire [ 7:0] jtag_write_data; +wire [ (32-1):0] jtag_address; +wire jtag_access_complete; + + + + +wire jtag_break; + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + wire branch_taken_x; + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; + reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + + +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; + + reg [ (3-1):0] eid_x; + + + + + + + + + + +wire dc_ss; + + +wire dc_re; +wire bp_match; +wire wp_match; wire exception_x; -reg exception_m; -reg exception_w; -wire exception_q_w; +reg exception_m; +wire debug_exception_x; +reg debug_exception_m; +reg debug_exception_w; +wire debug_exception_q_w; +wire non_debug_exception_x; +reg non_debug_exception_m; +reg non_debug_exception_w; +wire non_debug_exception_q_w; + + + + + + + + + + + + +wire reset_exception; + + + + + + wire interrupt_exception; + + + + +wire breakpoint_exception; +wire watchpoint_exception; + + + + wire instruction_bus_error_exception; wire data_bus_error_exception; + + + + wire divide_by_zero_exception; + + wire system_call_exception; + + + reg data_bus_error_seen; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -550,6 +2853,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -562,7 +2866,16 @@ begin clogb2_v1 = i-1; end endfunction -lm32_instruction_unit_full #( + + + + + + + + + +lm32_instruction_unit_full_debug #( .eba_reset (eba_reset), .associativity (icache_associativity), .sets (icache_sets), @@ -570,8 +2883,10 @@ lm32_instruction_unit_full #( .base_address (icache_base_address), .limit (icache_limit) ) instruction_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_f (stall_f), .stall_d (stall_d), @@ -582,29 +2897,63 @@ lm32_instruction_unit_full #( .kill_f (kill_f), .branch_predict_taken_d (branch_predict_taken_d), .branch_predict_address_d (branch_predict_address_d), + + .branch_taken_x (branch_taken_x), .branch_target_x (branch_target_x), + + .exception_m (exception_m), .branch_taken_m (branch_taken_m), .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), + + .iflush (iflush), + + + + .dcache_restart_request (dcache_restart_request), .dcache_refill_request (dcache_refill_request), .dcache_refilling (dcache_refilling), + + + + + .i_dat_i (I_DAT_I), .i_ack_i (I_ACK_I), .i_err_i (I_ERR_I), .i_rty_i (I_RTY_I), + + + + + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + + + + .pc_f (pc_f), .pc_d (pc_d), .pc_x (pc_x), .pc_m (pc_m), .pc_w (pc_w), + + .icache_stall_request (icache_stall_request), .icache_restart_request (icache_restart_request), .icache_refill_request (icache_refill_request), .icache_refilling (icache_refilling), + + + + + .i_dat_o (I_DAT_O), .i_adr_o (I_ADR_O), .i_cyc_o (I_CYC_O), @@ -614,23 +2963,80 @@ lm32_instruction_unit_full #( .i_cti_o (I_CTI_O), .i_lock_o (I_LOCK_O), .i_bte_o (I_BTE_O), + + + + + + + + + + + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + + + + .bus_error_d (bus_error_d), + + + + .instruction_f (instruction_f), + + + + .instruction_d (instruction_d) + + + ); -lm32_decoder_full decoder ( + + +lm32_decoder_full_debug decoder ( + .instruction (instruction_d), + .d_result_sel_0 (d_result_sel_0_d), .d_result_sel_1 (d_result_sel_1_d), .x_result_sel_csr (x_result_sel_csr_d), + + .x_result_sel_mc_arith (x_result_sel_mc_arith_d), + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + .x_result_sel_logic (x_result_sel_logic_d), + + + + .x_result_sel_add (x_result_sel_add_d), .m_result_sel_compare (m_result_sel_compare_d), + + .m_result_sel_shift (m_result_sel_shift_d), + + .w_result_sel_load (w_result_sel_load_d), + + .w_result_sel_mul (w_result_sel_mul_d), + + .x_bypass_enable (x_bypass_enable_d), .m_bypass_enable (m_bypass_enable_d), .read_enable_0 (read_enable_0_d), @@ -647,27 +3053,62 @@ lm32_decoder_full decoder ( .sign_extend (sign_extend_d), .adder_op (adder_op_d), .logic_op (logic_op_d), + + .direction (direction_d), + + + + + + + + + + + + + .divide (divide_d), .modulus (modulus_d), + + .branch (branch_d), .bi_unconditional (bi_unconditional), .bi_conditional (bi_conditional), .branch_reg (branch_reg_d), .condition (condition_d), + + + .break_opcode (break_d), + + .scall (scall_d), .eret (eret_d), + + + .bret (bret_d), + + + + + + .csr_write_enable (csr_write_enable_d) ); -lm32_load_store_unit_full #( + + +lm32_load_store_unit_full_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), .base_address (dcache_base_address), .limit (dcache_limit) ) load_store_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_x (stall_x), .stall_m (stall_m), @@ -686,17 +3127,41 @@ lm32_load_store_unit_full #( .store_q_m (store_q_m), .sign_extend_x (sign_extend_x), .size_x (size_x), + + .dflush (dflush_m), + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), .d_ack_i (D_ACK_I), .d_err_i (D_ERR_I), .d_rty_i (D_RTY_I), + + + + .dcache_refill_request (dcache_refill_request), .dcache_restart_request (dcache_restart_request), .dcache_stall_request (dcache_stall_request), .dcache_refilling (dcache_refilling), + + .load_data_w (load_data_w), .stall_wb_load (stall_wb_load), + .d_dat_o (D_DAT_O), .d_adr_o (D_ADR_O), .d_cyc_o (D_CYC_O), @@ -707,22 +3172,36 @@ lm32_load_store_unit_full #( .d_lock_o (D_LOCK_O), .d_bte_o (D_BTE_O) ); + + lm32_adder adder ( + .adder_op_x (adder_op_x), .adder_op_x_n (adder_op_x_n), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .adder_result_x (adder_result_x), .adder_carry_n_x (adder_carry_n_x), .adder_overflow_x (adder_overflow_x) ); + + lm32_logic_op logic_op ( + .logic_op_x (logic_op_x), .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + .logic_result_x (logic_result_x) ); + + + + lm32_shifter shifter ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), @@ -730,47 +3209,243 @@ lm32_shifter shifter ( .sign_extend_x (sign_extend_x), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .shifter_result_m (shifter_result_m) ); + + + + + + lm32_multiplier multiplier ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), .stall_m (stall_m), .operand_0 (d_result_0), .operand_1 (d_result_1), + .result (multiplier_result_w) ); -lm32_mc_arithmetic_full mc_arithmetic ( + + + + + + +lm32_mc_arithmetic_full_debug mc_arithmetic ( + .clk_i (clk_i), .rst_i (rst_i), .stall_d (stall_d), .kill_x (kill_x), + + .divide_d (divide_q_d), .modulus_d (modulus_q_d), + + + + + + + + + + + + .operand_0_d (d_result_0), .operand_1_d (d_result_1), + .result_x (mc_result_x), + + .divide_by_zero_x (divide_by_zero_x), + + .stall_request_x (mc_stall_request_x) ); -lm32_interrupt_full interrupt_unit ( + + + + + + +lm32_interrupt_full_debug interrupt_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .interrupt (interrupt), + .stall_x (stall_x), - .exception (exception_q_w), + + + .non_debug_exception (non_debug_exception_q_w), + .debug_exception (debug_exception_q_w), + + + + .eret_q_x (eret_q_x), + + + .bret_q_x (bret_q_x), + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), + .interrupt_exception (interrupt_exception), + .csr_read_data (interrupt_csr_read_data_x) ); + + + + + + +lm32_jtag_full_debug jtag ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .jtag_clk (jtag_clk), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + .stall_x (stall_x), + + + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + + + + + .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), + + + + + + + .jtx_csr_read_data (jtx_csr_read_data), + .jrx_csr_read_data (jrx_csr_read_data), + + + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + + + + + .jtag_break (jtag_break), + .jtag_reset (reset_exception), + + + + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d) + ); + + + + + + +lm32_debug_full_debug #( + .breakpoints (breakpoints), + .watchpoints (watchpoints) + ) hw_debug ( + + .clk_i (clk_i), + .rst_i (rst_i), + .pc_x (pc_x), + .load_x (load_x), + .store_x (store_x), + .load_store_address_x (adder_result_x), + .csr_write_enable_x (csr_write_enable_q_x), + .csr_write_data (operand_1_x), + .csr_x (csr_x), + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + + + + + .eret_q_x (eret_q_x), + .bret_q_x (bret_q_x), + .stall_x (stall_x), + .exception_x (exception_x), + .q_x (q_x), + + + .dcache_refill_request (dcache_refill_request), + + + + + + + + .dc_ss (dc_ss), + + + .dc_re (dc_re), + .bp_match (bp_match), + .wp_match (wp_match) + ); + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; reg [31:0] w_result_d; reg regfile_raw_0, regfile_raw_0_nxt; reg regfile_raw_1, regfile_raw_1_nxt; + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) begin if (reg_write_enable_q_w @@ -778,22 +3453,39 @@ lm32_interrupt_full interrupt_unit ( regfile_raw_0_nxt = 1'b1; else regfile_raw_0_nxt = 1'b0; + if (reg_write_enable_q_w && (write_idx_w == instruction_f[20:16])) regfile_raw_1_nxt = 1'b1; else regfile_raw_1_nxt = 1'b0; end + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) if (regfile_raw_0) reg_data_live_0 = w_result_d; else reg_data_live_0 = regfile_data_0; + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) if (regfile_raw_1) reg_data_live_1 = w_result_d; else reg_data_live_1 = regfile_data_1; + + + + always @(posedge clk_i ) if (rst_i == 1'b1) begin @@ -807,22 +3499,31 @@ lm32_interrupt_full interrupt_unit ( regfile_raw_1 <= regfile_raw_1_nxt; w_result_d <= w_result; end + + + + + lm32_dp_ram #( + .addr_depth(1<<5), .addr_width(5), .data_width(32) ) reg_0 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[25:21]), + .rdata_o (regfile_data_0) ); + lm32_dp_ram #( .addr_depth(1<<5), @@ -831,22 +3532,118 @@ lm32_interrupt_full interrupt_unit ( ) reg_1 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[20:16]), + .rdata_o (regfile_data_1) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + always @(*) begin if ( ( (x_bypass_enable_x == 1'b0) @@ -864,6 +3661,8 @@ begin else interlock = 1'b0; end + + always @(*) begin if (raw_x_0 == 1'b1) @@ -875,6 +3674,8 @@ begin else bypass_data_0 = reg_data_0; end + + always @(*) begin if (raw_x_1 == 1'b1) @@ -886,10 +3687,25 @@ begin else bypass_data_1 = reg_data_1; end + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + assign branch_target_d = pc_d + branch_offset_d; + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + always @(*) begin d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; @@ -900,9 +3716,30 @@ begin default: d_result_1 = { 32{1'bx}}; endcase end + + + + + + + + + + + assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + assign cmp_zero = operand_0_x == operand_1_x; assign cmp_negative = adder_result_x[ 32-1]; assign cmp_overflow = adder_overflow_x; @@ -921,32 +3758,70 @@ begin default: condition_met_x = 1'bx; endcase end + + always @(*) begin x_result = x_result_sel_add_x ? adder_result_x : x_result_sel_csr_x ? csr_read_data_x + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + : x_result_sel_mc_arith_x ? mc_result_x + + : logic_result_x; end + + always @(*) begin m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + : m_result_sel_shift_m ? shifter_result_m + + : operand_m; end + + always @(*) begin w_result = w_result_sel_load_w ? load_data_w + + : w_result_sel_mul_w ? multiplier_result_w + + : operand_w; end + + + + assign branch_taken_x = (stall_x == 1'b0) && ( (branch_x == 1'b1) && ((condition_x == 3'b000) || (condition_x == 3'b110)) && (valid_x == 1'b1) && (branch_predict_x == 1'b0) ); + + + + assign branch_taken_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -961,9 +3836,13 @@ assign branch_taken_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign branch_mispredict_taken_m = (condition_met_m == 1'b0) && (branch_predict_m == 1'b1) && (branch_predict_taken_m == 1'b1); + + assign branch_flushX_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -976,71 +3855,262 @@ assign branch_flushX_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign kill_f = ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) || (branch_taken_m == 1'b1) + + || (branch_taken_x == 1'b1) + + + + || (icache_refill_request == 1'b1) + + + + || (dcache_refill_request == 1'b1) + + ; assign kill_d = (branch_taken_m == 1'b1) + + || (branch_taken_x == 1'b1) + + + + || (icache_refill_request == 1'b1) + + + + || (dcache_refill_request == 1'b1) + + ; assign kill_x = (branch_flushX_m == 1'b1) + + || (dcache_refill_request == 1'b1) + + ; assign kill_m = 1'b0 + + || (dcache_refill_request == 1'b1) + + ; assign kill_w = 1'b0 + + || (dcache_refill_request == 1'b1) + + ; + + + + + +assign breakpoint_exception = ( ( (break_x == 1'b1) + || (bp_match == 1'b1) + ) + && (valid_x == 1'b1) + ) + + + || (jtag_break == 1'b1) + + + ; + + + + + +assign watchpoint_exception = wp_match == 1'b1; + + + + + assign instruction_bus_error_exception = ( (bus_error_x == 1'b1) && (valid_x == 1'b1) ); assign data_bus_error_exception = data_bus_error_seen == 1'b1; + + + + + assign divide_by_zero_exception = divide_by_zero_x == 1'b1; + + + assign system_call_exception = ( (scall_x == 1'b1) + + && (valid_x == 1'b1) + + ); -assign exception_x = (system_call_exception == 1'b1) + + + +assign debug_exception_x = (breakpoint_exception == 1'b1) + || (watchpoint_exception == 1'b1) + ; + +assign non_debug_exception_x = (system_call_exception == 1'b1) + + + || (reset_exception == 1'b1) + + + + || (instruction_bus_error_exception == 1'b1) || (data_bus_error_exception == 1'b1) + + + + || (divide_by_zero_exception == 1'b1) + + + + || ( (interrupt_exception == 1'b1) + + + && (dc_ss == 1'b0) + + + + && (store_q_m == 1'b0) && (D_CYC_O == 1'b0) + + ) + + ; + +assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin + + + + + if (reset_exception == 1'b1) + eid_x = 3'h0; + else + + + + + if (data_bus_error_exception == 1'b1) + eid_x = 3'h4; + else + + + if (breakpoint_exception == 1'b1) + eid_x = 3'd1; + else + + + + if (data_bus_error_exception == 1'b1) eid_x = 3'h4; else if (instruction_bus_error_exception == 1'b1) eid_x = 3'h2; else + + + + + if (watchpoint_exception == 1'b1) + eid_x = 3'd3; + else + + + + if (divide_by_zero_exception == 1'b1) eid_x = 3'h5; else + + + + if ( (interrupt_exception == 1'b1) + + + && (dc_ss == 1'b0) + + ) eid_x = 3'h6; else + + eid_x = 3'h7; end + + + assign stall_a = (stall_f == 1'b1); + assign stall_f = (stall_d == 1'b1); + assign stall_d = (stall_x == 1'b1) || ( (interlock == 1'b1) && (kill_d == 1'b0) ) || ( ( (eret_d == 1'b1) || (scall_d == 1'b1) + + || (bus_error_d == 1'b1) + + ) && ( (load_q_x == 1'b1) || (load_q_m == 1'b1) @@ -1050,115 +4120,434 @@ assign stall_d = (stall_x == 1'b1) ) && (kill_d == 1'b0) ) + + + || ( ( (break_d == 1'b1) + || (bret_d == 1'b1) + ) + && ( (load_q_x == 1'b1) + || (store_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) ) + + + + + + + + + + ; + assign stall_x = (stall_m == 1'b1) + + || ( (mc_stall_request_x == 1'b1) && (kill_x == 1'b0) ) + + + + ; + assign stall_m = (stall_wb_load == 1'b1) + + + + || ( (D_CYC_O == 1'b1) && ( (store_m == 1'b1) + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + || (load_m == 1'b1) || (load_x == 1'b1) ) ) + + + + || (dcache_stall_request == 1'b1) + + + + || (icache_stall_request == 1'b1) || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) + + + + + + + + + + + + ; + + + + assign q_d = (valid_d == 1'b1) && (kill_d == 1'b0); + + + + + + + + + + + + + assign divide_q_d = (divide_d == 1'b1) && (q_d == 1'b1); assign modulus_q_d = (modulus_d == 1'b1) && (q_d == 1'b1); + + assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + +assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); + + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + + + && (bp_match == 1'b0) + + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + + + && (bp_match == 1'b0) + + ; + + + + assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); -assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + +assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); +assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); + + + + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + assign cfg = { 6'h02, watchpoints[3:0], breakpoints[3:0], interrupts[5:0], + + + 1'b1, + + + + + + + + 1'b0, - 1'b0, - 1'b0, - 1'b0, + + + + + 1'b1, + + + + + + 1'b1, + + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + + 1'b0, + + + + + + 1'b0, + + + + 1'b1, + + + + + + 1'b1, + + + + + + 1'b1, + + + + + + 1'b1 + + + + }; + assign cfg2 = { 30'b0, + + + + 1'b0, + + + + + + 1'b0 + + }; + + + + assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 4 'h3) + && (csr_d == 5'h3) && (stall_d == 1'b0) && (kill_d == 1'b0) && (valid_d == 1'b1)) + + + + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h3)) + + ; + + + + assign dflush_x = ( (csr_write_enable_q_x == 1'b1) - && (csr_x == 4 'h4)) + && (csr_x == 5'h4)) + + + + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h4)) + + ; -assign csr_d = read_idx_0_d[ (4 -1):0]; + + + + +assign csr_d = read_idx_0_d[ (5-1):0]; + + always @(*) begin case (csr_x) - 4 'h0, - 4 'h1, - 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; - 4 'h6: csr_read_data_x = cfg; - 4 'h7: csr_read_data_x = {eba, 8'h00}; - 4 'ha: csr_read_data_x = cfg2; - 4 'hb: csr_read_data_x = sdb_address; + + + 5'h0, + 5'h1, + 5'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + + 5'h6: csr_read_data_x = cfg; + 5'h7: csr_read_data_x = {eba, 8'h00}; + + + 5'h9: csr_read_data_x = {deba, 8'h00}; + + + + + 5'he: csr_read_data_x = jtx_csr_read_data; + 5'hf: csr_read_data_x = jrx_csr_read_data; + + + 5'ha: csr_read_data_x = cfg2; + 5'hb: csr_read_data_x = sdb_address; + default: csr_read_data_x = { 32{1'bx}}; endcase end + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) + eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - data_bus_error_seen <= 1'b0; + deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - if ((D_ERR_I == 1'b1) && (D_CYC_O == 1'b1)) - data_bus_error_seen <= 1'b1; - if ((exception_m == 1'b1) && (kill_m == 1'b0)) - data_bus_error_seen <= 1'b0; + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) + deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) + deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + end +end + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + data_bus_error_seen <= 1'b0; + else + begin + + if ((D_ERR_I == 1'b1) && (D_CYC_O == 1'b1)) + data_bus_error_seen <= 1'b1; + + if ((exception_m == 1'b1) && (kill_m == 1'b0)) + data_bus_error_seen <= 1'b0; end end + + + + + + + + + always @(*) begin if ( (icache_refill_request == 1'b1) @@ -1172,6 +4561,33 @@ begin else valid_a = !icache_refilling && !dcache_refilling; end + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -1185,54 +4601,94 @@ begin else begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + valid_f <= valid_a; + + + + else if (stall_f == 1'b0) valid_f <= 1'b0; + if (kill_d == 1'b1) valid_d <= 1'b0; else if (stall_f == 1'b0) valid_d <= valid_f & !kill_f; else if (stall_d == 1'b0) valid_d <= 1'b0; + if (stall_d == 1'b0) valid_x <= valid_d & !kill_d; else if (kill_x == 1'b1) valid_x <= 1'b0; else if (stall_x == 1'b0) valid_x <= 1'b0; + if (kill_m == 1'b1) valid_m <= 1'b0; else if (stall_x == 1'b0) valid_m <= valid_x & !kill_x; else if (stall_m == 1'b0) valid_m <= 1'b0; + if (stall_m == 1'b0) valid_w <= valid_m & !kill_m; else valid_w <= 1'b0; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin + + + + operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; x_result_sel_csr_x <= 1'b0; + + x_result_sel_mc_arith_x <= 1'b0; + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + x_result_sel_add_x <= 1'b0; m_result_sel_compare_x <= 1'b0; + + m_result_sel_shift_x <= 1'b0; + + w_result_sel_load_x <= 1'b0; + + w_result_sel_mul_x <= 1'b0; + + x_bypass_enable_x <= 1'b0; m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; write_idx_x <= { 5{1'b0}}; - csr_x <= { 4 {1'b0}}; + csr_x <= { 5{1'b0}}; load_x <= 1'b0; store_x <= 1'b0; size_x <= { 2{1'b0}}; @@ -1240,22 +4696,53 @@ begin adder_op_x <= 1'b0; adder_op_x_n <= 1'b0; logic_op_x <= 4'h0; + + direction_x <= 1'b0; + + + + + + + branch_x <= 1'b0; branch_predict_x <= 1'b0; branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + + + break_x <= 1'b0; + + scall_x <= 1'b0; eret_x <= 1'b0; + + + bret_x <= 1'b0; + + + + bus_error_x <= 1'b0; data_bus_error_exception_m <= 1'b0; + + csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; m_result_sel_compare_m <= 1'b0; + + m_result_sel_shift_m <= 1'b0; + + w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + m_bypass_enable_m <= 1'b0; branch_m <= 1'b0; branch_predict_m <= 1'b0; @@ -1266,31 +4753,86 @@ begin write_enable_m <= 1'b0; write_idx_m <= { 5{1'b0}}; condition_met_m <= 1'b0; + + dflush_m <= 1'b0; + + + + + debug_exception_m <= 1'b0; + non_debug_exception_m <= 1'b0; + + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; + + w_result_sel_mul_w <= 1'b0; + + write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; - exception_w <= 1'b0; + + + debug_exception_w <= 1'b0; + non_debug_exception_w <= 1'b0; + + + + + + memop_pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + + end else begin + + if (stall_x == 1'b0) begin + + + + operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; + + x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d; + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + x_result_sel_add_x <= x_result_sel_add_d; m_result_sel_compare_x <= m_result_sel_compare_d; + + m_result_sel_shift_x <= m_result_sel_shift_d; + + w_result_sel_load_x <= w_result_sel_load_d; + + w_result_sel_mul_x <= w_result_sel_mul_d; + + x_bypass_enable_x <= x_bypass_enable_d; m_bypass_enable_x <= m_bypass_enable_d; load_x <= load_d; @@ -1305,65 +4847,208 @@ begin adder_op_x <= adder_op_d; adder_op_x_n <= ~adder_op_d; logic_op_x <= logic_op_d; + + direction_x <= direction_d; + + + + + + condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + + + break_x <= break_d; + + scall_x <= scall_d; + + bus_error_x <= bus_error_d; + + eret_x <= eret_d; + + + bret_x <= bret_d; + + write_enable_x <= write_enable_d; end + + + if (stall_m == 1'b0) begin operand_m <= x_result; m_result_sel_compare_m <= m_result_sel_compare_x; + + m_result_sel_shift_m <= m_result_sel_shift_x; + + if (exception_x == 1'b1) begin w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + end else begin w_result_sel_load_m <= w_result_sel_load_x; + + w_result_sel_mul_m <= w_result_sel_mul_x; + + end m_bypass_enable_m <= m_bypass_enable_x; load_m <= load_x; store_m <= store_x; + + branch_m <= branch_x && !branch_taken_x; - if (exception_x == 1'b1) + + + + + + + + + + + + + + if (non_debug_exception_x == 1'b1) write_idx_m <= 5'd30; + else if (debug_exception_x == 1'b1) + write_idx_m <= 5'd31; else write_idx_m <= write_idx_x; + + + + + + + condition_met_m <= condition_met_x; - branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + if (exception_x == 1'b1) + if ((dc_re == 1'b1) + || ((debug_exception_x == 1'b1) + && (non_debug_exception_x == 1'b0))) + branch_target_m <= {deba, eid_x, {3{1'b0}}}; + else + branch_target_m <= {eba, eid_x, {3{1'b0}}}; + else + branch_target_m <= branch_target_x; + + + + + + + + + + + dflush_m <= dflush_x; + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + debug_exception_m <= debug_exception_x; + non_debug_exception_m <= non_debug_exception_x; + + end + + if (stall_m == 1'b0) begin if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) exception_m <= 1'b1; else exception_m <= 1'b0; + + data_bus_error_exception_m <= (data_bus_error_exception == 1'b1) + + + && (reset_exception == 1'b0) + + ; + + end + + + + operand_w <= exception_m == 1'b1 ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result; + + + + w_result_sel_load_w <= w_result_sel_load_m; + + w_result_sel_mul_w <= w_result_sel_mul_m; + + write_idx_w <= write_idx_m; + + + + + + + + write_enable_w <= write_enable_m; - exception_w <= exception_m; + + + debug_exception_w <= debug_exception_m; + non_debug_exception_w <= non_debug_exception_m; + + + + + + if ( (stall_m == 1'b0) && ( (load_q_m == 1'b1) || (store_q_m == 1'b1) ) ) memop_pc_w <= pc_m; + + end end + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -1391,13 +5076,521 @@ begin end end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + initial begin + + + + + + end + + + endmodule -module lm32_load_store_unit_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_full_debug +( + clk_i, + + + + rst_i, + stall_a, stall_x, stall_m, @@ -1416,17 +5609,39 @@ module lm32_load_store_unit_full ( store_q_m, sign_extend_x, size_x, + + dflush, + + + d_dat_i, d_ack_i, d_err_i, d_rty_i, + + + + dcache_refill_request, dcache_restart_request, dcache_stall_request, dcache_refilling, + + + + + + + + + + + + load_data_w, stall_wb_load, + d_dat_o, d_adr_o, d_cyc_o, @@ -1437,22 +5652,37 @@ module lm32_load_store_unit_full ( d_lock_o, d_bte_o ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; + + + + + + input clk_i; + input rst_i; + input stall_a; input stall_x; input stall_m; input kill_x; input kill_m; input exception_m; + input [ (32-1):0] store_operand_x; input [ (32-1):0] load_store_address_x; input [ (32-1):0] load_store_address_m; @@ -1465,11 +5695,42 @@ input load_q_m; input store_q_m; input sign_extend_x; input [ 1:0] size_x; + + + input dflush; + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + input [ (32-1):0] d_dat_i; input d_ack_i; input d_err_i; input d_rty_i; + + + + + + + output dcache_refill_request; wire dcache_refill_request; output dcache_restart_request; @@ -1478,10 +5739,15 @@ output dcache_stall_request; wire dcache_stall_request; output dcache_refilling; wire dcache_refilling; + + + + output [ (32-1):0] load_data_w; reg [ (32-1):0] load_data_w; output stall_wb_load; reg stall_wb_load; + output [ (32-1):0] d_dat_o; reg [ (32-1):0] d_dat_o; output [ (32-1):0] d_adr_o; @@ -1500,6 +5766,12 @@ output d_lock_o; reg d_lock_o; output [ (2-1):0] d_bte_o; wire [ (2-1):0] d_bte_o; + + + + + + reg [ 1:0] size_m; reg [ 1:0] size_w; reg sign_extend_m; @@ -1510,6 +5782,11 @@ reg [ (4-1):0] byte_enable_x; reg [ (4-1):0] byte_enable_m; wire [ (32-1):0] data_m; reg [ (32-1):0] data_w; + + + + + wire dcache_select_x; reg dcache_select_m; wire [ (32-1):0] dcache_data_m; @@ -1519,10 +5796,100 @@ wire [ (3-1):0] first_cycle_type; wire [ (3-1):0] next_cycle_type; wire last_word; wire [ (32-1):0] first_address; + + + + + + + + + + + + wire wb_select_x; + + + + + + + + + + reg wb_select_m; reg [ (32-1):0] wb_data_m; reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -1530,6 +5897,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -1542,13 +5910,26 @@ begin clogb2_v1 = i-1; end endfunction -lm32_dcache_full #( + + + + + + + + + + + + +lm32_dcache_full_debug #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), .base_address (base_address), .limit (limit) ) dcache ( + .clk_i (clk_i), .rst_i (rst_i), .stall_a (stall_a), @@ -1563,6 +5944,7 @@ lm32_dcache_full #( .refill_ready (dcache_refill_ready), .refill_data (wb_data_m), .dflush (dflush), + .stall_request (dcache_stall_request), .restart_request (dcache_restart_request), .refill_request (dcache_refill_request), @@ -1570,12 +5952,79 @@ lm32_dcache_full #( .refilling (dcache_refilling), .load_data (dcache_data_m) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign dcache_select_x = (load_store_address_x >= 32'h0) && (load_store_address_x <= 32'h7fffffff) + + + + + + + + ; + + + assign wb_select_x = 1'b1 + + && !dcache_select_x + + + + + + + + + + ; + + always @(*) begin case (size_x) @@ -1585,6 +6034,8 @@ begin default: store_data_x = { 32{1'bx}}; endcase end + + always @(*) begin casez ({size_x, load_store_address_x[1:0]}) @@ -1598,9 +6049,90 @@ begin default: byte_enable_x = 4'bxxxx; endcase end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_select_m == 1'b1 ? wb_data_m : dcache_data_m; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin casez ({size_w, load_store_address_w[1:0]}) @@ -1614,7 +6146,13 @@ begin default: load_data_w = { 32{1'bx}}; endcase end + + assign d_bte_o = 2'b00; + + + + generate case (bytes_per_line) 4: @@ -1640,6 +6178,14 @@ assign first_address = {dcache_refill_address[ 32-1:addr_offset_msb+1], {addr_of end endcase endgenerate + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -1655,49 +6201,90 @@ begin wb_data_m <= { 32{1'b0}}; wb_load_complete <= 1'b0; stall_wb_load <= 1'b0; + + dcache_refill_ready <= 1'b0; + + end else begin + + + dcache_refill_ready <= 1'b0; + + + if (d_cyc_o == 1'b1) begin + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) begin + + if ((dcache_refilling == 1'b1) && (!last_word)) begin + d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; end else + + begin + d_cyc_o <= 1'b0; d_stb_o <= 1'b0; d_lock_o <= 1'b0; end + + d_cti_o <= next_cycle_type; + dcache_refill_ready <= dcache_refilling; + + + wb_data_m <= d_dat_i; + wb_load_complete <= !d_we_o; end + if (d_err_i == 1'b1) $display ("Data bus error. Address: %x", d_adr_o); + end else begin + + if (dcache_refill_request == 1'b1) begin + d_adr_o <= first_address; d_cyc_o <= 1'b1; d_sel_o <= { 32/8{ 1'b1}}; d_stb_o <= 1'b1; d_we_o <= 1'b0; d_cti_o <= first_cycle_type; + end else + + if ( (store_q_m == 1'b1) && (stall_m == 1'b0) + + + + + + + + ) begin + d_dat_o <= store_data_m; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -1709,8 +6296,10 @@ begin else if ( (load_q_m == 1'b1) && (wb_select_m == 1'b1) && (wb_load_complete == 1'b0) + ) begin + stall_wb_load <= 1'b0; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -1720,14 +6309,21 @@ begin d_cti_o <= 3'b111; end end + if (stall_m == 1'b0) wb_load_complete <= 1'b0; + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) stall_wb_load <= 1'b1; + if ((kill_m == 1'b1) || (exception_m == 1'b1)) stall_wb_load <= 1'b0; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -1736,7 +6332,20 @@ begin size_m <= 2'b00; byte_enable_m <= 1'b0; store_data_m <= { 32{1'b0}}; + + dcache_select_m <= 1'b0; + + + + + + + + + + + wb_select_m <= 1'b0; end else @@ -1747,11 +6356,26 @@ begin size_m <= size_x; byte_enable_m <= byte_enable_x; store_data_m <= store_data_x; + + dcache_select_m <= dcache_select_x; + + + + + + + + + + + wb_select_m <= wb_select_x; end end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -1763,10 +6387,24 @@ begin else begin size_w <= size_m; + + + + + data_w <= data_m; + sign_extend_w <= sign_extend_m; end end + + + + + + + + always @(posedge clk_i) begin if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) @@ -1777,20 +6415,511 @@ begin $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end end + + + endmodule -module lm32_decoder_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_full_debug ( + instruction, + d_result_sel_0, d_result_sel_1, x_result_sel_csr, + + x_result_sel_mc_arith, + + + + + + + + x_result_sel_sext, + + x_result_sel_logic, + + + + x_result_sel_add, m_result_sel_compare, + + m_result_sel_shift, + + w_result_sel_load, + + w_result_sel_mul, + + x_bypass_enable, m_bypass_enable, read_enable_0, @@ -1807,41 +6936,108 @@ module lm32_decoder_full ( sign_extend, adder_op, logic_op, + + direction, + + + + + + + + + + + + + divide, modulus, + + branch, branch_reg, condition, bi_conditional, bi_unconditional, + + + break_opcode, + + scall, eret, + + + bret, + + + + + + csr_write_enable ); + + + + + input [ (32-1):0] instruction; + + + + + output [ 0:0] d_result_sel_0; reg [ 0:0] d_result_sel_0; output [ 1:0] d_result_sel_1; reg [ 1:0] d_result_sel_1; output x_result_sel_csr; reg x_result_sel_csr; + + output x_result_sel_mc_arith; reg x_result_sel_mc_arith; + + + + + + + + + output x_result_sel_sext; reg x_result_sel_sext; + + output x_result_sel_logic; reg x_result_sel_logic; + + + + + output x_result_sel_add; reg x_result_sel_add; output m_result_sel_compare; reg m_result_sel_compare; + + output m_result_sel_shift; reg m_result_sel_shift; + + output w_result_sel_load; reg w_result_sel_load; + + output w_result_sel_mul; reg w_result_sel_mul; + + output x_bypass_enable; wire x_bypass_enable; output m_bypass_enable; @@ -1874,12 +7070,32 @@ output adder_op; wire adder_op; output [ 3:0] logic_op; wire [ 3:0] logic_op; + + output direction; wire direction; + + + + + + + + + + + + + + + + output divide; wire divide; output modulus; wire modulus; + + output branch; wire branch; output branch_reg; @@ -1890,12 +7106,34 @@ output bi_conditional; wire bi_conditional; output bi_unconditional; wire bi_unconditional; + + +output break_opcode; +wire break_opcode; + + output scall; wire scall; output eret; wire eret; + + +output bret; +wire bret; + + + + + + + output csr_write_enable; wire csr_write_enable; + + + + + wire [ (32-1):0] extended_immediate; wire [ (32-1):0] high_immediate; wire [ (32-1):0] call_immediate; @@ -1903,6 +7141,7 @@ wire [ (32-1):0] branch_immediate; wire sign_extend_immediate; wire select_high_immediate; wire select_call_immediate; + wire op_add; wire op_and; wire op_andhi; @@ -1922,38 +7161,110 @@ wire op_cmpge; wire op_cmpgeu; wire op_cmpgu; wire op_cmpne; + + wire op_divu; + + wire op_lb; wire op_lbu; wire op_lh; wire op_lhu; wire op_lw; + + wire op_modu; + + + + wire op_mul; + + wire op_nor; wire op_or; wire op_orhi; wire op_raise; wire op_rcsr; wire op_sb; + + wire op_sextb; wire op_sexth; + + wire op_sh; + + wire op_sl; + + wire op_sr; wire op_sru; wire op_sub; wire op_sw; + + + + wire op_wcsr; wire op_xnor; wire op_xor; + wire arith; wire logical; wire cmp; wire bra; wire call; + + wire shift; + + + + + + + + wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -1961,6 +7272,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -1973,6 +7285,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + assign op_add = instruction[ 30:26] == 5'b01101; assign op_and = instruction[ 30:26] == 5'b01000; assign op_andhi = instruction[ 31:26] == 6'b011000; @@ -1992,31 +7313,57 @@ assign op_cmpge = instruction[ 30:26] == 5'b11011; assign op_cmpgeu = instruction[ 30:26] == 5'b11100; assign op_cmpgu = instruction[ 30:26] == 5'b11101; assign op_cmpne = instruction[ 30:26] == 5'b11111; + + assign op_divu = instruction[ 31:26] == 6'b100011; + + assign op_lb = instruction[ 31:26] == 6'b000100; assign op_lbu = instruction[ 31:26] == 6'b010000; assign op_lh = instruction[ 31:26] == 6'b000111; assign op_lhu = instruction[ 31:26] == 6'b001011; assign op_lw = instruction[ 31:26] == 6'b001010; + + assign op_modu = instruction[ 31:26] == 6'b110001; + + + + assign op_mul = instruction[ 30:26] == 5'b00010; + + assign op_nor = instruction[ 30:26] == 5'b00001; assign op_or = instruction[ 30:26] == 5'b01110; assign op_orhi = instruction[ 31:26] == 6'b011110; assign op_raise = instruction[ 31:26] == 6'b101011; assign op_rcsr = instruction[ 31:26] == 6'b100100; assign op_sb = instruction[ 31:26] == 6'b001100; + + assign op_sextb = instruction[ 31:26] == 6'b101100; assign op_sexth = instruction[ 31:26] == 6'b110111; + + assign op_sh = instruction[ 31:26] == 6'b000011; + + assign op_sl = instruction[ 30:26] == 5'b01111; + + assign op_sr = instruction[ 30:26] == 5'b00101; assign op_sru = instruction[ 30:26] == 5'b00000; assign op_sub = instruction[ 31:26] == 6'b110010; assign op_sw = instruction[ 31:26] == 6'b010110; + + + + assign op_wcsr = instruction[ 31:26] == 6'b110100; assign op_xnor = instruction[ 30:26] == 5'b01001; assign op_xor = instruction[ 30:26] == 5'b00110; + + assign arith = op_add | op_sub; assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; @@ -2024,14 +7371,42 @@ assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; assign bi_unconditional = op_bi; assign bra = op_b | bi_unconditional | bi_conditional; assign call = op_call | op_calli; + + assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + assign sext = op_sextb | op_sexth; + + + + + + + + assign divide = op_divu; assign modulus = op_modu; + + assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; assign store = op_sb | op_sh | op_sw; + + always @(*) begin + if (call) d_result_sel_0 = 1'b1; else @@ -2042,73 +7417,612 @@ begin d_result_sel_1 = 2'b10; else d_result_sel_1 = 2'b01; + x_result_sel_csr = 1'b0; + + x_result_sel_mc_arith = 1'b0; + + + + + + + + x_result_sel_sext = 1'b0; + + x_result_sel_logic = 1'b0; + + + + x_result_sel_add = 1'b0; if (op_rcsr) x_result_sel_csr = 1'b1; + + + + + + + + + else if (divide | modulus) x_result_sel_mc_arith = 1'b1; + + + + + + + + + + + + + + + + else if (sext) x_result_sel_sext = 1'b1; + + else if (logical) x_result_sel_logic = 1'b1; + + + + + else x_result_sel_add = 1'b1; + + + m_result_sel_compare = cmp; + + m_result_sel_shift = shift; + + + + w_result_sel_load = load; + + w_result_sel_mul = op_mul; + + end + + assign x_bypass_enable = arith | logical + + + + + + + + + + + | divide | modulus + + + + + + + + | sext + + + + + + | op_rcsr ; + assign m_bypass_enable = x_bypass_enable + + | shift + + | cmp ; + assign read_enable_0 = ~(op_bi | op_calli); assign read_idx_0 = instruction[25:21]; + assign read_enable_1 = ~(op_bi | op_calli | load); assign read_idx_1 = instruction[20:16]; + assign write_enable = ~(bra | op_raise | store | op_wcsr); assign write_idx = call ? 5'd29 : instruction[31] == 1'b0 ? instruction[20:16] : instruction[15:11]; + + assign size = instruction[27:26]; + assign sign_extend = instruction[28]; + assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + assign logic_op = instruction[29:26]; + + + assign direction = instruction[29]; + + + assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + + +assign break_opcode = op_raise & ~instruction[2]; + + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + + +assign bret = op_b & (instruction[25:21] == 5'd31); + + + + + + + + assign csr_write_enable = op_wcsr; + + + assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); assign select_high_immediate = op_andhi | op_orhi; assign select_call_immediate = instruction[31]; + assign high_immediate = {instruction[15:0], 16'h0000}; assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + assign immediate = select_high_immediate == 1'b1 ? high_immediate : extended_immediate; + assign branch_offset = select_call_immediate == 1'b1 ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); + endmodule -module lm32_icache_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_icache_full_debug ( + clk_i, rst_i, stall_a, @@ -2119,8 +8033,13 @@ module lm32_icache_full ( refill_ready, refill_data, iflush, + + + + valid_d, branch_predict_taken_d, + stall_request, restart_request, refill_request, @@ -2128,11 +8047,17 @@ module lm32_icache_full ( refilling, inst ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + localparam addr_offset_width = clogb2(bytes_per_line)-1-2; localparam addr_set_width = clogb2(sets)-1; localparam addr_offset_lsb = 2; @@ -2142,18 +8067,37 @@ localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); localparam addr_tag_lsb = (addr_set_msb+1); localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; + input valid_d; input branch_predict_taken_d; + input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; input read_enable_f; + input refill_ready; input [ (32-1):0] refill_data; + input iflush; + + + + + + + + + output stall_request; wire stall_request; output restart_request; @@ -2166,6 +8110,11 @@ output refilling; reg refilling; output [ (32-1):0] inst; wire [ (32-1):0] inst; + + + + + wire enable; wire [0:associativity-1] way_mem_we; wire [ (32-1):0] way_data[0:associativity-1]; @@ -2173,20 +8122,59 @@ wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; wire [0:associativity-1] way_valid; wire [0:associativity-1] way_match; wire miss; + wire [ (addr_set_width-1):0] tmem_read_address; wire [ (addr_set_width-1):0] tmem_write_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; wire [ ((addr_tag_width+1)-1):0] tmem_write_data; + reg [ 3:0] state; wire flushing; wire check; wire refill; + reg [associativity-1:0] refill_way_select; reg [ addr_offset_msb:addr_offset_lsb] refill_offset; wire last_refill; reg [ (addr_set_width-1):0] flush_set; + genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -2194,6 +8182,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -2206,16 +8195,28 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : memories + lm32_ram #( + .data_width (32), .address_width ( (addr_offset_width+addr_set_width)) + ) way_0_data_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -2225,15 +8226,20 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i]), .write_data (refill_data), + .read_data (way_data[i]) ); + lm32_ram #( + .data_width ( (addr_tag_width+1)), .address_width ( addr_set_width) + ) way_0_tag_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -2243,16 +8249,26 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i] | flushing), .write_data (tmem_write_data), + .read_data ({way_tag[i], way_valid[i]}) ); + end endgenerate + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : match assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); end endgenerate + + generate if (associativity == 1) begin : inst_1 @@ -2263,24 +8279,35 @@ assign inst = way_match[0] ? way_data[0] : 32'b0; assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); end endgenerate + + generate if (bytes_per_line > 4) assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; else assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; endgenerate + assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; assign tmem_write_address = flushing ? flush_set : refill_address[ addr_set_msb:addr_set_lsb]; + + generate if (bytes_per_line > 4) assign last_refill = refill_offset == {addr_offset_width{1'b1}}; else assign last_refill = 1'b1; endgenerate + + assign enable = (stall_a == 1'b0); + + generate if (associativity == 1) begin : we_1 @@ -2292,14 +8319,25 @@ assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1 assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); end endgenerate + + assign tmem_write_data[ 0] = last_refill & !flushing; assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + assign flushing = |state[1:0]; assign check = state[2]; assign refill = state[3]; + assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); assign stall_request = (check == 1'b0); assign refill_request = (refill == 1'b1); + + + + + + generate if (associativity >= 2) begin : way_select @@ -2315,6 +8353,8 @@ begin end end endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2322,6 +8362,8 @@ begin else refilling <= refill; end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2334,18 +8376,31 @@ begin else begin case (state) + + 4'b0001: begin if (flush_set == { addr_set_width{1'b0}}) state <= 4'b0100; flush_set <= flush_set - 1'b1; end + + 4'b0010: begin if (flush_set == { addr_set_width{1'b0}}) + + + + + + state <= 4'b0100; + flush_set <= flush_set - 1'b1; end + + 4'b0100: begin if (stall_a == 1'b0) @@ -2361,6 +8416,8 @@ begin state <= 4'b1000; end end + + 4'b1000: begin if (refill_ready == 1'b1) @@ -2372,12 +8429,15 @@ begin end end end + endcase end end + generate if (bytes_per_line > 4) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2385,6 +8445,8 @@ begin else begin case (state) + + 4'b0100: begin if (iflush == 1'b1) @@ -2392,18 +8454,426 @@ begin else if (miss == 1'b1) refill_offset <= {addr_offset_width{1'b0}}; end + + 4'b1000: begin if (refill_ready == 1'b1) refill_offset <= refill_offset + 1'b1; end + endcase end end end endgenerate + endmodule -module lm32_dcache_full ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_dcache_full_debug ( + clk_i, rst_i, stall_a, @@ -2418,6 +8888,7 @@ module lm32_dcache_full ( refill_ready, refill_data, dflush, + stall_request, restart_request, refill_request, @@ -2425,11 +8896,17 @@ module lm32_dcache_full ( refilling, load_data ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + localparam addr_offset_width = clogb2(bytes_per_line)-1-2; localparam addr_set_width = clogb2(sets)-1; localparam addr_offset_lsb = 2; @@ -2439,20 +8916,34 @@ localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); localparam addr_tag_lsb = (addr_set_msb+1); localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + input clk_i; input rst_i; + input stall_a; input stall_x; input stall_m; + input [ (32-1):0] address_x; input [ (32-1):0] address_m; input load_q_m; input store_q_m; input [ (32-1):0] store_data; input [ (4-1):0] store_byte_select; + input refill_ready; input [ (32-1):0] refill_data; + input dflush; + + + + + output stall_request; wire stall_request; output restart_request; @@ -2465,6 +8956,11 @@ output refilling; reg refilling; output [ (32-1):0] load_data; wire [ (32-1):0] load_data; + + + + + wire read_port_enable; wire write_port_enable; wire [0:associativity-1] way_tmem_we; @@ -2474,22 +8970,61 @@ wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; wire [0:associativity-1] way_valid; wire [0:associativity-1] way_match; wire miss; + wire [ (addr_set_width-1):0] tmem_read_address; wire [ (addr_set_width-1):0] tmem_write_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; wire [ ((addr_tag_width+1)-1):0] tmem_write_data; reg [ (32-1):0] dmem_write_data; + reg [ 2:0] state; wire flushing; wire check; wire refill; + wire valid_store; reg [associativity-1:0] refill_way_select; reg [ addr_offset_msb:addr_offset_lsb] refill_offset; wire last_refill; reg [ (addr_set_width-1):0] flush_set; + genvar i, j; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -2497,6 +9032,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -2509,17 +9045,29 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : memories + if ( (addr_offset_width+addr_set_width) < 11) begin : data_memories lm32_ram #( + .data_width (32), .address_width ( (addr_offset_width+addr_set_width)) + ) way_0_data_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -2529,6 +9077,7 @@ endfunction .enable_write (write_port_enable), .write_enable (way_dmem_we[i]), .write_data (dmem_write_data), + .read_data (way_data[i]) ); end @@ -2538,10 +9087,13 @@ endfunction begin : byte_memories lm32_ram #( + .data_width (8), .address_width ( (addr_offset_width+addr_set_width)) + ) way_0_data_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -2551,16 +9103,22 @@ endfunction .enable_write (write_port_enable), .write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)), .write_data (dmem_write_data[(j+1)*8-1:j*8]), + .read_data (way_data[i][(j+1)*8-1:j*8]) ); end end + + lm32_ram #( + .data_width ( (addr_tag_width+1)), .address_width ( addr_set_width) + ) way_0_tag_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -2570,16 +9128,26 @@ endfunction .enable_write ( 1'b1), .write_enable (way_tmem_we[i]), .write_data (tmem_write_data), + .read_data ({way_tag[i], way_valid[i]}) ); end + endgenerate + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : match assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[ addr_tag_msb:addr_tag_lsb], 1'b1}); end endgenerate + + generate if (associativity == 1) begin : data_1 @@ -2590,9 +9158,11 @@ assign load_data = way_data[0]; assign load_data = way_match[0] ? way_data[0] : way_data[1]; end endgenerate + generate if ( (addr_offset_width+addr_set_width) < 11) begin + always @(*) begin if (refill == 1'b1) @@ -2608,6 +9178,7 @@ end end else begin + always @(*) begin if (refill == 1'b1) @@ -2617,6 +9188,8 @@ begin end end endgenerate + + generate if (bytes_per_line > 4) assign dmem_write_address = (refill == 1'b1) @@ -2628,19 +9201,28 @@ assign dmem_write_address = (refill == 1'b1) : address_m[ addr_set_msb:addr_offset_lsb]; endgenerate assign dmem_read_address = address_x[ addr_set_msb:addr_offset_lsb]; + assign tmem_write_address = (flushing == 1'b1) ? flush_set : refill_address[ addr_set_msb:addr_set_lsb]; assign tmem_read_address = address_x[ addr_set_msb:addr_set_lsb]; + + generate if (bytes_per_line > 4) assign last_refill = refill_offset == {addr_offset_width{1'b1}}; else assign last_refill = 1'b1; endgenerate + + assign read_port_enable = (stall_x == 1'b0); assign write_port_enable = (refill_ready == 1'b1) || !stall_m; + + assign valid_store = (store_q_m == 1'b1) && (check == 1'b1); + + generate if (associativity == 1) begin : we_1 @@ -2655,13 +9237,24 @@ assign way_tmem_we[0] = ((refill_ready == 1'b1) && (refill_way_select[0] == 1' assign way_tmem_we[1] = ((refill_ready == 1'b1) && (refill_way_select[1] == 1'b1)) || (flushing == 1'b1); end endgenerate + + assign tmem_write_data[ 0] = ((last_refill == 1'b1) || (valid_store == 1'b1)) && (flushing == 1'b0); assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + assign flushing = state[0]; assign check = state[1]; assign refill = state[2]; + assign miss = (~(|way_match)) && (load_q_m == 1'b1) && (stall_m == 1'b0); assign stall_request = (check == 1'b0); + + + + + + generate if (associativity >= 2) begin : way_select @@ -2677,6 +9270,8 @@ begin end end endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2684,6 +9279,8 @@ begin else refilling <= refill; end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2697,12 +9294,16 @@ begin else begin case (state) + + 3'b001: begin if (flush_set == { addr_set_width{1'b0}}) state <= 3'b010; flush_set <= flush_set - 1'b1; end + + 3'b010: begin if (stall_a == 1'b0) @@ -2716,6 +9317,8 @@ begin else if (dflush == 1'b1) state <= 3'b001; end + + 3'b100: begin refill_request <= 1'b0; @@ -2728,12 +9331,15 @@ begin end end end + endcase end end + generate if (bytes_per_line > 4) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -2741,895 +9347,4388 @@ begin else begin case (state) + + 3'b010: begin if (miss == 1'b1) refill_offset <= {addr_offset_width{1'b0}}; end + + 3'b100: begin if (refill_ready == 1'b1) refill_offset <= refill_offset + 1'b1; end + endcase end end end endgenerate + endmodule -module lm32_instruction_unit_full ( - clk_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_debug_full_debug ( + + clk_i, rst_i, - stall_a, - stall_f, - stall_d, + pc_x, + load_x, + store_x, + load_store_address_x, + csr_write_enable_x, + csr_write_data, + csr_x, + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + + + + + eret_q_x, + bret_q_x, stall_x, - stall_m, - valid_f, - valid_d, - kill_f, - branch_predict_taken_d, - branch_predict_address_d, - branch_taken_x, - branch_target_x, - exception_m, - branch_taken_m, - branch_mispredict_taken_m, - branch_target_m, - iflush, - dcache_restart_request, + exception_x, + q_x, + + dcache_refill_request, - dcache_refilling, - i_dat_i, - i_ack_i, - i_err_i, - i_rty_i, - pc_f, - pc_d, - pc_x, - pc_m, - pc_w, - icache_stall_request, - icache_restart_request, - icache_refill_request, - icache_refilling, - i_dat_o, - i_adr_o, - i_cyc_o, - i_sel_o, - i_stb_o, - i_we_o, - i_cti_o, - i_lock_o, - i_bte_o, - bus_error_d, - instruction_f, - instruction_d + + + + + + + + dc_ss, + + + dc_re, + bp_match, + wp_match ); -parameter eba_reset = 32'h00000000; -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam eba_reset_minus_4 = eba_reset - 4; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_f; -input stall_d; -input stall_x; -input stall_m; -input valid_f; -input valid_d; -input kill_f; -input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -input branch_taken_x; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; -input exception_m; -input branch_taken_m; -input branch_mispredict_taken_m; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; -input iflush; -input dcache_restart_request; -input dcache_refill_request; -input dcache_refilling; -input [ (32-1):0] i_dat_i; -input i_ack_i; -input i_err_i; -input i_rty_i; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -output icache_stall_request; -wire icache_stall_request; -output icache_restart_request; -wire icache_restart_request; -output icache_refill_request; -wire icache_refill_request; -output icache_refilling; -wire icache_refilling; -output [ (32-1):0] i_dat_o; -wire [ (32-1):0] i_dat_o; -output [ (32-1):0] i_adr_o; -reg [ (32-1):0] i_adr_o; -output i_cyc_o; -reg i_cyc_o; -output [ (4-1):0] i_sel_o; -wire [ (4-1):0] i_sel_o; -output i_stb_o; -reg i_stb_o; -output i_we_o; -wire i_we_o; -output [ (3-1):0] i_cti_o; -reg [ (3-1):0] i_cti_o; -output i_lock_o; -reg i_lock_o; -output [ (2-1):0] i_bte_o; -wire [ (2-1):0] i_bte_o; -output bus_error_d; -reg bus_error_d; -output [ (32-1):0] instruction_f; -wire [ (32-1):0] instruction_f; -output [ (32-1):0] instruction_d; -reg [ (32-1):0] instruction_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; -wire icache_read_enable_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; -reg icache_refill_ready; -reg [ (32-1):0] icache_refill_data; -wire [ (32-1):0] icache_data_f; -wire [ (3-1):0] first_cycle_type; -wire [ (3-1):0] next_cycle_type; -wire last_word; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; -reg bus_error_f; -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; -begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction -lm32_icache_full #( - .associativity (associativity), - .sets (sets), - .bytes_per_line (bytes_per_line), - .base_address (base_address), - .limit (limit) - ) icache ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .branch_predict_taken_d (branch_predict_taken_d), - .valid_d (valid_d), - .address_a (pc_a), - .address_f (pc_f), - .read_enable_f (icache_read_enable_f), - .refill_ready (icache_refill_ready), - .refill_data (icache_refill_data), - .iflush (iflush), - .stall_request (icache_stall_request), - .restart_request (icache_restart_request), - .refill_request (icache_refill_request), - .refill_address (icache_refill_address), - .refilling (icache_refilling), - .inst (icache_data_f) - ); -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - && (dcache_restart_request == 1'b0) - ; -always @(*) + + + + + +parameter breakpoints = 0; +parameter watchpoints = 0; + + + + + +input clk_i; +input rst_i; + +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +input load_x; +input store_x; +input [ (32-1):0] load_store_address_x; +input csr_write_enable_x; +input [ (32-1):0] csr_write_data; +input [ (5-1):0] csr_x; + + +input jtag_csr_write_enable; +input [ (32-1):0] jtag_csr_write_data; +input [ (5-1):0] jtag_csr; + + + + +input eret_q_x; +input bret_q_x; +input stall_x; +input exception_x; +input q_x; + + +input dcache_refill_request; + + + + + + + + + + + +output dc_ss; +reg dc_ss; + + +output dc_re; +reg dc_re; +output bp_match; +wire bp_match; +output wp_match; +wire wp_match; + + + + + +genvar i; + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; +reg bp_e[0:breakpoints-1]; +wire [0:breakpoints-1]bp_match_n; + +reg [ 1:0] wpc_c[0:watchpoints-1]; +reg [ (32-1):0] wp[0:watchpoints-1]; +wire [0:watchpoints-1]wp_match_n; + +wire debug_csr_write_enable; +wire [ (32-1):0] debug_csr_write_data; +wire [ (5-1):0] debug_csr; + + + + +reg [ 2:0] state; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - if (dcache_restart_request == 1'b1) - pc_a = restart_address; - else - if (branch_taken_m == 1'b1) - if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) - pc_a = pc_x; - else - pc_a = branch_target_m; - else if (branch_taken_x == 1'b1) - pc_a = branch_target_x; - else - if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) - pc_a = branch_predict_address_d; - else - if (icache_restart_request == 1'b1) - pc_a = restart_address; - else - pc_a = pc_f + 1'b1; + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -assign instruction_f = icache_data_f; -assign i_dat_o = 32'd0; -assign i_we_o = 1'b0; -assign i_sel_o = 4'b1111; -assign i_bte_o = 2'b00; +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + generate - case (bytes_per_line) - 4: - begin -assign first_cycle_type = 3'b111; -assign next_cycle_type = 3'b111; -assign last_word = 1'b1; -assign first_address = icache_refill_address; + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_comb +assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); end - 8: +endgenerate +generate + + + if (breakpoints > 0) +assign bp_match = (|bp_match_n) || (state == 3'b011); + else +assign bp_match = state == 3'b011; + + + + + + + +endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_comb +assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); + end +endgenerate +generate + if (watchpoints > 0) +assign wp_match = |wp_match_n; + else +assign wp_match = 1'b0; +endgenerate + + + + +assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); +assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; +assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; + + + + + + + + + + + + +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = 3'b111; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + bp_e[i] <= 1'b0; end - 16: + else begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) + begin + bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + bp_e[i] <= debug_csr_write_data[0]; + end + end +end end - endcase endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_seq always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + wp[i] <= { 32{1'bx}}; + wpc_c[i] <= 2'b00; end else begin - if (stall_f == 1'b0) - pc_f <= pc_a; - if (stall_d == 1'b0) - pc_d <= pc_f; - if (stall_x == 1'b0) - pc_x <= pc_d; - if (stall_m == 1'b0) - pc_m <= pc_x; - pc_w <= pc_m; - end + if (debug_csr_write_enable == 1'b1) + begin + if (debug_csr == 5'h8) + wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; + if (debug_csr == 5'h18 + i) + wp[i] <= debug_csr_write_data; + end + end end + end +endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + dc_re <= 1'b0; else begin - if (dcache_refill_request == 1'b1) - restart_address <= pc_w; - else if ((icache_refill_request == 1'b1) && (!dcache_refilling) && (!dcache_restart_request)) - restart_address <= icache_refill_address; + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + dc_re <= debug_csr_write_data[1]; end -end +end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - bus_error_f <= 1'b0; + state <= 3'b000; + dc_ss <= 1'b0; end else - begin - icache_refill_ready <= 1'b0; - if (i_cyc_o == 1'b1) + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - begin - if (last_word == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end - end - if (i_err_i == 1'b1) - begin - bus_error_f <= 1'b1; - $display ("Instruction bus error. Address: %x", i_adr_o); - end + dc_ss <= debug_csr_write_data[0]; + if (debug_csr_write_data[0] == 1'b0) + state <= 3'b000; + else + state <= 3'b001; end - else + case (state) + 3'b001: begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + + if ( ( (eret_q_x == 1'b1) + || (bret_q_x == 1'b1) + ) + && (stall_x == 1'b0) + ) + state <= 3'b010; + end + 3'b010: + begin + + if ((q_x == 1'b1) && (stall_x == 1'b0)) + state <= 3'b011; + end + 3'b011: + begin + + + + if (dcache_refill_request == 1'b1) + state <= 3'b010; + else + + + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) begin - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; - bus_error_f <= 1'b0; + dc_ss <= 1'b0; + state <= 3'b100; end - if (branch_taken_x == 1'b1) - bus_error_f <= 1'b0; - if (branch_taken_m == 1'b1) - bus_error_f <= 1'b0; end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - bus_error_d <= 1'b0; - end - else - begin - if (stall_d == 1'b0) + 3'b100: begin - instruction_d <= instruction_f; - bus_error_d <= bus_error_f; + + + + if (dcache_refill_request == 1'b1) + state <= 3'b010; + else + + + state <= 3'b000; end + endcase end -end +end + + + endmodule -module lm32_interrupt_full ( - clk_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_full_debug ( + + clk_i, rst_i, - interrupt, + + stall_a, + stall_f, + stall_d, stall_x, - exception, - eret_q_x, - csr, - csr_write_data, - csr_write_enable, - interrupt_exception, - csr_read_data + stall_m, + valid_f, + valid_d, + kill_f, + branch_predict_taken_d, + branch_predict_address_d, + + + branch_taken_x, + branch_target_x, + + + exception_m, + branch_taken_m, + branch_mispredict_taken_m, + branch_target_m, + + + iflush, + + + + + dcache_restart_request, + dcache_refill_request, + dcache_refilling, + + + + + + i_dat_i, + i_ack_i, + i_err_i, + i_rty_i, + + + + + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + + + + + pc_f, + pc_d, + pc_x, + pc_m, + pc_w, + + + icache_stall_request, + icache_restart_request, + icache_refill_request, + icache_refilling, + + + + + + i_dat_o, + i_adr_o, + i_cyc_o, + i_sel_o, + i_stb_o, + i_we_o, + i_cti_o, + i_lock_o, + i_bte_o, + + + + + + + + + + + jtag_read_data, + jtag_access_complete, + + + + + bus_error_d, + + + + + instruction_f, + + + instruction_d ); -parameter interrupts = 32; -input clk_i; -input rst_i; -input [interrupts-1:0] interrupt; -input stall_x; -input exception; -input eret_q_x; -input [ (4 -1):0] csr; -input [ (32-1):0] csr_write_data; -input csr_write_enable; -output interrupt_exception; -wire interrupt_exception; -output [ (32-1):0] csr_read_data; -reg [ (32-1):0] csr_read_data; -wire [interrupts-1:0] asserted; -wire [interrupts-1:0] interrupt_n_exception; -reg ie; -reg eie; -reg [interrupts-1:0] ip; -reg [interrupts-1:0] im; -assign interrupt_n_exception = ip & im; -assign interrupt_exception = (|interrupt_n_exception) & ie; -assign asserted = ip | interrupt; -generate - if (interrupts > 1) - begin -always @(*) + + + + + +parameter eba_reset = 32'h00000000; +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam eba_reset_minus_4 = eba_reset - 4; +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + +input clk_i; +input rst_i; + +input stall_a; +input stall_f; +input stall_d; +input stall_x; +input stall_m; +input valid_f; +input valid_d; +input kill_f; + +input branch_predict_taken_d; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; + + + +input branch_taken_x; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; + + +input exception_m; +input branch_taken_m; +input branch_mispredict_taken_m; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; + + + +input iflush; + + + + +input dcache_restart_request; +input dcache_refill_request; +input dcache_refilling; + + + + + + +input [ (32-1):0] i_dat_i; +input i_ack_i; +input i_err_i; +input i_rty_i; + + + + + +input jtag_read_enable; +input jtag_write_enable; +input [ 7:0] jtag_write_data; +input [ (32-1):0] jtag_address; + + + + + + + +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + +output icache_stall_request; +wire icache_stall_request; +output icache_restart_request; +wire icache_restart_request; +output icache_refill_request; +wire icache_refill_request; +output icache_refilling; +wire icache_refilling; + + + + + +output [ (32-1):0] i_dat_o; + + +reg [ (32-1):0] i_dat_o; + + + + +output [ (32-1):0] i_adr_o; +reg [ (32-1):0] i_adr_o; +output i_cyc_o; +reg i_cyc_o; +output [ (4-1):0] i_sel_o; + + +reg [ (4-1):0] i_sel_o; + + + + +output i_stb_o; +reg i_stb_o; +output i_we_o; + + +reg i_we_o; + + + + +output [ (3-1):0] i_cti_o; +reg [ (3-1):0] i_cti_o; +output i_lock_o; +reg i_lock_o; +output [ (2-1):0] i_bte_o; +wire [ (2-1):0] i_bte_o; + + + + + +output [ 7:0] jtag_read_data; +reg [ 7:0] jtag_read_data; +output jtag_access_complete; +wire jtag_access_complete; + + + + + +output bus_error_d; +reg bus_error_d; + + + + +output [ (32-1):0] instruction_f; +wire [ (32-1):0] instruction_f; + + +output [ (32-1):0] instruction_d; +reg [ (32-1):0] instruction_d; + + + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + + + + + +wire icache_read_enable_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; +reg icache_refill_ready; +reg [ (32-1):0] icache_refill_data; +wire [ (32-1):0] icache_data_f; +wire [ (3-1):0] first_cycle_type; +wire [ (3-1):0] next_cycle_type; +wire last_word; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + + + + + + + + + + + + + + + + + + + + +reg bus_error_f; + + + + + +reg jtag_access; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - case (csr) - 4 'h0: csr_read_data = {{ 32-3{1'b0}}, - 1'b0, - eie, - ie - }; - 4 'h2: csr_read_data = ip; - 4 'h1: csr_read_data = im; - default: csr_read_data = { 32{1'bx}}; - endcase + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end - end - else - begin -always @(*) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - case (csr) - 4 'h0: csr_read_data = {{ 32-3{1'b0}}, - 1'b0, - eie, - ie - }; - 4 'h2: csr_read_data = ip; - default: csr_read_data = { 32{1'bx}}; - endcase + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end - end -endgenerate - reg [ 10:0] eie_delay = 0; -generate - if (interrupts > 1) - begin -always @(posedge clk_i ) - begin - if (rst_i == 1'b1) - begin - ie <= 1'b0; - eie <= 1'b0; - im <= {interrupts{1'b0}}; - ip <= {interrupts{1'b0}}; - eie_delay <= 0; - end - else - begin - ip <= asserted; - if (exception == 1'b1) - begin - eie <= ie; - ie <= 1'b0; - end - else if (stall_x == 1'b0) - begin - if(eie_delay[0]) - ie <= eie; - eie_delay <= {1'b0, eie_delay[ 10:1]}; - if (eret_q_x == 1'b1) begin - eie_delay[ 10] <= 1'b1; - eie_delay[ 10-1:0] <= 0; - end - else if (csr_write_enable == 1'b1) - begin - if (csr == 4 'h0) - begin - ie <= csr_write_data[0]; - eie <= csr_write_data[1]; - end - if (csr == 4 'h1) - im <= csr_write_data[interrupts-1:0]; - if (csr == 4 'h2) - ip <= asserted & ~csr_write_data[interrupts-1:0]; - end - end - end +endfunction + + + + + + + + + + + + +lm32_icache_full_debug #( + .associativity (associativity), + .sets (sets), + .bytes_per_line (bytes_per_line), + .base_address (base_address), + .limit (limit) + ) icache ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_a (stall_a), + .stall_f (stall_f), + .branch_predict_taken_d (branch_predict_taken_d), + .valid_d (valid_d), + .address_a (pc_a), + .address_f (pc_f), + .read_enable_f (icache_read_enable_f), + .refill_ready (icache_refill_ready), + .refill_data (icache_refill_data), + .iflush (iflush), + + .stall_request (icache_stall_request), + .restart_request (icache_restart_request), + .refill_request (icache_refill_request), + .refill_address (icache_refill_address), + .refilling (icache_refilling), + .inst (icache_data_f) + ); + + + + + + + + + + + assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + + && (dcache_restart_request == 1'b0) + + + + + + + ; + + + + +always @(*) +begin + + + + if (dcache_restart_request == 1'b1) + pc_a = restart_address; + else + + + if (branch_taken_m == 1'b1) + if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) + pc_a = pc_x; + else + pc_a = branch_target_m; + + + else if (branch_taken_x == 1'b1) + pc_a = branch_target_x; + + + else + if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) + pc_a = branch_predict_address_d; + else + + + if (icache_restart_request == 1'b1) + pc_a = restart_address; + else + + + pc_a = pc_f + 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_f = icache_data_f; + + + + + + + + + + + + + + + + + + + +assign i_bte_o = 2'b00; + + + + + + +generate + case (bytes_per_line) + 4: + begin +assign first_cycle_type = 3'b111; +assign next_cycle_type = 3'b111; +assign last_word = 1'b1; +assign first_address = icache_refill_address; end -else + 8: begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = 3'b111; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + 16: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + endcase +endgenerate + + + + + + + + always @(posedge clk_i ) - begin +begin if (rst_i == 1'b1) begin - ie <= 1'b0; - eie <= 1'b0; - ip <= {interrupts{1'b0}}; - eie_delay <= 0; + pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; end else begin - ip <= asserted; - if (exception == 1'b1) - begin - eie <= ie; - ie <= 1'b0; - end - else if (stall_x == 1'b0) - begin - if(eie_delay[0]) - ie <= eie; - eie_delay <= {1'b0, eie_delay[ 10:1]}; - if (eret_q_x == 1'b1) begin - eie_delay[ 10] <= 1'b1; - eie_delay[ 10-1:0] <= 0; - end - else if (csr_write_enable == 1'b1) - begin - if (csr == 4 'h0) - begin - ie <= csr_write_data[0]; - eie <= csr_write_data[1]; - end - if (csr == 4 'h2) - ip <= asserted & ~csr_write_data[interrupts-1:0]; - end - end + if (stall_f == 1'b0) + pc_f <= pc_a; + if (stall_d == 1'b0) + pc_d <= pc_f; + if (stall_x == 1'b0) + pc_x <= pc_d; + if (stall_m == 1'b0) + pc_m <= pc_x; + pc_w <= pc_m; end end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + else + begin + + + + + + if (dcache_refill_request == 1'b1) + restart_address <= pc_w; + else if ((icache_refill_request == 1'b1) && (!dcache_refilling) && (!dcache_restart_request)) + restart_address <= icache_refill_address; + + + + + + + + + + + + end -endgenerate +end + + + + + + + + + + + + + + + + + + + + +assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); +always @(*) +begin + case (jtag_address[1:0]) + 2'b00: jtag_read_data = i_dat_i[ 31:24]; + 2'b01: jtag_read_data = i_dat_i[ 23:16]; + 2'b10: jtag_read_data = i_dat_i[ 15:8]; + 2'b11: jtag_read_data = i_dat_i[ 7:0]; + endcase +end + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + bus_error_f <= 1'b0; + + + + + i_we_o <= 1'b0; + i_sel_o <= 4'b1111; + jtag_access <= 1'b0; + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + if (jtag_access == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_we_o <= 1'b0; + jtag_access <= 1'b0; + end + else + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + if (i_err_i == 1'b1) + begin + bus_error_f <= 1'b1; + $display ("Instruction bus error. Address: %x", i_adr_o); + end + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + i_sel_o <= 4'b1111; + + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + bus_error_f <= 1'b0; + + + end + + + else + begin + if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + begin + case (jtag_address[1:0]) + 2'b00: i_sel_o <= 4'b1000; + 2'b01: i_sel_o <= 4'b0100; + 2'b10: i_sel_o <= 4'b0010; + 2'b11: i_sel_o <= 4'b0001; + endcase + i_adr_o <= jtag_address; + i_dat_o <= {4{jtag_write_data}}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_we_o <= jtag_write_enable; + i_cti_o <= 3'b111; + jtag_access <= 1'b1; + end + end + + + + + + + + + if (branch_taken_x == 1'b1) + bus_error_f <= 1'b0; + + + if (branch_taken_m == 1'b1) + bus_error_f <= 1'b0; + + + end + end + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + bus_error_d <= 1'b0; + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + bus_error_d <= bus_error_f; + + + end + end + end + endmodule -module lm32_top_full_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_jtag_full_debug ( + clk_i, rst_i, - interrupt, - I_DAT_I, - I_ACK_I, - I_ERR_I, - I_RTY_I, - D_DAT_I, - D_ACK_I, - D_ERR_I, - D_RTY_I, - I_DAT_O, - I_ADR_O, - I_CYC_O, - I_SEL_O, - I_STB_O, - I_WE_O, - I_CTI_O, - I_LOCK_O, - I_BTE_O, - D_DAT_O, - D_ADR_O, - D_CYC_O, - D_SEL_O, - D_STB_O, - D_WE_O, - D_CTI_O, - D_LOCK_O, - D_BTE_O + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + csr, + csr_write_enable, + csr_write_data, + stall_x, + + + + + jtag_read_data, + jtag_access_complete, + + + + + exception_q_w, + + + + + + jtx_csr_read_data, + jrx_csr_read_data, + + + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + + + + + jtag_break, + jtag_reset, + + + jtag_reg_d, + jtag_reg_addr_d ); -parameter eba_reset = 32'h00000000; -parameter sdb_address = 32'h00000000; -input clk_i; -input rst_i; -input [ (32-1):0] interrupt; -input [ (32-1):0] I_DAT_I; -input I_ACK_I; -input I_ERR_I; -input I_RTY_I; -input [ (32-1):0] D_DAT_I; -input D_ACK_I; -input D_ERR_I; -input D_RTY_I; -output [ (32-1):0] I_DAT_O; -wire [ (32-1):0] I_DAT_O; -output [ (32-1):0] I_ADR_O; -wire [ (32-1):0] I_ADR_O; -output I_CYC_O; -wire I_CYC_O; -output [ (4-1):0] I_SEL_O; -wire [ (4-1):0] I_SEL_O; -output I_STB_O; -wire I_STB_O; -output I_WE_O; -wire I_WE_O; -output [ (3-1):0] I_CTI_O; -wire [ (3-1):0] I_CTI_O; -output I_LOCK_O; -wire I_LOCK_O; -output [ (2-1):0] I_BTE_O; -wire [ (2-1):0] I_BTE_O; -output [ (32-1):0] D_DAT_O; -wire [ (32-1):0] D_DAT_O; -output [ (32-1):0] D_ADR_O; -wire [ (32-1):0] D_ADR_O; -output D_CYC_O; -wire D_CYC_O; -output [ (4-1):0] D_SEL_O; -wire [ (4-1):0] D_SEL_O; -output D_STB_O; -wire D_STB_O; -output D_WE_O; -wire D_WE_O; -output [ (3-1):0] D_CTI_O; -wire [ (3-1):0] D_CTI_O; -output D_LOCK_O; -wire D_LOCK_O; -output [ (2-1):0] D_BTE_O; -wire [ (2-1):0] D_BTE_O; -wire [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_q; -wire jtag_update; -wire [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_q; -wire jtck; -wire jrstn; -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + + + + +input clk_i; +input rst_i; + +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + + +input [ (5-1):0] csr; +input csr_write_enable; +input [ (32-1):0] csr_write_data; +input stall_x; + + + + +input [ 7:0] jtag_read_data; +input jtag_access_complete; + + + + +input exception_q_w; + + + + + + + + + +output [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jtx_csr_read_data; +output [ (32-1):0] jrx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + + + + +output jtag_csr_write_enable; +reg jtag_csr_write_enable; +output [ (32-1):0] jtag_csr_write_data; +wire [ (32-1):0] jtag_csr_write_data; +output [ (5-1):0] jtag_csr; +wire [ (5-1):0] jtag_csr; +output jtag_read_enable; +reg jtag_read_enable; +output jtag_write_enable; +reg jtag_write_enable; +output [ 7:0] jtag_write_data; +wire [ 7:0] jtag_write_data; +output [ (32-1):0] jtag_address; +wire [ (32-1):0] jtag_address; + + + + +output jtag_break; +reg jtag_break; +output jtag_reset; +reg jtag_reset; + + +output [ 7:0] jtag_reg_d; +reg [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + + + + + +reg rx_update; +reg rx_update_r; +reg rx_update_r_r; +reg rx_update_r_r_r; + + + +wire [ 7:0] rx_byte; +wire [2:0] rx_addr; + + + +reg [ 7:0] uart_tx_byte; +reg uart_tx_valid; +reg [ 7:0] uart_rx_byte; +reg uart_rx_valid; + + + +reg [ 3:0] command; + + +reg [ 7:0] jtag_byte_0; +reg [ 7:0] jtag_byte_1; +reg [ 7:0] jtag_byte_2; +reg [ 7:0] jtag_byte_3; +reg [ 7:0] jtag_byte_4; +reg processing; + + + +reg [ 3:0] state; + + + + + + + +assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_csr = jtag_byte_4[ (5-1):0]; +assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_write_data = jtag_byte_4; + + + + + + +assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; + + + + + + +assign jtag_reg_addr_d[2] = processing; + + + + + + + +assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; +assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; + + + + + + + +assign rx_byte = jtag_reg_q; +assign rx_addr = jtag_reg_addr_q; + + + +always @(posedge clk_i ) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; + if (rst_i == 1'b1) + begin + rx_update <= 1'b0; + rx_update_r <= 1'b0; + rx_update_r_r <= 1'b0; + rx_update_r_r_r <= 1'b0; + end + else + begin + rx_update <= jtag_update; + rx_update_r <= rx_update; + rx_update_r_r <= rx_update_r; + rx_update_r_r_r <= rx_update_r_r; + end end -endfunction -lm32_cpu_full_debug - #( - .eba_reset(eba_reset), - .sdb_address(sdb_address) - ) cpu ( - .clk_i (clk_i), - .rst_i (rst_i), - .interrupt (interrupt), - .jtag_clk (jtck), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), - .I_DAT_I (I_DAT_I), - .I_ACK_I (I_ACK_I), - .I_ERR_I (I_ERR_I), - .I_RTY_I (I_RTY_I), - .D_DAT_I (D_DAT_I), - .D_ACK_I (D_ACK_I), - .D_ERR_I (D_ERR_I), - .D_RTY_I (D_RTY_I), - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d), - .I_DAT_O (I_DAT_O), - .I_ADR_O (I_ADR_O), - .I_CYC_O (I_CYC_O), - .I_SEL_O (I_SEL_O), - .I_STB_O (I_STB_O), - .I_WE_O (I_WE_O), - .I_CTI_O (I_CTI_O), - .I_LOCK_O (I_LOCK_O), - .I_BTE_O (I_BTE_O), - .D_DAT_O (D_DAT_O), - .D_ADR_O (D_ADR_O), - .D_CYC_O (D_CYC_O), - .D_SEL_O (D_SEL_O), - .D_STB_O (D_STB_O), - .D_WE_O (D_WE_O), - .D_CTI_O (D_CTI_O), - .D_LOCK_O (D_LOCK_O), - .D_BTE_O (D_BTE_O) - ); -jtag_cores jtag_cores ( - .reg_d (jtag_reg_d), - .reg_addr_d (jtag_reg_addr_d), - .reg_update (jtag_update), - .reg_q (jtag_reg_q), - .reg_addr_q (jtag_reg_addr_q), - .jtck (jtck), - .jrstn (jrstn) - ); -endmodule -module lm32_mc_arithmetic_full_debug ( - clk_i, - rst_i, - stall_d, - kill_x, - divide_d, - modulus_d, - operand_0_d, - operand_1_d, - result_x, - divide_by_zero_x, - stall_request_x - ); -input clk_i; -input rst_i; -input stall_d; -input kill_x; -input divide_d; -input modulus_d; -input [ (32-1):0] operand_0_d; -input [ (32-1):0] operand_1_d; -output [ (32-1):0] result_x; -reg [ (32-1):0] result_x; -output divide_by_zero_x; -reg divide_by_zero_x; -output stall_request_x; -wire stall_request_x; -reg [ (32-1):0] p; -reg [ (32-1):0] a; -reg [ (32-1):0] b; -wire [32:0] t; -reg [ 2:0] state; -reg [5:0] cycles; -assign stall_request_x = state != 3'b000; -assign t = {p[ 32-2:0], a[ 32-1]} - b; + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - cycles <= {6{1'b0}}; - p <= { 32{1'b0}}; - a <= { 32{1'b0}}; - b <= { 32{1'b0}}; - divide_by_zero_x <= 1'b0; - result_x <= { 32{1'b0}}; - state <= 3'b000; + state <= 4'h0; + command <= 4'b0000; + jtag_reg_d <= 8'h00; + + + processing <= 1'b0; + jtag_csr_write_enable <= 1'b0; + jtag_read_enable <= 1'b0; + jtag_write_enable <= 1'b0; + + + + + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + + + + + uart_tx_byte <= 8'h00; + uart_tx_valid <= 1'b0; + uart_rx_byte <= 8'h00; + uart_rx_valid <= 1'b0; + + end else begin - divide_by_zero_x <= 1'b0; - case (state) - 3'b000: - begin - if (stall_d == 1'b0) - begin - cycles <= 32; - p <= 32'b0; - a <= operand_0_d; - b <= operand_1_d; - if (divide_d == 1'b1) - state <= 3'b011 ; - if (modulus_d == 1'b1) - state <= 3'b010 ; - end - end - 3'b011 : + + + if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) begin - if (t[32] == 1'b0) - begin - p <= t[31:0]; - a <= {a[ 32-2:0], 1'b1}; - end - else + case (csr) + 5'he: begin - p <= {p[ 32-2:0], a[ 32-1]}; - a <= {a[ 32-2:0], 1'b0}; + + uart_tx_byte <= csr_write_data[ 7:0]; + uart_tx_valid <= 1'b1; end - result_x <= a; - if ((cycles == 32'd0) || (kill_x == 1'b1)) + 5'hf: begin - divide_by_zero_x <= b == { 32{1'b0}}; - state <= 3'b000; + + uart_rx_valid <= 1'b0; end - cycles <= cycles - 1'b1; + endcase end - 3'b010 : + + + + + + if (exception_q_w == 1'b1) begin - if (t[32] == 1'b0) - begin - p <= t[31:0]; - a <= {a[ 32-2:0], 1'b1}; - end - else + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + end + + + case (state) + 4'h0: + begin + + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) begin - p <= {p[ 32-2:0], a[ 32-1]}; - a <= {a[ 32-2:0], 1'b0}; + command <= rx_byte[7:4]; + case (rx_addr) + + + 3'b000: + begin + case (rx_byte[7:4]) + + + 4'b0001: + state <= 4'h1; + 4'b0011: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 4'h6; + end + 4'b0010: + state <= 4'h1; + 4'b0100: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 5; + end + 4'b0101: + state <= 4'h1; + + + 4'b0110: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + + + jtag_break <= 1'b1; + end + 4'b0111: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + + + jtag_reset <= 1'b1; + end + endcase + end + + + + + 3'b001: + begin + uart_rx_byte <= rx_byte; + uart_rx_valid <= 1'b1; + end + 3'b010: + begin + jtag_reg_d <= uart_tx_byte; + uart_tx_valid <= 1'b0; + end + + + default: + ; + endcase end - result_x <= p; - if ((cycles == 32'd0) || (kill_x == 1'b1)) + end + + + 4'h1: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) begin - divide_by_zero_x <= b == { 32{1'b0}}; - state <= 3'b000; + jtag_byte_0 <= rx_byte; + state <= 4'h2; end - cycles <= cycles - 1'b1; end + 4'h2: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_1 <= rx_byte; + state <= 4'h3; + end + end + 4'h3: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_2 <= rx_byte; + state <= 4'h4; + end + end + 4'h4: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_3 <= rx_byte; + if (command == 4'b0001) + state <= 4'h6; + else + state <= 4'h5; + end + end + 4'h5: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_4 <= rx_byte; + state <= 4'h6; + end + end + 4'h6: + begin + case (command) + 4'b0001, + 4'b0011: + begin + jtag_read_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0010, + 4'b0100: + begin + jtag_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0101: + begin + jtag_csr_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h8; + end + endcase + end + 4'h7: + begin + if (jtag_access_complete == 1'b1) + begin + jtag_read_enable <= 1'b0; + jtag_reg_d <= jtag_read_data; + jtag_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + end + 4'h8: + begin + jtag_csr_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + + endcase end -end +end + endmodule -module lm32_cpu_full_debug ( - clk_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_full_debug ( + + clk_i, rst_i, + interrupt, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - I_DAT_I, - I_ACK_I, - I_ERR_I, - I_RTY_I, - D_DAT_I, - D_ACK_I, - D_ERR_I, - D_RTY_I, - jtag_reg_d, - jtag_reg_addr_d, - I_DAT_O, - I_ADR_O, - I_CYC_O, - I_SEL_O, - I_STB_O, - I_WE_O, - I_CTI_O, - I_LOCK_O, - I_BTE_O, - D_DAT_O, - D_ADR_O, - D_CYC_O, - D_SEL_O, - D_STB_O, - D_WE_O, - D_CTI_O, - D_LOCK_O, - D_BTE_O + + stall_x, + + + non_debug_exception, + debug_exception, + + + + + eret_q_x, + + + bret_q_x, + + + csr, + csr_write_data, + csr_write_enable, + + interrupt_exception, + + csr_read_data ); -parameter eba_reset = 32'h00000000; -parameter deba_reset = 32'h10000000; -parameter sdb_address = 32'h00000000; -parameter icache_associativity = 1; -parameter icache_sets = 256; -parameter icache_bytes_per_line = 16; -parameter icache_base_address = 32'h0; -parameter icache_limit = 32'h7fffffff; -parameter dcache_associativity = 1; -parameter dcache_sets = 256; -parameter dcache_bytes_per_line = 16; -parameter dcache_base_address = 32'h0; -parameter dcache_limit = 32'h7fffffff; -parameter watchpoints = 32'h4; -parameter breakpoints = 0; -parameter interrupts = 32; + + + + + +parameter interrupts = 32; + + + + + input clk_i; input rst_i; -input [ (32-1):0] interrupt; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; -input [ (32-1):0] I_DAT_I; -input I_ACK_I; -input I_ERR_I; -input I_RTY_I; -input [ (32-1):0] D_DAT_I; -input D_ACK_I; -input D_ERR_I; -input D_RTY_I; -output [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; -output [ (32-1):0] I_DAT_O; -wire [ (32-1):0] I_DAT_O; -output [ (32-1):0] I_ADR_O; -wire [ (32-1):0] I_ADR_O; -output I_CYC_O; -wire I_CYC_O; -output [ (4-1):0] I_SEL_O; -wire [ (4-1):0] I_SEL_O; -output I_STB_O; -wire I_STB_O; -output I_WE_O; -wire I_WE_O; -output [ (3-1):0] I_CTI_O; -wire [ (3-1):0] I_CTI_O; -output I_LOCK_O; -wire I_LOCK_O; -output [ (2-1):0] I_BTE_O; -wire [ (2-1):0] I_BTE_O; -output [ (32-1):0] D_DAT_O; -wire [ (32-1):0] D_DAT_O; -output [ (32-1):0] D_ADR_O; -wire [ (32-1):0] D_ADR_O; -output D_CYC_O; -wire D_CYC_O; -output [ (4-1):0] D_SEL_O; -wire [ (4-1):0] D_SEL_O; -output D_STB_O; -wire D_STB_O; + +input [interrupts-1:0] interrupt; + +input stall_x; + + + +input non_debug_exception; +input debug_exception; + + + + +input eret_q_x; + + +input bret_q_x; + + + +input [ (5-1):0] csr; +input [ (32-1):0] csr_write_data; +input csr_write_enable; + + + + + +output interrupt_exception; +wire interrupt_exception; + +output [ (32-1):0] csr_read_data; +reg [ (32-1):0] csr_read_data; + + + + + +wire [interrupts-1:0] asserted; + +wire [interrupts-1:0] interrupt_n_exception; + + + +reg ie; +reg eie; + + +reg bie; + + +reg [interrupts-1:0] ip; +reg [interrupts-1:0] im; + + + + + + +assign interrupt_n_exception = ip & im; + + +assign interrupt_exception = (|interrupt_n_exception) & ie; + + +assign asserted = ip | interrupt; + +generate + if (interrupts > 1) + begin + +always @(*) +begin + case (csr) + 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + + bie, + + + + + eie, + ie + }; + 5'h2: csr_read_data = ip; + 5'h1: csr_read_data = im; + default: csr_read_data = { 32{1'bx}}; + endcase +end + end + else + begin + +always @(*) +begin + case (csr) + 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + + bie, + + + + + eie, + ie + }; + 5'h2: csr_read_data = ip; + default: csr_read_data = { 32{1'bx}}; + endcase +end + end +endgenerate + + + + + + + + reg [ 10:0] eie_delay = 0; + + +generate + + + if (interrupts > 1) + begin + +always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + ie <= 1'b0; + eie <= 1'b0; + + + bie <= 1'b0; + + + im <= {interrupts{1'b0}}; + ip <= {interrupts{1'b0}}; + eie_delay <= 0; + + end + else + begin + + ip <= asserted; + + + if (non_debug_exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + + bie <= ie; + ie <= 1'b0; + end + + + + + + + + + + else if (stall_x == 1'b0) + begin + + if(eie_delay[0]) + ie <= eie; + + eie_delay <= {1'b0, eie_delay[ 10:1]}; + + if (eret_q_x == 1'b1) begin + + eie_delay[ 10] <= 1'b1; + eie_delay[ 10-1:0] <= 0; + end + + + + + + else if (bret_q_x == 1'b1) + + ie <= bie; + + + else if (csr_write_enable == 1'b1) + begin + + if (csr == 5'h0) + begin + ie <= csr_write_data[0]; + eie <= csr_write_data[1]; + + + bie <= csr_write_data[2]; + + + end + if (csr == 5'h1) + im <= csr_write_data[interrupts-1:0]; + if (csr == 5'h2) + ip <= asserted & ~csr_write_data[interrupts-1:0]; + end + end + end +end + end +else + begin + +always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + ie <= 1'b0; + eie <= 1'b0; + + + bie <= 1'b0; + + + ip <= {interrupts{1'b0}}; + eie_delay <= 0; + end + else + begin + + ip <= asserted; + + + if (non_debug_exception == 1'b1) + begin + + eie <= ie; + ie <= 1'b0; + end + else if (debug_exception == 1'b1) + begin + + bie <= ie; + ie <= 1'b0; + end + + + + + + + + + + else if (stall_x == 1'b0) + begin + + if(eie_delay[0]) + ie <= eie; + + eie_delay <= {1'b0, eie_delay[ 10:1]}; + + if (eret_q_x == 1'b1) begin + + eie_delay[ 10] <= 1'b1; + eie_delay[ 10-1:0] <= 0; + end + + + + else if (bret_q_x == 1'b1) + + ie <= bie; + + + else if (csr_write_enable == 1'b1) + begin + + if (csr == 5'h0) + begin + ie <= csr_write_data[0]; + eie <= csr_write_data[1]; + + + bie <= csr_write_data[2]; + + + end + if (csr == 5'h2) + ip <= asserted & ~csr_write_data[interrupts-1:0]; + end + end + end +end + end +endgenerate + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_full ( + + clk_i, + rst_i, + + + interrupt, + + + + + + + + + + + I_DAT_I, + I_ACK_I, + I_ERR_I, + I_RTY_I, + + + + D_DAT_I, + D_ACK_I, + D_ERR_I, + D_RTY_I, + + + + + + + + + + + + I_DAT_O, + I_ADR_O, + I_CYC_O, + I_SEL_O, + I_STB_O, + I_WE_O, + I_CTI_O, + I_LOCK_O, + I_BTE_O, + + + + D_DAT_O, + D_ADR_O, + D_CYC_O, + D_SEL_O, + D_STB_O, + D_WE_O, + D_CTI_O, + D_LOCK_O, + D_BTE_O + ); + +parameter eba_reset = 32'h00000000; +parameter sdb_address = 32'h00000000; + + + + +input clk_i; +input rst_i; + + +input [ (32-1):0] interrupt; + + + + + + + + + + +input [ (32-1):0] I_DAT_I; +input I_ACK_I; +input I_ERR_I; +input I_RTY_I; + + + +input [ (32-1):0] D_DAT_I; +input D_ACK_I; +input D_ERR_I; +input D_RTY_I; + + + + + + + + + + + + + + + + + + + +output [ (32-1):0] I_DAT_O; +wire [ (32-1):0] I_DAT_O; +output [ (32-1):0] I_ADR_O; +wire [ (32-1):0] I_ADR_O; +output I_CYC_O; +wire I_CYC_O; +output [ (4-1):0] I_SEL_O; +wire [ (4-1):0] I_SEL_O; +output I_STB_O; +wire I_STB_O; +output I_WE_O; +wire I_WE_O; +output [ (3-1):0] I_CTI_O; +wire [ (3-1):0] I_CTI_O; +output I_LOCK_O; +wire I_LOCK_O; +output [ (2-1):0] I_BTE_O; +wire [ (2-1):0] I_BTE_O; + + + +output [ (32-1):0] D_DAT_O; +wire [ (32-1):0] D_DAT_O; +output [ (32-1):0] D_ADR_O; +wire [ (32-1):0] D_ADR_O; +output D_CYC_O; +wire D_CYC_O; +output [ (4-1):0] D_SEL_O; +wire [ (4-1):0] D_SEL_O; +output D_STB_O; +wire D_STB_O; output D_WE_O; wire D_WE_O; output [ (3-1):0] D_CTI_O; @@ -3638,245 +13737,71 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; -reg valid_a; -reg valid_f; -reg valid_d; -reg valid_x; -reg valid_m; -reg valid_w; -wire q_x; -wire [ (32-1):0] immediate_d; -wire load_d; -reg load_x; -reg load_m; -wire load_q_x; -wire store_q_x; -wire q_m; -wire load_q_m; -wire store_q_m; -wire store_d; -reg store_x; -reg store_m; -wire [ 1:0] size_d; -reg [ 1:0] size_x; -wire branch_d; -wire branch_predict_d; -wire branch_predict_taken_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; -wire bi_unconditional; -wire bi_conditional; -reg branch_x; -reg branch_predict_x; -reg branch_predict_taken_x; -reg branch_m; -reg branch_predict_m; -reg branch_predict_taken_m; -wire branch_mispredict_taken_m; -wire branch_flushX_m; -wire branch_reg_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; -wire [ 0:0] d_result_sel_0_d; -wire [ 1:0] d_result_sel_1_d; -wire x_result_sel_csr_d; -reg x_result_sel_csr_x; -wire q_d; -wire x_result_sel_mc_arith_d; -reg x_result_sel_mc_arith_x; -wire x_result_sel_sext_d; -reg x_result_sel_sext_x; -wire x_result_sel_logic_d; -wire x_result_sel_add_d; -reg x_result_sel_add_x; -wire m_result_sel_compare_d; -reg m_result_sel_compare_x; -reg m_result_sel_compare_m; -wire m_result_sel_shift_d; -reg m_result_sel_shift_x; -reg m_result_sel_shift_m; -wire w_result_sel_load_d; -reg w_result_sel_load_x; -reg w_result_sel_load_m; -reg w_result_sel_load_w; -wire w_result_sel_mul_d; -reg w_result_sel_mul_x; -reg w_result_sel_mul_m; -reg w_result_sel_mul_w; -wire x_bypass_enable_d; -reg x_bypass_enable_x; -wire m_bypass_enable_d; -reg m_bypass_enable_x; -reg m_bypass_enable_m; -wire sign_extend_d; -reg sign_extend_x; -wire write_enable_d; -reg write_enable_x; -wire write_enable_q_x; -reg write_enable_m; -wire write_enable_q_m; -reg write_enable_w; -wire write_enable_q_w; -wire read_enable_0_d; -wire [ (5-1):0] read_idx_0_d; -wire read_enable_1_d; -wire [ (5-1):0] read_idx_1_d; -wire [ (5-1):0] write_idx_d; -reg [ (5-1):0] write_idx_x; -reg [ (5-1):0] write_idx_m; -reg [ (5-1):0] write_idx_w; -wire [ (5-1):0] csr_d; -reg [ (5-1):0] csr_x; -wire [ (3-1):0] condition_d; -reg [ (3-1):0] condition_x; -wire break_d; -reg break_x; -wire scall_d; -reg scall_x; -wire eret_d; -reg eret_x; -wire eret_q_x; -wire bret_d; -reg bret_x; -wire bret_q_x; -wire csr_write_enable_d; -reg csr_write_enable_x; -wire csr_write_enable_q_x; -wire bus_error_d; -reg bus_error_x; -reg data_bus_error_exception_m; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] memop_pc_w; -reg [ (32-1):0] d_result_0; -reg [ (32-1):0] d_result_1; -reg [ (32-1):0] x_result; -reg [ (32-1):0] m_result; -reg [ (32-1):0] w_result; -reg [ (32-1):0] operand_0_x; -reg [ (32-1):0] operand_1_x; -reg [ (32-1):0] store_operand_x; -reg [ (32-1):0] operand_m; -reg [ (32-1):0] operand_w; -reg [ (32-1):0] reg_data_live_0; -reg [ (32-1):0] reg_data_live_1; -reg use_buf; -reg [ (32-1):0] reg_data_buf_0; -reg [ (32-1):0] reg_data_buf_1; -wire [ (32-1):0] reg_data_0; -wire [ (32-1):0] reg_data_1; -reg [ (32-1):0] bypass_data_0; -reg [ (32-1):0] bypass_data_1; -wire reg_write_enable_q_w; -reg interlock; -wire stall_a; -wire stall_f; -wire stall_d; -wire stall_x; -wire stall_m; -wire adder_op_d; -reg adder_op_x; -reg adder_op_x_n; -wire [ (32-1):0] adder_result_x; -wire adder_overflow_x; -wire adder_carry_n_x; -wire [ 3:0] logic_op_d; -reg [ 3:0] logic_op_x; -wire [ (32-1):0] logic_result_x; -wire [ (32-1):0] sextb_result_x; -wire [ (32-1):0] sexth_result_x; -wire [ (32-1):0] sext_result_x; -wire direction_d; -reg direction_x; -wire [ (32-1):0] shifter_result_m; -wire [ (32-1):0] multiplier_result_w; -wire divide_d; -wire divide_q_d; -wire modulus_d; -wire modulus_q_d; -wire divide_by_zero_x; -wire mc_stall_request_x; -wire [ (32-1):0] mc_result_x; -wire [ (32-1):0] interrupt_csr_read_data_x; -wire [ (32-1):0] cfg; -wire [ (32-1):0] cfg2; -reg [ (32-1):0] csr_read_data_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -wire [ (32-1):0] instruction_f; -wire [ (32-1):0] instruction_d; -wire iflush; -wire icache_stall_request; -wire icache_restart_request; -wire icache_refill_request; -wire icache_refilling; -wire dflush_x; -reg dflush_m; -wire dcache_stall_request; -wire dcache_restart_request; -wire dcache_refill_request; -wire dcache_refilling; -wire [ (32-1):0] load_data_w; -wire stall_wb_load; -wire [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; -wire jtag_csr_write_enable; -wire [ (32-1):0] jtag_csr_write_data; -wire [ (5-1):0] jtag_csr; -wire jtag_read_enable; -wire [ 7:0] jtag_read_data; -wire jtag_write_enable; -wire [ 7:0] jtag_write_data; -wire [ (32-1):0] jtag_address; -wire jtag_access_complete; -wire jtag_break; -wire raw_x_0; -wire raw_x_1; -wire raw_m_0; -wire raw_m_1; -wire raw_w_0; -wire raw_w_1; -wire cmp_zero; -wire cmp_negative; -wire cmp_overflow; -wire cmp_carry_n; -reg condition_met_x; -reg condition_met_m; -wire branch_taken_x; -wire branch_taken_m; -wire kill_f; -wire kill_d; -wire kill_x; -wire kill_m; -wire kill_w; -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; -reg [ (3-1):0] eid_x; -wire dc_ss; -wire dc_re; -wire bp_match; -wire wp_match; -wire exception_x; -reg exception_m; -wire debug_exception_x; -reg debug_exception_m; -reg debug_exception_w; -wire debug_exception_q_w; -wire non_debug_exception_x; -reg non_debug_exception_m; -reg non_debug_exception_w; -wire non_debug_exception_q_w; -wire reset_exception; -wire interrupt_exception; -wire breakpoint_exception; -wire watchpoint_exception; -wire instruction_bus_error_exception; -wire data_bus_error_exception; -wire divide_by_zero_exception; -wire system_call_exception; -reg data_bus_error_seen; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -3884,6 +13809,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -3896,1555 +13822,1995 @@ begin clogb2_v1 = i-1; end endfunction -lm32_instruction_unit_full_debug #( - .eba_reset (eba_reset), - .associativity (icache_associativity), - .sets (icache_sets), - .bytes_per_line (icache_bytes_per_line), - .base_address (icache_base_address), - .limit (icache_limit) - ) instruction_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .stall_d (stall_d), - .stall_x (stall_x), - .stall_m (stall_m), - .valid_f (valid_f), - .valid_d (valid_d), - .kill_f (kill_f), - .branch_predict_taken_d (branch_predict_taken_d), - .branch_predict_address_d (branch_predict_address_d), - .branch_taken_x (branch_taken_x), - .branch_target_x (branch_target_x), - .exception_m (exception_m), - .branch_taken_m (branch_taken_m), - .branch_mispredict_taken_m (branch_mispredict_taken_m), - .branch_target_m (branch_target_m), - .iflush (iflush), - .dcache_restart_request (dcache_restart_request), - .dcache_refill_request (dcache_refill_request), - .dcache_refilling (dcache_refilling), - .i_dat_i (I_DAT_I), - .i_ack_i (I_ACK_I), - .i_err_i (I_ERR_I), - .i_rty_i (I_RTY_I), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - .pc_f (pc_f), - .pc_d (pc_d), - .pc_x (pc_x), - .pc_m (pc_m), - .pc_w (pc_w), - .icache_stall_request (icache_stall_request), - .icache_restart_request (icache_restart_request), - .icache_refill_request (icache_refill_request), - .icache_refilling (icache_refilling), - .i_dat_o (I_DAT_O), - .i_adr_o (I_ADR_O), - .i_cyc_o (I_CYC_O), - .i_sel_o (I_SEL_O), - .i_stb_o (I_STB_O), - .i_we_o (I_WE_O), - .i_cti_o (I_CTI_O), - .i_lock_o (I_LOCK_O), - .i_bte_o (I_BTE_O), - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - .bus_error_d (bus_error_d), - .instruction_f (instruction_f), - .instruction_d (instruction_d) - ); -lm32_decoder_full_debug decoder ( - .instruction (instruction_d), - .d_result_sel_0 (d_result_sel_0_d), - .d_result_sel_1 (d_result_sel_1_d), - .x_result_sel_csr (x_result_sel_csr_d), - .x_result_sel_mc_arith (x_result_sel_mc_arith_d), - .x_result_sel_sext (x_result_sel_sext_d), - .x_result_sel_logic (x_result_sel_logic_d), - .x_result_sel_add (x_result_sel_add_d), - .m_result_sel_compare (m_result_sel_compare_d), - .m_result_sel_shift (m_result_sel_shift_d), - .w_result_sel_load (w_result_sel_load_d), - .w_result_sel_mul (w_result_sel_mul_d), - .x_bypass_enable (x_bypass_enable_d), - .m_bypass_enable (m_bypass_enable_d), - .read_enable_0 (read_enable_0_d), - .read_idx_0 (read_idx_0_d), - .read_enable_1 (read_enable_1_d), - .read_idx_1 (read_idx_1_d), - .write_enable (write_enable_d), - .write_idx (write_idx_d), - .immediate (immediate_d), - .branch_offset (branch_offset_d), - .load (load_d), - .store (store_d), - .size (size_d), - .sign_extend (sign_extend_d), - .adder_op (adder_op_d), - .logic_op (logic_op_d), - .direction (direction_d), - .divide (divide_d), - .modulus (modulus_d), - .branch (branch_d), - .bi_unconditional (bi_unconditional), - .bi_conditional (bi_conditional), - .branch_reg (branch_reg_d), - .condition (condition_d), - .break_opcode (break_d), - .scall (scall_d), - .eret (eret_d), - .bret (bret_d), - .csr_write_enable (csr_write_enable_d) - ); -lm32_load_store_unit_full_debug #( - .associativity (dcache_associativity), - .sets (dcache_sets), - .bytes_per_line (dcache_bytes_per_line), - .base_address (dcache_base_address), - .limit (dcache_limit) - ) load_store_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_x (stall_x), - .stall_m (stall_m), - .kill_x (kill_x), - .kill_m (kill_m), - .exception_m (exception_m), - .store_operand_x (store_operand_x), - .load_store_address_x (adder_result_x), - .load_store_address_m (operand_m), - .load_store_address_w (operand_w[1:0]), - .load_x (load_x), - .store_x (store_x), - .load_q_x (load_q_x), - .store_q_x (store_q_x), - .load_q_m (load_q_m), - .store_q_m (store_q_m), - .sign_extend_x (sign_extend_x), - .size_x (size_x), - .dflush (dflush_m), - .d_dat_i (D_DAT_I), - .d_ack_i (D_ACK_I), - .d_err_i (D_ERR_I), - .d_rty_i (D_RTY_I), - .dcache_refill_request (dcache_refill_request), - .dcache_restart_request (dcache_restart_request), - .dcache_stall_request (dcache_stall_request), - .dcache_refilling (dcache_refilling), - .load_data_w (load_data_w), - .stall_wb_load (stall_wb_load), - .d_dat_o (D_DAT_O), - .d_adr_o (D_ADR_O), - .d_cyc_o (D_CYC_O), - .d_sel_o (D_SEL_O), - .d_stb_o (D_STB_O), - .d_we_o (D_WE_O), - .d_cti_o (D_CTI_O), - .d_lock_o (D_LOCK_O), - .d_bte_o (D_BTE_O) - ); -lm32_adder adder ( - .adder_op_x (adder_op_x), - .adder_op_x_n (adder_op_x_n), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .adder_result_x (adder_result_x), - .adder_carry_n_x (adder_carry_n_x), - .adder_overflow_x (adder_overflow_x) - ); -lm32_logic_op logic_op ( - .logic_op_x (logic_op_x), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .logic_result_x (logic_result_x) - ); -lm32_shifter shifter ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_x (stall_x), - .direction_x (direction_x), - .sign_extend_x (sign_extend_x), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .shifter_result_m (shifter_result_m) - ); -lm32_multiplier multiplier ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_x (stall_x), - .stall_m (stall_m), - .operand_0 (d_result_0), - .operand_1 (d_result_1), - .result (multiplier_result_w) - ); -lm32_mc_arithmetic_full_debug mc_arithmetic ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_d (stall_d), - .kill_x (kill_x), - .divide_d (divide_q_d), - .modulus_d (modulus_q_d), - .operand_0_d (d_result_0), - .operand_1_d (d_result_1), - .result_x (mc_result_x), - .divide_by_zero_x (divide_by_zero_x), - .stall_request_x (mc_stall_request_x) - ); -lm32_interrupt_full_debug interrupt_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .interrupt (interrupt), - .stall_x (stall_x), - .non_debug_exception (non_debug_exception_q_w), - .debug_exception (debug_exception_q_w), - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .interrupt_exception (interrupt_exception), - .csr_read_data (interrupt_csr_read_data_x) + + + + + + + + +lm32_cpu_full + #( + .eba_reset(eba_reset), + .sdb_address(sdb_address) + ) cpu ( + + .clk_i (clk_i), + + + + + .rst_i (rst_i), + + + + .interrupt (interrupt), + + + + + + + + + + + + + + + + + + + + .I_DAT_I (I_DAT_I), + .I_ACK_I (I_ACK_I), + .I_ERR_I (I_ERR_I), + .I_RTY_I (I_RTY_I), + + + + .D_DAT_I (D_DAT_I), + .D_ACK_I (D_ACK_I), + .D_ERR_I (D_ERR_I), + .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + + + + + + + + + + + + + + + .I_DAT_O (I_DAT_O), + .I_ADR_O (I_ADR_O), + .I_CYC_O (I_CYC_O), + .I_SEL_O (I_SEL_O), + .I_STB_O (I_STB_O), + .I_WE_O (I_WE_O), + .I_CTI_O (I_CTI_O), + .I_LOCK_O (I_LOCK_O), + .I_BTE_O (I_BTE_O), + + + + .D_DAT_O (D_DAT_O), + .D_ADR_O (D_ADR_O), + .D_CYC_O (D_CYC_O), + .D_SEL_O (D_SEL_O), + .D_STB_O (D_STB_O), + .D_WE_O (D_WE_O), + .D_CTI_O (D_CTI_O), + .D_LOCK_O (D_LOCK_O), + .D_BTE_O (D_BTE_O) ); -lm32_jtag_full_debug jtag ( - .clk_i (clk_i), - .rst_i (rst_i), - .jtag_clk (jtag_clk), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .stall_x (stall_x), - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), - .jtx_csr_read_data (jtx_csr_read_data), - .jrx_csr_read_data (jrx_csr_read_data), - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - .jtag_break (jtag_break), - .jtag_reset (reset_exception), - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d) + + + + + + + + + + + + + + + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_full ( + + clk_i, + rst_i, + stall_d, + kill_x, + + + divide_d, + modulus_d, + + + + + + + + + + + + + operand_0_d, + operand_1_d, + + result_x, + + + divide_by_zero_x, + + + stall_request_x ); -lm32_debug_full_debug #( - .breakpoints (breakpoints), - .watchpoints (watchpoints) - ) hw_debug ( - .clk_i (clk_i), - .rst_i (rst_i), - .pc_x (pc_x), - .load_x (load_x), - .store_x (store_x), - .load_store_address_x (adder_result_x), - .csr_write_enable_x (csr_write_enable_q_x), - .csr_write_data (operand_1_x), - .csr_x (csr_x), - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .stall_x (stall_x), - .exception_x (exception_x), - .q_x (q_x), - .dcache_refill_request (dcache_refill_request), - .dc_ss (dc_ss), - .dc_re (dc_re), - .bp_match (bp_match), - .wp_match (wp_match) - ); - wire [31:0] regfile_data_0, regfile_data_1; - reg [31:0] w_result_d; - reg regfile_raw_0, regfile_raw_0_nxt; - reg regfile_raw_1, regfile_raw_1_nxt; - always @(reg_write_enable_q_w or write_idx_w or instruction_f) - begin - if (reg_write_enable_q_w - && (write_idx_w == instruction_f[25:21])) - regfile_raw_0_nxt = 1'b1; - else - regfile_raw_0_nxt = 1'b0; - if (reg_write_enable_q_w - && (write_idx_w == instruction_f[20:16])) - regfile_raw_1_nxt = 1'b1; - else - regfile_raw_1_nxt = 1'b0; - end - always @(regfile_raw_0 or w_result_d or regfile_data_0) - if (regfile_raw_0) - reg_data_live_0 = w_result_d; - else - reg_data_live_0 = regfile_data_0; - always @(regfile_raw_1 or w_result_d or regfile_data_1) - if (regfile_raw_1) - reg_data_live_1 = w_result_d; - else - reg_data_live_1 = regfile_data_1; - always @(posedge clk_i ) - if (rst_i == 1'b1) - begin - regfile_raw_0 <= 1'b0; - regfile_raw_1 <= 1'b0; - w_result_d <= 32'b0; - end - else - begin - regfile_raw_0 <= regfile_raw_0_nxt; - regfile_raw_1 <= regfile_raw_1_nxt; - w_result_d <= w_result; - end - lm32_dp_ram - #( - .addr_depth(1<<5), - .addr_width(5), - .data_width(32) - ) - reg_0 - ( - .clk_i (clk_i), - .rst_i (rst_i), - .we_i (reg_write_enable_q_w), - .wdata_i (w_result), - .waddr_i (write_idx_w), - .raddr_i (instruction_f[25:21]), - .rdata_o (regfile_data_0) - ); - lm32_dp_ram - #( - .addr_depth(1<<5), - .addr_width(5), - .data_width(32) - ) - reg_1 - ( - .clk_i (clk_i), - .rst_i (rst_i), - .we_i (reg_write_enable_q_w), - .wdata_i (w_result), - .waddr_i (write_idx_w), - .raddr_i (instruction_f[20:16]), - .rdata_o (regfile_data_1) - ); -assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; -assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; -assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); -assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); -assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); -assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); -assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); -assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); -always @(*) -begin - if ( ( (x_bypass_enable_x == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) - ) - ) - || ( (m_bypass_enable_m == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) - ) - ) - ) - interlock = 1'b1; - else - interlock = 1'b0; -end -always @(*) -begin - if (raw_x_0 == 1'b1) - bypass_data_0 = x_result; - else if (raw_m_0 == 1'b1) - bypass_data_0 = m_result; - else if (raw_w_0 == 1'b1) - bypass_data_0 = w_result; - else - bypass_data_0 = reg_data_0; -end -always @(*) + + + + + +input clk_i; +input rst_i; +input stall_d; +input kill_x; + + +input divide_d; +input modulus_d; + + + + + + + + + + + + +input [ (32-1):0] operand_0_d; +input [ (32-1):0] operand_1_d; + + + + + +output [ (32-1):0] result_x; +reg [ (32-1):0] result_x; + + +output divide_by_zero_x; +reg divide_by_zero_x; + + +output stall_request_x; +wire stall_request_x; + + + + + +reg [ (32-1):0] p; +reg [ (32-1):0] a; +reg [ (32-1):0] b; + + +wire [32:0] t; + + + +reg [ 2:0] state; +reg [5:0] cycles; + + + + + + + + + + + + +assign stall_request_x = state != 3'b000; + + + + +assign t = {p[ 32-2:0], a[ 32-1]} - b; + + + + + + + + + + + + + + +always @(posedge clk_i ) begin - if (raw_x_1 == 1'b1) - bypass_data_1 = x_result; - else if (raw_m_1 == 1'b1) - bypass_data_1 = m_result; - else if (raw_w_1 == 1'b1) - bypass_data_1 = w_result; - else - bypass_data_1 = reg_data_1; -end - assign branch_predict_d = bi_unconditional | bi_conditional; - assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); - assign branch_target_d = pc_d + branch_offset_d; - assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; -always @(*) -begin - d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; - case (d_result_sel_1_d) - 2'b00: d_result_1 = { 32{1'b0}}; - 2'b01: d_result_1 = bypass_data_1; - 2'b10: d_result_1 = immediate_d; - default: d_result_1 = { 32{1'bx}}; - endcase -end -assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; -assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; -assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; -assign cmp_zero = operand_0_x == operand_1_x; -assign cmp_negative = adder_result_x[ 32-1]; -assign cmp_overflow = adder_overflow_x; -assign cmp_carry_n = adder_carry_n_x; -always @(*) -begin - case (condition_x) - 3'b000: condition_met_x = 1'b1; - 3'b110: condition_met_x = 1'b1; - 3'b001: condition_met_x = cmp_zero; - 3'b111: condition_met_x = !cmp_zero; - 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); - 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; - 3'b011: condition_met_x = cmp_negative == cmp_overflow; - 3'b100: condition_met_x = cmp_carry_n; - default: condition_met_x = 1'bx; - endcase -end -always @(*) -begin - x_result = x_result_sel_add_x ? adder_result_x - : x_result_sel_csr_x ? csr_read_data_x - : x_result_sel_sext_x ? sext_result_x - : x_result_sel_mc_arith_x ? mc_result_x - : logic_result_x; -end -always @(*) -begin - m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} - : m_result_sel_shift_m ? shifter_result_m - : operand_m; -end -always @(*) -begin - w_result = w_result_sel_load_w ? load_data_w - : w_result_sel_mul_w ? multiplier_result_w - : operand_w; -end -assign branch_taken_x = (stall_x == 1'b0) - && ( (branch_x == 1'b1) - && ((condition_x == 3'b000) || (condition_x == 3'b110)) - && (valid_x == 1'b1) - && (branch_predict_x == 1'b0) - ); -assign branch_taken_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( ( (condition_met_m == 1'b1) - && (branch_predict_taken_m == 1'b0) - ) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign branch_mispredict_taken_m = (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1); -assign branch_flushX_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( (condition_met_m == 1'b1) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign kill_f = ( (valid_d == 1'b1) - && (branch_predict_taken_d == 1'b1) - ) - || (branch_taken_m == 1'b1) - || (branch_taken_x == 1'b1) - || (icache_refill_request == 1'b1) - || (dcache_refill_request == 1'b1) - ; -assign kill_d = (branch_taken_m == 1'b1) - || (branch_taken_x == 1'b1) - || (icache_refill_request == 1'b1) - || (dcache_refill_request == 1'b1) - ; -assign kill_x = (branch_flushX_m == 1'b1) - || (dcache_refill_request == 1'b1) - ; -assign kill_m = 1'b0 - || (dcache_refill_request == 1'b1) - ; -assign kill_w = 1'b0 - || (dcache_refill_request == 1'b1) - ; -assign breakpoint_exception = ( ( (break_x == 1'b1) - || (bp_match == 1'b1) - ) - && (valid_x == 1'b1) - ) - || (jtag_break == 1'b1) - ; -assign watchpoint_exception = wp_match == 1'b1; -assign instruction_bus_error_exception = ( (bus_error_x == 1'b1) - && (valid_x == 1'b1) - ); -assign data_bus_error_exception = data_bus_error_seen == 1'b1; -assign divide_by_zero_exception = divide_by_zero_x == 1'b1; -assign system_call_exception = ( (scall_x == 1'b1) - && (valid_x == 1'b1) - ); -assign debug_exception_x = (breakpoint_exception == 1'b1) - || (watchpoint_exception == 1'b1) - ; -assign non_debug_exception_x = (system_call_exception == 1'b1) - || (reset_exception == 1'b1) - || (instruction_bus_error_exception == 1'b1) - || (data_bus_error_exception == 1'b1) - || (divide_by_zero_exception == 1'b1) - || ( (interrupt_exception == 1'b1) - && (dc_ss == 1'b0) - && (store_q_m == 1'b0) - && (D_CYC_O == 1'b0) - ) - ; -assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); -always @(*) -begin - if (reset_exception == 1'b1) - eid_x = 3'h0; - else - if (data_bus_error_exception == 1'b1) - eid_x = 3'h4; - else - if (breakpoint_exception == 1'b1) - eid_x = 3'd1; - else - if (data_bus_error_exception == 1'b1) - eid_x = 3'h4; - else - if (instruction_bus_error_exception == 1'b1) - eid_x = 3'h2; - else - if (watchpoint_exception == 1'b1) - eid_x = 3'd3; - else - if (divide_by_zero_exception == 1'b1) - eid_x = 3'h5; - else - if ( (interrupt_exception == 1'b1) - && (dc_ss == 1'b0) - ) - eid_x = 3'h6; - else - eid_x = 3'h7; -end -assign stall_a = (stall_f == 1'b1); -assign stall_f = (stall_d == 1'b1); -assign stall_d = (stall_x == 1'b1) - || ( (interlock == 1'b1) - && (kill_d == 1'b0) - ) - || ( ( (eret_d == 1'b1) - || (scall_d == 1'b1) - || (bus_error_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_x == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( ( (break_d == 1'b1) - || (bret_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (store_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( (csr_write_enable_d == 1'b1) - && (load_q_x == 1'b1) - ) - ; -assign stall_x = (stall_m == 1'b1) - || ( (mc_stall_request_x == 1'b1) - && (kill_x == 1'b0) - ) - ; -assign stall_m = (stall_wb_load == 1'b1) - || ( (D_CYC_O == 1'b1) - && ( (store_m == 1'b1) - || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) - || (load_m == 1'b1) - || (load_x == 1'b1) - ) - ) - || (dcache_stall_request == 1'b1) - || (icache_stall_request == 1'b1) - || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) - ; -assign q_d = (valid_d == 1'b1) && (kill_d == 1'b0); -assign divide_q_d = (divide_d == 1'b1) && (q_d == 1'b1); -assign modulus_q_d = (modulus_d == 1'b1) && (q_d == 1'b1); -assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); -assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); -assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); -assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); -assign load_q_x = (load_x == 1'b1) - && (q_x == 1'b1) - && (bp_match == 1'b0) - ; -assign store_q_x = (store_x == 1'b1) - && (q_x == 1'b1) - && (bp_match == 1'b0) - ; -assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); -assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); -assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); -assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); -assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); -assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); -assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); -assign cfg = { - 6'h02, - watchpoints[3:0], - breakpoints[3:0], - interrupts[5:0], - 1'b1, - 1'b0, - 1'b1, - 1'b1, - 1'b1, - 1'b1, - 1'b0, - 1'b0, - 1'b1, - 1'b1, - 1'b1, - 1'b1 - }; -assign cfg2 = { - 30'b0, - 1'b0, - 1'b0 - }; -assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 5'h3) - && (stall_d == 1'b0) - && (kill_d == 1'b0) - && (valid_d == 1'b1)) - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h3)) - ; -assign dflush_x = ( (csr_write_enable_q_x == 1'b1) - && (csr_x == 5'h4)) - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h4)) - ; -assign csr_d = read_idx_0_d[ (5-1):0]; -always @(*) -begin - case (csr_x) - 5'h0, - 5'h1, - 5'h2: csr_read_data_x = interrupt_csr_read_data_x; - 5'h6: csr_read_data_x = cfg; - 5'h7: csr_read_data_x = {eba, 8'h00}; - 5'h9: csr_read_data_x = {deba, 8'h00}; - 5'he: csr_read_data_x = jtx_csr_read_data; - 5'hf: csr_read_data_x = jrx_csr_read_data; - 5'ha: csr_read_data_x = cfg2; - 5'hb: csr_read_data_x = sdb_address; - default: csr_read_data_x = { 32{1'bx}}; - endcase -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + if (rst_i == 1'b1) + begin + cycles <= {6{1'b0}}; + p <= { 32{1'b0}}; + a <= { 32{1'b0}}; + b <= { 32{1'b0}}; + + + + + + + divide_by_zero_x <= 1'b0; + + + result_x <= { 32{1'b0}}; + state <= 3'b000; + end else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) - eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) - eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - else - begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) - deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) - deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - data_bus_error_seen <= 1'b0; - else - begin - if ((D_ERR_I == 1'b1) && (D_CYC_O == 1'b1)) - data_bus_error_seen <= 1'b1; - if ((exception_m == 1'b1) && (kill_m == 1'b0)) - data_bus_error_seen <= 1'b0; - end -end -always @(*) -begin - if ( (icache_refill_request == 1'b1) - || (dcache_refill_request == 1'b1) - ) - valid_a = 1'b0; - else if ( (icache_restart_request == 1'b1) - || (dcache_restart_request == 1'b1) - ) - valid_a = 1'b1; - else - valid_a = !icache_refilling && !dcache_refilling; -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - valid_f <= 1'b0; - valid_d <= 1'b0; - valid_x <= 1'b0; - valid_m <= 1'b0; - valid_w <= 1'b0; - end - else - begin - if ((kill_f == 1'b1) || (stall_a == 1'b0)) - valid_f <= valid_a; - else if (stall_f == 1'b0) - valid_f <= 1'b0; - if (kill_d == 1'b1) - valid_d <= 1'b0; - else if (stall_f == 1'b0) - valid_d <= valid_f & !kill_f; - else if (stall_d == 1'b0) - valid_d <= 1'b0; - if (stall_d == 1'b0) - valid_x <= valid_d & !kill_d; - else if (kill_x == 1'b1) - valid_x <= 1'b0; - else if (stall_x == 1'b0) - valid_x <= 1'b0; - if (kill_m == 1'b1) - valid_m <= 1'b0; - else if (stall_x == 1'b0) - valid_m <= valid_x & !kill_x; - else if (stall_m == 1'b0) - valid_m <= 1'b0; - if (stall_m == 1'b0) - valid_w <= valid_m & !kill_m; - else - valid_w <= 1'b0; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - operand_0_x <= { 32{1'b0}}; - operand_1_x <= { 32{1'b0}}; - store_operand_x <= { 32{1'b0}}; - branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - x_result_sel_csr_x <= 1'b0; - x_result_sel_mc_arith_x <= 1'b0; - x_result_sel_sext_x <= 1'b0; - x_result_sel_add_x <= 1'b0; - m_result_sel_compare_x <= 1'b0; - m_result_sel_shift_x <= 1'b0; - w_result_sel_load_x <= 1'b0; - w_result_sel_mul_x <= 1'b0; - x_bypass_enable_x <= 1'b0; - m_bypass_enable_x <= 1'b0; - write_enable_x <= 1'b0; - write_idx_x <= { 5{1'b0}}; - csr_x <= { 5{1'b0}}; - load_x <= 1'b0; - store_x <= 1'b0; - size_x <= { 2{1'b0}}; - sign_extend_x <= 1'b0; - adder_op_x <= 1'b0; - adder_op_x_n <= 1'b0; - logic_op_x <= 4'h0; - direction_x <= 1'b0; - branch_x <= 1'b0; - branch_predict_x <= 1'b0; - branch_predict_taken_x <= 1'b0; - condition_x <= 3'b000; - break_x <= 1'b0; - scall_x <= 1'b0; - eret_x <= 1'b0; - bret_x <= 1'b0; - bus_error_x <= 1'b0; - data_bus_error_exception_m <= 1'b0; - csr_write_enable_x <= 1'b0; - operand_m <= { 32{1'b0}}; - branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - m_result_sel_compare_m <= 1'b0; - m_result_sel_shift_m <= 1'b0; - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; - m_bypass_enable_m <= 1'b0; - branch_m <= 1'b0; - branch_predict_m <= 1'b0; - branch_predict_taken_m <= 1'b0; - exception_m <= 1'b0; - load_m <= 1'b0; - store_m <= 1'b0; - write_enable_m <= 1'b0; - write_idx_m <= { 5{1'b0}}; - condition_met_m <= 1'b0; - dflush_m <= 1'b0; - debug_exception_m <= 1'b0; - non_debug_exception_m <= 1'b0; - operand_w <= { 32{1'b0}}; - w_result_sel_load_w <= 1'b0; - w_result_sel_mul_w <= 1'b0; - write_idx_w <= { 5{1'b0}}; - write_enable_w <= 1'b0; - debug_exception_w <= 1'b0; - non_debug_exception_w <= 1'b0; - memop_pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - end - else - begin - if (stall_x == 1'b0) + + + divide_by_zero_x <= 1'b0; + + + case (state) + 3'b000: begin - operand_0_x <= d_result_0; - operand_1_x <= d_result_1; - store_operand_x <= bypass_data_1; - branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; - x_result_sel_csr_x <= x_result_sel_csr_d; - x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d; - x_result_sel_sext_x <= x_result_sel_sext_d; - x_result_sel_add_x <= x_result_sel_add_d; - m_result_sel_compare_x <= m_result_sel_compare_d; - m_result_sel_shift_x <= m_result_sel_shift_d; - w_result_sel_load_x <= w_result_sel_load_d; - w_result_sel_mul_x <= w_result_sel_mul_d; - x_bypass_enable_x <= x_bypass_enable_d; - m_bypass_enable_x <= m_bypass_enable_d; - load_x <= load_d; - store_x <= store_d; - branch_x <= branch_d; - branch_predict_x <= branch_predict_d; - branch_predict_taken_x <= branch_predict_taken_d; - write_idx_x <= write_idx_d; - csr_x <= csr_d; - size_x <= size_d; - sign_extend_x <= sign_extend_d; - adder_op_x <= adder_op_d; - adder_op_x_n <= ~adder_op_d; - logic_op_x <= logic_op_d; - direction_x <= direction_d; - condition_x <= condition_d; - csr_write_enable_x <= csr_write_enable_d; - break_x <= break_d; - scall_x <= scall_d; - bus_error_x <= bus_error_d; - eret_x <= eret_d; - bret_x <= bret_d; - write_enable_x <= write_enable_d; + if (stall_d == 1'b0) + begin + cycles <= 32; + p <= 32'b0; + a <= operand_0_d; + b <= operand_1_d; + + + if (divide_d == 1'b1) + state <= 3'b011 ; + if (modulus_d == 1'b1) + state <= 3'b010 ; + + + + + + + + + + + + + + + + + + + + + + + + + + + end end - if (stall_m == 1'b0) + + + 3'b011 : begin - operand_m <= x_result; - m_result_sel_compare_m <= m_result_sel_compare_x; - m_result_sel_shift_m <= m_result_sel_shift_x; - if (exception_x == 1'b1) + if (t[32] == 1'b0) begin - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; + p <= t[31:0]; + a <= {a[ 32-2:0], 1'b1}; end - else + else begin - w_result_sel_load_m <= w_result_sel_load_x; - w_result_sel_mul_m <= w_result_sel_mul_x; + p <= {p[ 32-2:0], a[ 32-1]}; + a <= {a[ 32-2:0], 1'b0}; end - m_bypass_enable_m <= m_bypass_enable_x; - load_m <= load_x; - store_m <= store_x; - branch_m <= branch_x && !branch_taken_x; - if (non_debug_exception_x == 1'b1) - write_idx_m <= 5'd30; - else if (debug_exception_x == 1'b1) - write_idx_m <= 5'd31; - else - write_idx_m <= write_idx_x; - condition_met_m <= condition_met_x; - if (exception_x == 1'b1) - if ((dc_re == 1'b1) - || ((debug_exception_x == 1'b1) - && (non_debug_exception_x == 1'b0))) - branch_target_m <= {deba, eid_x, {3{1'b0}}}; - else - branch_target_m <= {eba, eid_x, {3{1'b0}}}; - else - branch_target_m <= branch_target_x; - dflush_m <= dflush_x; - write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; - debug_exception_m <= debug_exception_x; - non_debug_exception_m <= non_debug_exception_x; + result_x <= a; + if ((cycles == 32'd0) || (kill_x == 1'b1)) + begin + + divide_by_zero_x <= b == { 32{1'b0}}; + state <= 3'b000; + end + cycles <= cycles - 1'b1; end - if (stall_m == 1'b0) + 3'b010 : begin - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - exception_m <= 1'b1; + if (t[32] == 1'b0) + begin + p <= t[31:0]; + a <= {a[ 32-2:0], 1'b1}; + end else - exception_m <= 1'b0; - data_bus_error_exception_m <= (data_bus_error_exception == 1'b1) - && (reset_exception == 1'b0) - ; - end - operand_w <= exception_m == 1'b1 ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result; - w_result_sel_load_w <= w_result_sel_load_m; - w_result_sel_mul_w <= w_result_sel_mul_m; - write_idx_w <= write_idx_m; - write_enable_w <= write_enable_m; - debug_exception_w <= debug_exception_m; - non_debug_exception_w <= non_debug_exception_m; - if ( (stall_m == 1'b0) - && ( (load_q_m == 1'b1) - || (store_q_m == 1'b1) - ) - ) - memop_pc_w <= pc_m; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - use_buf <= 1'b0; - reg_data_buf_0 <= { 32{1'b0}}; - reg_data_buf_1 <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) - use_buf <= 1'b0; - else if (use_buf == 1'b0) - begin - reg_data_buf_0 <= reg_data_live_0; - reg_data_buf_1 <= reg_data_live_1; - use_buf <= 1'b1; - end - if (reg_write_enable_q_w == 1'b1) - begin - if (write_idx_w == read_idx_0_d) - reg_data_buf_0 <= w_result; - if (write_idx_w == read_idx_1_d) - reg_data_buf_1 <= w_result; + begin + p <= {p[ 32-2:0], a[ 32-1]}; + a <= {a[ 32-2:0], 1'b0}; + end + result_x <= p; + if ((cycles == 32'd0) || (kill_x == 1'b1)) + begin + + divide_by_zero_x <= b == { 32{1'b0}}; + state <= 3'b000; + end + cycles <= cycles - 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end -end -initial -begin -end -endmodule -module lm32_load_store_unit_full_debug ( +end + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_full ( + clk_i, + + + + rst_i, - stall_a, - stall_x, - stall_m, - kill_x, - kill_m, - exception_m, - store_operand_x, - load_store_address_x, - load_store_address_m, - load_store_address_w, - load_x, - store_x, - load_q_x, - store_q_x, - load_q_m, - store_q_m, - sign_extend_x, - size_x, - dflush, - d_dat_i, - d_ack_i, - d_err_i, - d_rty_i, - dcache_refill_request, - dcache_restart_request, - dcache_stall_request, - dcache_refilling, - load_data_w, - stall_wb_load, - d_dat_o, - d_adr_o, - d_cyc_o, - d_sel_o, - d_stb_o, - d_we_o, - d_cti_o, - d_lock_o, - d_bte_o - ); -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_x; -input stall_m; -input kill_x; -input kill_m; -input exception_m; -input [ (32-1):0] store_operand_x; -input [ (32-1):0] load_store_address_x; -input [ (32-1):0] load_store_address_m; -input [1:0] load_store_address_w; -input load_x; -input store_x; -input load_q_x; -input store_q_x; -input load_q_m; -input store_q_m; -input sign_extend_x; -input [ 1:0] size_x; -input dflush; -input [ (32-1):0] d_dat_i; -input d_ack_i; -input d_err_i; -input d_rty_i; -output dcache_refill_request; -wire dcache_refill_request; -output dcache_restart_request; -wire dcache_restart_request; -output dcache_stall_request; -wire dcache_stall_request; -output dcache_refilling; -wire dcache_refilling; -output [ (32-1):0] load_data_w; -reg [ (32-1):0] load_data_w; -output stall_wb_load; -reg stall_wb_load; -output [ (32-1):0] d_dat_o; -reg [ (32-1):0] d_dat_o; -output [ (32-1):0] d_adr_o; -reg [ (32-1):0] d_adr_o; -output d_cyc_o; -reg d_cyc_o; -output [ (4-1):0] d_sel_o; -reg [ (4-1):0] d_sel_o; -output d_stb_o; -reg d_stb_o; -output d_we_o; -reg d_we_o; -output [ (3-1):0] d_cti_o; -reg [ (3-1):0] d_cti_o; -output d_lock_o; -reg d_lock_o; -output [ (2-1):0] d_bte_o; -wire [ (2-1):0] d_bte_o; -reg [ 1:0] size_m; -reg [ 1:0] size_w; -reg sign_extend_m; -reg sign_extend_w; -reg [ (32-1):0] store_data_x; -reg [ (32-1):0] store_data_m; -reg [ (4-1):0] byte_enable_x; -reg [ (4-1):0] byte_enable_m; -wire [ (32-1):0] data_m; -reg [ (32-1):0] data_w; -wire dcache_select_x; -reg dcache_select_m; -wire [ (32-1):0] dcache_data_m; -wire [ (32-1):0] dcache_refill_address; -reg dcache_refill_ready; -wire [ (3-1):0] first_cycle_type; -wire [ (3-1):0] next_cycle_type; -wire last_word; -wire [ (32-1):0] first_address; -wire wb_select_x; -reg wb_select_m; -reg [ (32-1):0] wb_data_m; -reg wb_load_complete; -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; -begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction -lm32_dcache_full_debug #( - .associativity (associativity), - .sets (sets), - .bytes_per_line (bytes_per_line), - .base_address (base_address), - .limit (limit) - ) dcache ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_x (stall_x), - .stall_m (stall_m), - .address_x (load_store_address_x), - .address_m (load_store_address_m), - .load_q_m (load_q_m & dcache_select_m), - .store_q_m (store_q_m & dcache_select_m), - .store_data (store_data_m), - .store_byte_select (byte_enable_m & {4{dcache_select_m}}), - .refill_ready (dcache_refill_ready), - .refill_data (wb_data_m), - .dflush (dflush), - .stall_request (dcache_stall_request), - .restart_request (dcache_restart_request), - .refill_request (dcache_refill_request), - .refill_address (dcache_refill_address), - .refilling (dcache_refilling), - .load_data (dcache_data_m) + + + + interrupt, + + + + + + + + + + + + + + + + + + + + I_DAT_I, + I_ACK_I, + I_ERR_I, + I_RTY_I, + + + + D_DAT_I, + D_ACK_I, + D_ERR_I, + D_RTY_I, + + + + + + + + + + + + + + + + + + + + + + + + + + + + I_DAT_O, + I_ADR_O, + I_CYC_O, + I_SEL_O, + I_STB_O, + I_WE_O, + I_CTI_O, + I_LOCK_O, + I_BTE_O, + + + + + + + + + + + + + + + + + + D_DAT_O, + D_ADR_O, + D_CYC_O, + D_SEL_O, + D_STB_O, + D_WE_O, + D_CTI_O, + D_LOCK_O, + D_BTE_O + + ); - assign dcache_select_x = (load_store_address_x >= 32'h0) - && (load_store_address_x <= 32'h7fffffff) - ; - assign wb_select_x = 1'b1 - && !dcache_select_x - ; -always @(*) -begin - case (size_x) - 2'b00: store_data_x = {4{store_operand_x[7:0]}}; - 2'b11: store_data_x = {2{store_operand_x[15:0]}}; - 2'b10: store_data_x = store_operand_x; - default: store_data_x = { 32{1'bx}}; - endcase -end -always @(*) -begin - casez ({size_x, load_store_address_x[1:0]}) - { 2'b00, 2'b11}: byte_enable_x = 4'b0001; - { 2'b00, 2'b10}: byte_enable_x = 4'b0010; - { 2'b00, 2'b01}: byte_enable_x = 4'b0100; - { 2'b00, 2'b00}: byte_enable_x = 4'b1000; - { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; - { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; - { 2'b10, 2'b??}: byte_enable_x = 4'b1111; - default: byte_enable_x = 4'bxxxx; - endcase -end - assign data_m = wb_select_m == 1'b1 - ? wb_data_m - : dcache_data_m; -always @(*) -begin - casez ({size_w, load_store_address_w[1:0]}) - { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; - { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; - { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; - { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; - { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; - { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; - { 2'b10, 2'b??}: load_data_w = data_w; - default: load_data_w = { 32{1'bx}}; - endcase -end -assign d_bte_o = 2'b00; -generate - case (bytes_per_line) - 4: - begin -assign first_cycle_type = 3'b111; -assign next_cycle_type = 3'b111; -assign last_word = 1'b1; -assign first_address = {dcache_refill_address[ 32-1:2], 2'b00}; - end - 8: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = 3'b111; -assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1; -assign first_address = {dcache_refill_address[ 32-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00}; - end - 16: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = d_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; -assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1; -assign first_address = {dcache_refill_address[ 32-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00}; - end - endcase -endgenerate -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_dat_o <= { 32{1'b0}}; - d_adr_o <= { 32{1'b0}}; - d_sel_o <= { 4{ 1'b0}}; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; - d_lock_o <= 1'b0; - wb_data_m <= { 32{1'b0}}; - wb_load_complete <= 1'b0; - stall_wb_load <= 1'b0; - dcache_refill_ready <= 1'b0; - end - else - begin - dcache_refill_ready <= 1'b0; - if (d_cyc_o == 1'b1) - begin - if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) - begin - if ((dcache_refilling == 1'b1) && (!last_word)) - begin - d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - end - else - begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_lock_o <= 1'b0; - end - d_cti_o <= next_cycle_type; - dcache_refill_ready <= dcache_refilling; - wb_data_m <= d_dat_i; - wb_load_complete <= !d_we_o; - end - if (d_err_i == 1'b1) - $display ("Data bus error. Address: %x", d_adr_o); - end - else - begin - if (dcache_refill_request == 1'b1) - begin - d_adr_o <= first_address; - d_cyc_o <= 1'b1; - d_sel_o <= { 32/8{ 1'b1}}; - d_stb_o <= 1'b1; - d_we_o <= 1'b0; - d_cti_o <= first_cycle_type; - end - else - if ( (store_q_m == 1'b1) - && (stall_m == 1'b0) - ) - begin - d_dat_o <= store_data_m; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b1; - d_cti_o <= 3'b111; - end - else if ( (load_q_m == 1'b1) - && (wb_select_m == 1'b1) - && (wb_load_complete == 1'b0) - ) - begin - stall_wb_load <= 1'b0; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; - end - end - if (stall_m == 1'b0) - wb_load_complete <= 1'b0; - if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) - stall_wb_load <= 1'b1; - if ((kill_m == 1'b1) || (exception_m == 1'b1)) - stall_wb_load <= 1'b0; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - sign_extend_m <= 1'b0; - size_m <= 2'b00; - byte_enable_m <= 1'b0; - store_data_m <= { 32{1'b0}}; - dcache_select_m <= 1'b0; - wb_select_m <= 1'b0; - end - else - begin - if (stall_m == 1'b0) - begin - sign_extend_m <= sign_extend_x; - size_m <= size_x; - byte_enable_m <= byte_enable_x; - store_data_m <= store_data_x; - dcache_select_m <= dcache_select_x; - wb_select_m <= wb_select_x; - end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - size_w <= 2'b00; - data_w <= { 32{1'b0}}; - sign_extend_w <= 1'b0; - end - else - begin - size_w <= size_m; - data_w <= data_m; - sign_extend_w <= sign_extend_m; - end -end -always @(posedge clk_i) -begin - if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) - begin - if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) - $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); - if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) - $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); - end -end -endmodule -module lm32_decoder_full_debug ( - instruction, - d_result_sel_0, - d_result_sel_1, - x_result_sel_csr, - x_result_sel_mc_arith, - x_result_sel_sext, - x_result_sel_logic, - x_result_sel_add, - m_result_sel_compare, - m_result_sel_shift, - w_result_sel_load, - w_result_sel_mul, - x_bypass_enable, - m_bypass_enable, - read_enable_0, - read_idx_0, - read_enable_1, - read_idx_1, - write_enable, - write_idx, - immediate, - branch_offset, - load, - store, - size, - sign_extend, - adder_op, - logic_op, - direction, - divide, - modulus, - branch, - branch_reg, - condition, - bi_conditional, - bi_unconditional, - break_opcode, - scall, - eret, - bret, - csr_write_enable - ); -input [ (32-1):0] instruction; -output [ 0:0] d_result_sel_0; -reg [ 0:0] d_result_sel_0; -output [ 1:0] d_result_sel_1; -reg [ 1:0] d_result_sel_1; -output x_result_sel_csr; -reg x_result_sel_csr; -output x_result_sel_mc_arith; -reg x_result_sel_mc_arith; -output x_result_sel_sext; -reg x_result_sel_sext; -output x_result_sel_logic; -reg x_result_sel_logic; -output x_result_sel_add; -reg x_result_sel_add; -output m_result_sel_compare; -reg m_result_sel_compare; -output m_result_sel_shift; -reg m_result_sel_shift; -output w_result_sel_load; -reg w_result_sel_load; -output w_result_sel_mul; -reg w_result_sel_mul; -output x_bypass_enable; -wire x_bypass_enable; -output m_bypass_enable; -wire m_bypass_enable; -output read_enable_0; -wire read_enable_0; -output [ (5-1):0] read_idx_0; -wire [ (5-1):0] read_idx_0; -output read_enable_1; -wire read_enable_1; -output [ (5-1):0] read_idx_1; -wire [ (5-1):0] read_idx_1; -output write_enable; -wire write_enable; -output [ (5-1):0] write_idx; -wire [ (5-1):0] write_idx; -output [ (32-1):0] immediate; -wire [ (32-1):0] immediate; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; -output load; -wire load; -output store; -wire store; -output [ 1:0] size; -wire [ 1:0] size; -output sign_extend; -wire sign_extend; -output adder_op; -wire adder_op; -output [ 3:0] logic_op; -wire [ 3:0] logic_op; -output direction; -wire direction; -output divide; -wire divide; -output modulus; -wire modulus; -output branch; -wire branch; -output branch_reg; -wire branch_reg; -output [ (3-1):0] condition; -wire [ (3-1):0] condition; -output bi_conditional; -wire bi_conditional; -output bi_unconditional; + + + + + +parameter eba_reset = 32'h00000000; + + + + +parameter sdb_address = 32'h00000000; + + + +parameter icache_associativity = 1; +parameter icache_sets = 256; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 32'h0; +parameter icache_limit = 32'h7fffffff; + + + + + + + + + + + +parameter dcache_associativity = 1; +parameter dcache_sets = 256; +parameter dcache_bytes_per_line = 16; +parameter dcache_base_address = 32'h0; +parameter dcache_limit = 32'h7fffffff; + + + + + + + + + + + + + +parameter watchpoints = 0; + + + + + + +parameter breakpoints = 0; + + + + + +parameter interrupts = 32; + + + + + + + + + +input clk_i; + + + + +input rst_i; + + + +input [ (32-1):0] interrupt; + + + + + + + + + + + + + + + + + + + +input [ (32-1):0] I_DAT_I; +input I_ACK_I; +input I_ERR_I; +input I_RTY_I; + + + +input [ (32-1):0] D_DAT_I; +input D_ACK_I; +input D_ERR_I; +input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +output [ (32-1):0] I_DAT_O; +wire [ (32-1):0] I_DAT_O; +output [ (32-1):0] I_ADR_O; +wire [ (32-1):0] I_ADR_O; +output I_CYC_O; +wire I_CYC_O; +output [ (4-1):0] I_SEL_O; +wire [ (4-1):0] I_SEL_O; +output I_STB_O; +wire I_STB_O; +output I_WE_O; +wire I_WE_O; +output [ (3-1):0] I_CTI_O; +wire [ (3-1):0] I_CTI_O; +output I_LOCK_O; +wire I_LOCK_O; +output [ (2-1):0] I_BTE_O; +wire [ (2-1):0] I_BTE_O; + + + +output [ (32-1):0] D_DAT_O; +wire [ (32-1):0] D_DAT_O; +output [ (32-1):0] D_ADR_O; +wire [ (32-1):0] D_ADR_O; +output D_CYC_O; +wire D_CYC_O; +output [ (4-1):0] D_SEL_O; +wire [ (4-1):0] D_SEL_O; +output D_STB_O; +wire D_STB_O; +output D_WE_O; +wire D_WE_O; +output [ (3-1):0] D_CTI_O; +wire [ (3-1):0] D_CTI_O; +output D_LOCK_O; +wire D_LOCK_O; +output [ (2-1):0] D_BTE_O; +wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + +reg valid_a; + + +reg valid_f; +reg valid_d; +reg valid_x; +reg valid_m; +reg valid_w; + +wire q_x; +wire [ (32-1):0] immediate_d; +wire load_d; +reg load_x; +reg load_m; +wire load_q_x; +wire store_q_x; +wire q_m; +wire load_q_m; +wire store_q_m; +wire store_d; +reg store_x; +reg store_m; +wire [ 1:0] size_d; +reg [ 1:0] size_x; +wire branch_d; +wire branch_predict_d; +wire branch_predict_taken_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; wire bi_unconditional; -output break_opcode; -wire break_opcode; -output scall; -wire scall; -output eret; -wire eret; -output bret; -wire bret; -output csr_write_enable; -wire csr_write_enable; -wire [ (32-1):0] extended_immediate; -wire [ (32-1):0] high_immediate; -wire [ (32-1):0] call_immediate; -wire [ (32-1):0] branch_immediate; -wire sign_extend_immediate; -wire select_high_immediate; -wire select_call_immediate; -wire op_add; -wire op_and; -wire op_andhi; -wire op_b; -wire op_bi; -wire op_be; -wire op_bg; -wire op_bge; -wire op_bgeu; -wire op_bgu; -wire op_bne; -wire op_call; -wire op_calli; -wire op_cmpe; -wire op_cmpg; -wire op_cmpge; -wire op_cmpgeu; -wire op_cmpgu; -wire op_cmpne; -wire op_divu; -wire op_lb; -wire op_lbu; -wire op_lh; -wire op_lhu; -wire op_lw; -wire op_modu; -wire op_mul; -wire op_nor; -wire op_or; -wire op_orhi; -wire op_raise; -wire op_rcsr; -wire op_sb; -wire op_sextb; -wire op_sexth; -wire op_sh; -wire op_sl; -wire op_sr; -wire op_sru; -wire op_sub; -wire op_sw; -wire op_wcsr; -wire op_xnor; -wire op_xor; -wire arith; -wire logical; -wire cmp; -wire bra; -wire call; -wire shift; -wire sext; +wire bi_conditional; +reg branch_x; +reg branch_predict_x; +reg branch_predict_taken_x; +reg branch_m; +reg branch_predict_m; +reg branch_predict_taken_m; +wire branch_mispredict_taken_m; +wire branch_flushX_m; +wire branch_reg_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; +wire [ 0:0] d_result_sel_0_d; +wire [ 1:0] d_result_sel_1_d; + +wire x_result_sel_csr_d; +reg x_result_sel_csr_x; + + +wire q_d; +wire x_result_sel_mc_arith_d; +reg x_result_sel_mc_arith_x; + + + + + + + + + +wire x_result_sel_sext_d; +reg x_result_sel_sext_x; + + +wire x_result_sel_logic_d; + + + + + +wire x_result_sel_add_d; +reg x_result_sel_add_x; +wire m_result_sel_compare_d; +reg m_result_sel_compare_x; +reg m_result_sel_compare_m; + + +wire m_result_sel_shift_d; +reg m_result_sel_shift_x; +reg m_result_sel_shift_m; + + +wire w_result_sel_load_d; +reg w_result_sel_load_x; +reg w_result_sel_load_m; +reg w_result_sel_load_w; + + +wire w_result_sel_mul_d; +reg w_result_sel_mul_x; +reg w_result_sel_mul_m; +reg w_result_sel_mul_w; + + +wire x_bypass_enable_d; +reg x_bypass_enable_x; +wire m_bypass_enable_d; +reg m_bypass_enable_x; +reg m_bypass_enable_m; +wire sign_extend_d; +reg sign_extend_x; +wire write_enable_d; +reg write_enable_x; +wire write_enable_q_x; +reg write_enable_m; +wire write_enable_q_m; +reg write_enable_w; +wire write_enable_q_w; +wire read_enable_0_d; +wire [ (5-1):0] read_idx_0_d; +wire read_enable_1_d; +wire [ (5-1):0] read_idx_1_d; +wire [ (5-1):0] write_idx_d; +reg [ (5-1):0] write_idx_x; +reg [ (5-1):0] write_idx_m; +reg [ (5-1):0] write_idx_w; +wire [ (4 -1):0] csr_d; +reg [ (4 -1):0] csr_x; +wire [ (3-1):0] condition_d; +reg [ (3-1):0] condition_x; + + + + + +wire scall_d; +reg scall_x; +wire eret_d; +reg eret_x; +wire eret_q_x; + + + + + + + + + + + + + + + +wire csr_write_enable_d; +reg csr_write_enable_x; +wire csr_write_enable_q_x; + + + + + + + +wire bus_error_d; +reg bus_error_x; +reg data_bus_error_exception_m; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] memop_pc_w; + + + +reg [ (32-1):0] d_result_0; +reg [ (32-1):0] d_result_1; +reg [ (32-1):0] x_result; +reg [ (32-1):0] m_result; +reg [ (32-1):0] w_result; + +reg [ (32-1):0] operand_0_x; +reg [ (32-1):0] operand_1_x; +reg [ (32-1):0] store_operand_x; +reg [ (32-1):0] operand_m; +reg [ (32-1):0] operand_w; + + + + +reg [ (32-1):0] reg_data_live_0; +reg [ (32-1):0] reg_data_live_1; +reg use_buf; +reg [ (32-1):0] reg_data_buf_0; +reg [ (32-1):0] reg_data_buf_1; + + + + + + + + +wire [ (32-1):0] reg_data_0; +wire [ (32-1):0] reg_data_1; +reg [ (32-1):0] bypass_data_0; +reg [ (32-1):0] bypass_data_1; +wire reg_write_enable_q_w; + +reg interlock; + +wire stall_a; +wire stall_f; +wire stall_d; +wire stall_x; +wire stall_m; + + +wire adder_op_d; +reg adder_op_x; +reg adder_op_x_n; +wire [ (32-1):0] adder_result_x; +wire adder_overflow_x; +wire adder_carry_n_x; + + +wire [ 3:0] logic_op_d; +reg [ 3:0] logic_op_x; +wire [ (32-1):0] logic_result_x; + + + + +wire [ (32-1):0] sextb_result_x; +wire [ (32-1):0] sexth_result_x; +wire [ (32-1):0] sext_result_x; + + + + + + + + + + + +wire direction_d; +reg direction_x; +wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + +wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + +wire divide_d; +wire divide_q_d; +wire modulus_d; +wire modulus_q_d; +wire divide_by_zero_x; + + + + + + +wire mc_stall_request_x; +wire [ (32-1):0] mc_result_x; + + + + + + +wire [ (32-1):0] interrupt_csr_read_data_x; + + +wire [ (32-1):0] cfg; +wire [ (32-1):0] cfg2; + + + + +reg [ (32-1):0] csr_read_data_x; + + +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + + + + +wire [ (32-1):0] instruction_f; + + + + +wire [ (32-1):0] instruction_d; + + +wire iflush; +wire icache_stall_request; +wire icache_restart_request; +wire icache_refill_request; +wire icache_refilling; + + + + + + +wire dflush_x; +reg dflush_m; +wire dcache_stall_request; +wire dcache_restart_request; +wire dcache_refill_request; +wire dcache_refilling; + + +wire [ (32-1):0] load_data_w; +wire stall_wb_load; + + + + + + + + + + + + + + + + + + + + + + + + + +wire raw_x_0; +wire raw_x_1; +wire raw_m_0; +wire raw_m_1; +wire raw_w_0; +wire raw_w_1; + + +wire cmp_zero; +wire cmp_negative; +wire cmp_overflow; +wire cmp_carry_n; +reg condition_met_x; +reg condition_met_m; + + +wire branch_taken_x; + + +wire branch_taken_m; + +wire kill_f; +wire kill_d; +wire kill_x; +wire kill_m; +wire kill_w; + +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + + + + +reg [ (3-1):0] eid_x; + + + + + + + + + + + + + + + + + + + + + + + + + +wire exception_x; +reg exception_m; +reg exception_w; +wire exception_q_w; + + + + + + + + + + + +wire interrupt_exception; + + + + + + + + + +wire instruction_bus_error_exception; +wire data_bus_error_exception; + + + + +wire divide_by_zero_exception; + + +wire system_call_exception; + + + +reg data_bus_error_seen; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -5452,6 +15818,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -5464,855 +15831,2970 @@ begin clogb2_v1 = i-1; end endfunction -assign op_add = instruction[ 30:26] == 5'b01101; -assign op_and = instruction[ 30:26] == 5'b01000; -assign op_andhi = instruction[ 31:26] == 6'b011000; -assign op_b = instruction[ 31:26] == 6'b110000; -assign op_bi = instruction[ 31:26] == 6'b111000; -assign op_be = instruction[ 31:26] == 6'b010001; -assign op_bg = instruction[ 31:26] == 6'b010010; -assign op_bge = instruction[ 31:26] == 6'b010011; -assign op_bgeu = instruction[ 31:26] == 6'b010100; -assign op_bgu = instruction[ 31:26] == 6'b010101; -assign op_bne = instruction[ 31:26] == 6'b010111; -assign op_call = instruction[ 31:26] == 6'b110110; -assign op_calli = instruction[ 31:26] == 6'b111110; -assign op_cmpe = instruction[ 30:26] == 5'b11001; -assign op_cmpg = instruction[ 30:26] == 5'b11010; -assign op_cmpge = instruction[ 30:26] == 5'b11011; -assign op_cmpgeu = instruction[ 30:26] == 5'b11100; -assign op_cmpgu = instruction[ 30:26] == 5'b11101; -assign op_cmpne = instruction[ 30:26] == 5'b11111; -assign op_divu = instruction[ 31:26] == 6'b100011; -assign op_lb = instruction[ 31:26] == 6'b000100; -assign op_lbu = instruction[ 31:26] == 6'b010000; -assign op_lh = instruction[ 31:26] == 6'b000111; -assign op_lhu = instruction[ 31:26] == 6'b001011; -assign op_lw = instruction[ 31:26] == 6'b001010; -assign op_modu = instruction[ 31:26] == 6'b110001; -assign op_mul = instruction[ 30:26] == 5'b00010; -assign op_nor = instruction[ 30:26] == 5'b00001; -assign op_or = instruction[ 30:26] == 5'b01110; -assign op_orhi = instruction[ 31:26] == 6'b011110; -assign op_raise = instruction[ 31:26] == 6'b101011; -assign op_rcsr = instruction[ 31:26] == 6'b100100; -assign op_sb = instruction[ 31:26] == 6'b001100; -assign op_sextb = instruction[ 31:26] == 6'b101100; -assign op_sexth = instruction[ 31:26] == 6'b110111; -assign op_sh = instruction[ 31:26] == 6'b000011; -assign op_sl = instruction[ 30:26] == 5'b01111; -assign op_sr = instruction[ 30:26] == 5'b00101; -assign op_sru = instruction[ 30:26] == 5'b00000; -assign op_sub = instruction[ 31:26] == 6'b110010; -assign op_sw = instruction[ 31:26] == 6'b010110; -assign op_wcsr = instruction[ 31:26] == 6'b110100; -assign op_xnor = instruction[ 30:26] == 5'b01001; -assign op_xor = instruction[ 30:26] == 5'b00110; -assign arith = op_add | op_sub; -assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; -assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; -assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; -assign bi_unconditional = op_bi; -assign bra = op_b | bi_unconditional | bi_conditional; -assign call = op_call | op_calli; -assign shift = op_sl | op_sr | op_sru; -assign sext = op_sextb | op_sexth; -assign divide = op_divu; -assign modulus = op_modu; -assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; -assign store = op_sb | op_sh | op_sw; -always @(*) -begin - if (call) - d_result_sel_0 = 1'b1; - else - d_result_sel_0 = 1'b0; - if (call) - d_result_sel_1 = 2'b00; - else if ((instruction[31] == 1'b0) && !bra) - d_result_sel_1 = 2'b10; - else - d_result_sel_1 = 2'b01; - x_result_sel_csr = 1'b0; - x_result_sel_mc_arith = 1'b0; - x_result_sel_sext = 1'b0; - x_result_sel_logic = 1'b0; - x_result_sel_add = 1'b0; - if (op_rcsr) - x_result_sel_csr = 1'b1; - else if (divide | modulus) - x_result_sel_mc_arith = 1'b1; - else if (sext) - x_result_sel_sext = 1'b1; - else if (logical) - x_result_sel_logic = 1'b1; - else - x_result_sel_add = 1'b1; - m_result_sel_compare = cmp; - m_result_sel_shift = shift; - w_result_sel_load = load; - w_result_sel_mul = op_mul; -end -assign x_bypass_enable = arith - | logical - | divide - | modulus - | sext - | op_rcsr - ; -assign m_bypass_enable = x_bypass_enable - | shift - | cmp - ; -assign read_enable_0 = ~(op_bi | op_calli); -assign read_idx_0 = instruction[25:21]; -assign read_enable_1 = ~(op_bi | op_calli | load); -assign read_idx_1 = instruction[20:16]; -assign write_enable = ~(bra | op_raise | store | op_wcsr); -assign write_idx = call - ? 5'd29 - : instruction[31] == 1'b0 - ? instruction[20:16] - : instruction[15:11]; -assign size = instruction[27:26]; -assign sign_extend = instruction[28]; -assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; -assign logic_op = instruction[29:26]; -assign direction = instruction[29]; -assign branch = bra | call; -assign branch_reg = op_call | op_b; -assign condition = instruction[28:26]; -assign break_opcode = op_raise & ~instruction[2]; -assign scall = op_raise & instruction[2]; -assign eret = op_b & (instruction[25:21] == 5'd30); -assign bret = op_b & (instruction[25:21] == 5'd31); -assign csr_write_enable = op_wcsr; -assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); -assign select_high_immediate = op_andhi | op_orhi; -assign select_call_immediate = instruction[31]; -assign high_immediate = {instruction[15:0], 16'h0000}; -assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; -assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; -assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; -assign immediate = select_high_immediate == 1'b1 - ? high_immediate - : extended_immediate; -assign branch_offset = select_call_immediate == 1'b1 - ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) - : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); -endmodule -module lm32_icache_full_debug ( - clk_i, - rst_i, - stall_a, - stall_f, - address_a, - address_f, - read_enable_f, - refill_ready, - refill_data, - iflush, - valid_d, - branch_predict_taken_d, - stall_request, - restart_request, - refill_request, - refill_address, - refilling, - inst + + + + + + + + + +lm32_instruction_unit_full #( + .eba_reset (eba_reset), + .associativity (icache_associativity), + .sets (icache_sets), + .bytes_per_line (icache_bytes_per_line), + .base_address (icache_base_address), + .limit (icache_limit) + ) instruction_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_f (stall_f), + .stall_d (stall_d), + .stall_x (stall_x), + .stall_m (stall_m), + .valid_f (valid_f), + .valid_d (valid_d), + .kill_f (kill_f), + .branch_predict_taken_d (branch_predict_taken_d), + .branch_predict_address_d (branch_predict_address_d), + + + .branch_taken_x (branch_taken_x), + .branch_target_x (branch_target_x), + + + .exception_m (exception_m), + .branch_taken_m (branch_taken_m), + .branch_mispredict_taken_m (branch_mispredict_taken_m), + .branch_target_m (branch_target_m), + + + .iflush (iflush), + + + + + .dcache_restart_request (dcache_restart_request), + .dcache_refill_request (dcache_refill_request), + .dcache_refilling (dcache_refilling), + + + + + + .i_dat_i (I_DAT_I), + .i_ack_i (I_ACK_I), + .i_err_i (I_ERR_I), + .i_rty_i (I_RTY_I), + + + + + + + + + + + + .pc_f (pc_f), + .pc_d (pc_d), + .pc_x (pc_x), + .pc_m (pc_m), + .pc_w (pc_w), + + + .icache_stall_request (icache_stall_request), + .icache_restart_request (icache_restart_request), + .icache_refill_request (icache_refill_request), + .icache_refilling (icache_refilling), + + + + + + .i_dat_o (I_DAT_O), + .i_adr_o (I_ADR_O), + .i_cyc_o (I_CYC_O), + .i_sel_o (I_SEL_O), + .i_stb_o (I_STB_O), + .i_we_o (I_WE_O), + .i_cti_o (I_CTI_O), + .i_lock_o (I_LOCK_O), + .i_bte_o (I_BTE_O), + + + + + + + + + + + + + + + + + + .bus_error_d (bus_error_d), + + + + + .instruction_f (instruction_f), + + + + + .instruction_d (instruction_d) + + + + ); + + +lm32_decoder_full decoder ( + + .instruction (instruction_d), + + .d_result_sel_0 (d_result_sel_0_d), + .d_result_sel_1 (d_result_sel_1_d), + .x_result_sel_csr (x_result_sel_csr_d), + + + .x_result_sel_mc_arith (x_result_sel_mc_arith_d), + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + + .x_result_sel_logic (x_result_sel_logic_d), + + + + + .x_result_sel_add (x_result_sel_add_d), + .m_result_sel_compare (m_result_sel_compare_d), + + + .m_result_sel_shift (m_result_sel_shift_d), + + + .w_result_sel_load (w_result_sel_load_d), + + + .w_result_sel_mul (w_result_sel_mul_d), + + + .x_bypass_enable (x_bypass_enable_d), + .m_bypass_enable (m_bypass_enable_d), + .read_enable_0 (read_enable_0_d), + .read_idx_0 (read_idx_0_d), + .read_enable_1 (read_enable_1_d), + .read_idx_1 (read_idx_1_d), + .write_enable (write_enable_d), + .write_idx (write_idx_d), + .immediate (immediate_d), + .branch_offset (branch_offset_d), + .load (load_d), + .store (store_d), + .size (size_d), + .sign_extend (sign_extend_d), + .adder_op (adder_op_d), + .logic_op (logic_op_d), + + + .direction (direction_d), + + + + + + + + + + + + + + .divide (divide_d), + .modulus (modulus_d), + + + .branch (branch_d), + .bi_unconditional (bi_unconditional), + .bi_conditional (bi_conditional), + .branch_reg (branch_reg_d), + .condition (condition_d), + + + + + .scall (scall_d), + .eret (eret_d), + + + + + + + + + .csr_write_enable (csr_write_enable_d) + ); + + +lm32_load_store_unit_full #( + .associativity (dcache_associativity), + .sets (dcache_sets), + .bytes_per_line (dcache_bytes_per_line), + .base_address (dcache_base_address), + .limit (dcache_limit) + ) load_store_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_x (stall_x), + .stall_m (stall_m), + .kill_x (kill_x), + .kill_m (kill_m), + .exception_m (exception_m), + .store_operand_x (store_operand_x), + .load_store_address_x (adder_result_x), + .load_store_address_m (operand_m), + .load_store_address_w (operand_w[1:0]), + .load_x (load_x), + .store_x (store_x), + .load_q_x (load_q_x), + .store_q_x (store_q_x), + .load_q_m (load_q_m), + .store_q_m (store_q_m), + .sign_extend_x (sign_extend_x), + .size_x (size_x), + + + .dflush (dflush_m), + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), + .d_ack_i (D_ACK_I), + .d_err_i (D_ERR_I), + .d_rty_i (D_RTY_I), + + + + + .dcache_refill_request (dcache_refill_request), + .dcache_restart_request (dcache_restart_request), + .dcache_stall_request (dcache_stall_request), + .dcache_refilling (dcache_refilling), + + + .load_data_w (load_data_w), + .stall_wb_load (stall_wb_load), + + .d_dat_o (D_DAT_O), + .d_adr_o (D_ADR_O), + .d_cyc_o (D_CYC_O), + .d_sel_o (D_SEL_O), + .d_stb_o (D_STB_O), + .d_we_o (D_WE_O), + .d_cti_o (D_CTI_O), + .d_lock_o (D_LOCK_O), + .d_bte_o (D_BTE_O) + ); + + +lm32_adder adder ( + + .adder_op_x (adder_op_x), + .adder_op_x_n (adder_op_x_n), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .adder_result_x (adder_result_x), + .adder_carry_n_x (adder_carry_n_x), + .adder_overflow_x (adder_overflow_x) ); -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam addr_offset_width = clogb2(bytes_per_line)-1-2; -localparam addr_set_width = clogb2(sets)-1; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -localparam addr_set_lsb = (addr_offset_msb+1); -localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); -localparam addr_tag_lsb = (addr_set_msb+1); -localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; -localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); -input clk_i; -input rst_i; -input stall_a; -input stall_f; -input valid_d; -input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; -input read_enable_f; -input refill_ready; -input [ (32-1):0] refill_data; -input iflush; -output stall_request; -wire stall_request; -output restart_request; -reg restart_request; -output refill_request; -wire refill_request; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -output refilling; -reg refilling; -output [ (32-1):0] inst; -wire [ (32-1):0] inst; -wire enable; -wire [0:associativity-1] way_mem_we; -wire [ (32-1):0] way_data[0:associativity-1]; -wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; -wire [0:associativity-1] way_valid; -wire [0:associativity-1] way_match; -wire miss; -wire [ (addr_set_width-1):0] tmem_read_address; -wire [ (addr_set_width-1):0] tmem_write_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; -wire [ ((addr_tag_width+1)-1):0] tmem_write_data; -reg [ 3:0] state; -wire flushing; -wire check; -wire refill; -reg [associativity-1:0] refill_way_select; -reg [ addr_offset_msb:addr_offset_lsb] refill_offset; -wire last_refill; -reg [ (addr_set_width-1):0] flush_set; -genvar i; -function integer clogb2; -input [31:0] value; -begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; -end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + +lm32_logic_op logic_op ( + + .logic_op_x (logic_op_x), + .operand_0_x (operand_0_x), + + .operand_1_x (operand_1_x), + + .logic_result_x (logic_result_x) + ); + + + + +lm32_shifter shifter ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .direction_x (direction_x), + .sign_extend_x (sign_extend_x), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .shifter_result_m (shifter_result_m) + ); + + + + + + +lm32_multiplier multiplier ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .stall_m (stall_m), + .operand_0 (d_result_0), + .operand_1 (d_result_1), + + .result (multiplier_result_w) + ); + + + + + + +lm32_mc_arithmetic_full mc_arithmetic ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_d (stall_d), + .kill_x (kill_x), + + + .divide_d (divide_q_d), + .modulus_d (modulus_q_d), + + + + + + + + + + + + + .operand_0_d (d_result_0), + .operand_1_d (d_result_1), + + .result_x (mc_result_x), + + + .divide_by_zero_x (divide_by_zero_x), + + + .stall_request_x (mc_stall_request_x) + ); + + + + + + +lm32_interrupt_full interrupt_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .interrupt (interrupt), + + .stall_x (stall_x), + + + + + + .exception (exception_q_w), + + + .eret_q_x (eret_q_x), + + + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + + .interrupt_exception (interrupt_exception), + + .csr_read_data (interrupt_csr_read_data_x) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; + reg [31:0] w_result_d; + reg regfile_raw_0, regfile_raw_0_nxt; + reg regfile_raw_1, regfile_raw_1_nxt; + + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) + begin + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[25:21])) + regfile_raw_0_nxt = 1'b1; + else + regfile_raw_0_nxt = 1'b0; + + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[20:16])) + regfile_raw_1_nxt = 1'b1; + else + regfile_raw_1_nxt = 1'b0; + end + + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) + if (regfile_raw_0) + reg_data_live_0 = w_result_d; + else + reg_data_live_0 = regfile_data_0; + + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) + if (regfile_raw_1) + reg_data_live_1 = w_result_d; + else + reg_data_live_1 = regfile_data_1; + + + + + always @(posedge clk_i ) + if (rst_i == 1'b1) + begin + regfile_raw_0 <= 1'b0; + regfile_raw_1 <= 1'b0; + w_result_d <= 32'b0; + end + else + begin + regfile_raw_0 <= regfile_raw_0_nxt; + regfile_raw_1 <= regfile_raw_1_nxt; + w_result_d <= w_result; + end + + + + + + lm32_dp_ram + #( + + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_0 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[25:21]), + + .rdata_o (regfile_data_0) + ); + + lm32_dp_ram + #( + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_1 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[20:16]), + + .rdata_o (regfile_data_1) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; +assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + +assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); +assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); +assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); +assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); +assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); +assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + +always @(*) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction - generate - for (i = 0; i < associativity; i = i + 1) - begin : memories - lm32_ram - #( - .data_width (32), - .address_width ( (addr_offset_width+addr_set_width)) -) - way_0_data_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (dmem_read_address), - .enable_read (enable), - .write_address (dmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i]), - .write_data (refill_data), - .read_data (way_data[i]) - ); - lm32_ram - #( - .data_width ( (addr_tag_width+1)), - .address_width ( addr_set_width) - ) - way_0_tag_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (tmem_read_address), - .enable_read (enable), - .write_address (tmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i] | flushing), - .write_data (tmem_write_data), - .read_data ({way_tag[i], way_valid[i]}) - ); - end -endgenerate -generate - for (i = 0; i < associativity; i = i + 1) - begin : match -assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); - end -endgenerate -generate - if (associativity == 1) - begin : inst_1 -assign inst = way_match[0] ? way_data[0] : 32'b0; - end - else if (associativity == 2) - begin : inst_2 -assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); - end -endgenerate -generate - if (bytes_per_line > 4) -assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; - else -assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; -endgenerate -assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; -assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; -assign tmem_write_address = flushing - ? flush_set - : refill_address[ addr_set_msb:addr_set_lsb]; -generate - if (bytes_per_line > 4) -assign last_refill = refill_offset == {addr_offset_width{1'b1}}; - else -assign last_refill = 1'b1; -endgenerate -assign enable = (stall_a == 1'b0); -generate - if (associativity == 1) - begin : we_1 -assign way_mem_we[0] = (refill_ready == 1'b1); - end + if ( ( (x_bypass_enable_x == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) + ) + ) + || ( (m_bypass_enable_m == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) + ) + ) + ) + interlock = 1'b1; else - begin : we_2 -assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); -assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); - end -endgenerate -assign tmem_write_data[ 0] = last_refill & !flushing; -assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; -assign flushing = |state[1:0]; -assign check = state[2]; -assign refill = state[3]; -assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); -assign stall_request = (check == 1'b0); -assign refill_request = (refill == 1'b1); -generate - if (associativity >= 2) - begin : way_select -always @(posedge clk_i ) + interlock = 1'b0; +end + + +always @(*) begin - if (rst_i == 1'b1) - refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + if (raw_x_0 == 1'b1) + bypass_data_0 = x_result; + else if (raw_m_0 == 1'b1) + bypass_data_0 = m_result; + else if (raw_w_0 == 1'b1) + bypass_data_0 = w_result; else - begin - if (miss == 1'b1) - refill_way_select <= {refill_way_select[0], refill_way_select[1]}; - end + bypass_data_0 = reg_data_0; end - end -endgenerate -always @(posedge clk_i ) + + +always @(*) begin - if (rst_i == 1'b1) - refilling <= 1'b0; + if (raw_x_1 == 1'b1) + bypass_data_1 = x_result; + else if (raw_m_1 == 1'b1) + bypass_data_1 = m_result; + else if (raw_w_1 == 1'b1) + bypass_data_1 = w_result; else - refilling <= refill; + bypass_data_1 = reg_data_1; end -always @(posedge clk_i ) + + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; + assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + + assign branch_target_d = pc_d + branch_offset_d; + + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + +always @(*) begin - if (rst_i == 1'b1) - begin - state <= 4'b0001; - flush_set <= { addr_set_width{1'b1}}; - refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - restart_request <= 1'b0; - end - else - begin - case (state) - 4'b0001: - begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 4'b0100; - flush_set <= flush_set - 1'b1; - end - 4'b0010: - begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 4'b0100; - flush_set <= flush_set - 1'b1; - end - 4'b0100: - begin - if (stall_a == 1'b0) - restart_request <= 1'b0; - if (iflush == 1'b1) - begin - refill_address <= address_f; - state <= 4'b0010; - end - else if (miss == 1'b1) - begin - refill_address <= address_f; - state <= 4'b1000; - end - end - 4'b1000: - begin - if (refill_ready == 1'b1) - begin - if (last_refill == 1'b1) - begin - restart_request <= 1'b1; - state <= 4'b0100; - end - end - end - endcase - end + d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; + case (d_result_sel_1_d) + 2'b00: d_result_1 = { 32{1'b0}}; + 2'b01: d_result_1 = bypass_data_1; + 2'b10: d_result_1 = immediate_d; + default: d_result_1 = { 32{1'bx}}; + endcase end -generate - if (bytes_per_line > 4) - begin -always @(posedge clk_i ) + + + + + + + + + + + +assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; +assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; +assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + +assign cmp_zero = operand_0_x == operand_1_x; +assign cmp_negative = adder_result_x[ 32-1]; +assign cmp_overflow = adder_overflow_x; +assign cmp_carry_n = adder_carry_n_x; +always @(*) begin - if (rst_i == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else - begin - case (state) - 4'b0100: - begin - if (iflush == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else if (miss == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - end - 4'b1000: - begin - if (refill_ready == 1'b1) - refill_offset <= refill_offset + 1'b1; - end - endcase - end + case (condition_x) + 3'b000: condition_met_x = 1'b1; + 3'b110: condition_met_x = 1'b1; + 3'b001: condition_met_x = cmp_zero; + 3'b111: condition_met_x = !cmp_zero; + 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); + 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; + 3'b011: condition_met_x = cmp_negative == cmp_overflow; + 3'b100: condition_met_x = cmp_carry_n; + default: condition_met_x = 1'bx; + endcase +end + + +always @(*) +begin + x_result = x_result_sel_add_x ? adder_result_x + : x_result_sel_csr_x ? csr_read_data_x + + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + : x_result_sel_mc_arith_x ? mc_result_x + + + : logic_result_x; end - end -endgenerate -endmodule -module lm32_dcache_full_debug ( - clk_i, - rst_i, - stall_a, - stall_x, - stall_m, - address_x, - address_m, - load_q_m, - store_q_m, - store_data, - store_byte_select, - refill_ready, - refill_data, - dflush, - stall_request, - restart_request, - refill_request, - refill_address, - refilling, - load_data - ); -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam addr_offset_width = clogb2(bytes_per_line)-1-2; -localparam addr_set_width = clogb2(sets)-1; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -localparam addr_set_lsb = (addr_offset_msb+1); -localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); -localparam addr_tag_lsb = (addr_set_msb+1); -localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; -localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); -input clk_i; -input rst_i; -input stall_a; -input stall_x; -input stall_m; -input [ (32-1):0] address_x; -input [ (32-1):0] address_m; -input load_q_m; -input store_q_m; -input [ (32-1):0] store_data; -input [ (4-1):0] store_byte_select; -input refill_ready; -input [ (32-1):0] refill_data; -input dflush; -output stall_request; -wire stall_request; -output restart_request; -reg restart_request; -output refill_request; -reg refill_request; -output [ (32-1):0] refill_address; -reg [ (32-1):0] refill_address; -output refilling; -reg refilling; -output [ (32-1):0] load_data; -wire [ (32-1):0] load_data; -wire read_port_enable; -wire write_port_enable; -wire [0:associativity-1] way_tmem_we; -wire [0:associativity-1] way_dmem_we; -wire [ (32-1):0] way_data[0:associativity-1]; -wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; -wire [0:associativity-1] way_valid; -wire [0:associativity-1] way_match; -wire miss; -wire [ (addr_set_width-1):0] tmem_read_address; -wire [ (addr_set_width-1):0] tmem_write_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; -wire [ ((addr_tag_width+1)-1):0] tmem_write_data; -reg [ (32-1):0] dmem_write_data; -reg [ 2:0] state; -wire flushing; -wire check; -wire refill; -wire valid_store; -reg [associativity-1:0] refill_way_select; -reg [ addr_offset_msb:addr_offset_lsb] refill_offset; -wire last_refill; -reg [ (addr_set_width-1):0] flush_set; -genvar i, j; -function integer clogb2; -input [31:0] value; + + +always @(*) begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; + m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + + : m_result_sel_shift_m ? shifter_result_m + + + : operand_m; end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + +always @(*) +begin + w_result = w_result_sel_load_w ? load_data_w + + + : w_result_sel_mul_w ? multiplier_result_w + + + : operand_w; +end + + + + +assign branch_taken_x = (stall_x == 1'b0) + && ( (branch_x == 1'b1) + && ((condition_x == 3'b000) || (condition_x == 3'b110)) + && (valid_x == 1'b1) + && (branch_predict_x == 1'b0) + ); + + + + +assign branch_taken_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( ( (condition_met_m == 1'b1) + && (branch_predict_taken_m == 1'b0) + ) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign branch_mispredict_taken_m = (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1); + + +assign branch_flushX_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( (condition_met_m == 1'b1) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign kill_f = ( (valid_d == 1'b1) + && (branch_predict_taken_d == 1'b1) + ) + || (branch_taken_m == 1'b1) + + + || (branch_taken_x == 1'b1) + + + + + || (icache_refill_request == 1'b1) + + + + + || (dcache_refill_request == 1'b1) + + + ; +assign kill_d = (branch_taken_m == 1'b1) + + + || (branch_taken_x == 1'b1) + + + + + || (icache_refill_request == 1'b1) + + + + + || (dcache_refill_request == 1'b1) + + + ; +assign kill_x = (branch_flushX_m == 1'b1) + + + || (dcache_refill_request == 1'b1) + + + ; +assign kill_m = 1'b0 + + + || (dcache_refill_request == 1'b1) + + + ; +assign kill_w = 1'b0 + + + || (dcache_refill_request == 1'b1) + + + ; + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_bus_error_exception = ( (bus_error_x == 1'b1) + && (valid_x == 1'b1) + ); +assign data_bus_error_exception = data_bus_error_seen == 1'b1; + + + + + +assign divide_by_zero_exception = divide_by_zero_x == 1'b1; + + + +assign system_call_exception = ( (scall_x == 1'b1) + + + && (valid_x == 1'b1) + + + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign exception_x = (system_call_exception == 1'b1) + + + || (instruction_bus_error_exception == 1'b1) + || (data_bus_error_exception == 1'b1) + + + + + || (divide_by_zero_exception == 1'b1) + + + + + || ( (interrupt_exception == 1'b1) + + + + + + + && (store_q_m == 1'b0) + && (D_CYC_O == 1'b0) + + + ) + + + ; + + + + +always @(*) +begin + + + + + + + + + + + + + + + + + + + if (data_bus_error_exception == 1'b1) + eid_x = 3'h4; + else + if (instruction_bus_error_exception == 1'b1) + eid_x = 3'h2; + else + + + + + + + + + + + if (divide_by_zero_exception == 1'b1) + eid_x = 3'h5; + else + + + + + if ( (interrupt_exception == 1'b1) + + + + + ) + eid_x = 3'h6; + else + + + eid_x = 3'h7; +end + + + +assign stall_a = (stall_f == 1'b1); + +assign stall_f = (stall_d == 1'b1); + +assign stall_d = (stall_x == 1'b1) + || ( (interlock == 1'b1) + && (kill_d == 1'b0) + ) + || ( ( (eret_d == 1'b1) + || (scall_d == 1'b1) + + + || (bus_error_d == 1'b1) + + + ) + && ( (load_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_x == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + + + + + + + + + + + + + + || ( (csr_write_enable_d == 1'b1) + && (load_q_x == 1'b1) + ) + + + + + + + + + + + ; + +assign stall_x = (stall_m == 1'b1) + + + || ( (mc_stall_request_x == 1'b1) + && (kill_x == 1'b0) + ) + + + + + ; + +assign stall_m = (stall_wb_load == 1'b1) + + + + + || ( (D_CYC_O == 1'b1) + && ( (store_m == 1'b1) + + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + + || (load_m == 1'b1) + || (load_x == 1'b1) + ) + ) + + + + + || (dcache_stall_request == 1'b1) + + + + + || (icache_stall_request == 1'b1) + || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) + + + + + + + + + + + + + ; + + + + +assign q_d = (valid_d == 1'b1) && (kill_d == 1'b0); + + + + + + + + + + + + + +assign divide_q_d = (divide_d == 1'b1) && (q_d == 1'b1); +assign modulus_q_d = (modulus_d == 1'b1) && (q_d == 1'b1); + + +assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); +assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); +assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + + + +assign load_q_x = (load_x == 1'b1) + && (q_x == 1'b1) + + + + + ; +assign store_q_x = (store_x == 1'b1) + && (q_x == 1'b1) + + + + + ; + + + + +assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); +assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); +assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + + + + +assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + + +assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); +assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); +assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + +assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + +assign cfg = { + 6'h02, + watchpoints[3:0], + breakpoints[3:0], + interrupts[5:0], + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + 1'b1 + + + + + }; + +assign cfg2 = { + 30'b0, + + + + + 1'b0, + + + + + + + 1'b0 + + + }; + + + + +assign iflush = ( (csr_write_enable_d == 1'b1) + && (csr_d == 4 'h3) + && (stall_d == 1'b0) + && (kill_d == 1'b0) + && (valid_d == 1'b1)) + + + + + + + + ; + + + + +assign dflush_x = ( (csr_write_enable_q_x == 1'b1) + && (csr_x == 4 'h4)) + + + + + + + + ; + + + + +assign csr_d = read_idx_0_d[ (4 -1):0]; + + +always @(*) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; + case (csr_x) + + + 4 'h0, + 4 'h1, + 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + + 4 'h6: csr_read_data_x = cfg; + 4 'h7: csr_read_data_x = {eba, 8'h00}; + + + + + + + + + + 4 'ha: csr_read_data_x = cfg2; + 4 'hb: csr_read_data_x = sdb_address; + + default: csr_read_data_x = { 32{1'bx}}; + endcase end -endfunction - generate - for (i = 0; i < associativity; i = i + 1) - begin : memories - if ( (addr_offset_width+addr_set_width) < 11) - begin : data_memories - lm32_ram - #( - .data_width (32), - .address_width ( (addr_offset_width+addr_set_width)) - ) way_0_data_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (dmem_read_address), - .enable_read (read_port_enable), - .write_address (dmem_write_address), - .enable_write (write_port_enable), - .write_enable (way_dmem_we[i]), - .write_data (dmem_write_data), - .read_data (way_data[i]) - ); - end - else - begin - for (j = 0; j < 4; j = j + 1) - begin : byte_memories - lm32_ram - #( - .data_width (8), - .address_width ( (addr_offset_width+addr_set_width)) - ) way_0_data_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (dmem_read_address), - .enable_read (read_port_enable), - .write_address (dmem_write_address), - .enable_write (write_port_enable), - .write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)), - .write_data (dmem_write_data[(j+1)*8-1:j*8]), - .read_data (way_data[i][(j+1)*8-1:j*8]) - ); - end - end - lm32_ram - #( - .data_width ( (addr_tag_width+1)), - .address_width ( addr_set_width) - ) way_0_tag_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (tmem_read_address), - .enable_read (read_port_enable), - .write_address (tmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_tmem_we[i]), - .write_data (tmem_write_data), - .read_data ({way_tag[i], way_valid[i]}) - ); - end - endgenerate -generate - for (i = 0; i < associativity; i = i + 1) - begin : match -assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[ addr_tag_msb:addr_tag_lsb], 1'b1}); - end -endgenerate -generate - if (associativity == 1) - begin : data_1 -assign load_data = way_data[0]; - end - else if (associativity == 2) - begin : data_2 -assign load_data = way_match[0] ? way_data[0] : way_data[1]; - end -endgenerate -generate - if ( (addr_offset_width+addr_set_width) < 11) - begin -always @(*) + + + + + + +always @(posedge clk_i ) begin - if (refill == 1'b1) - dmem_write_data = refill_data; + if (rst_i == 1'b1) + eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; else begin - dmem_write_data[ 7:0] = store_byte_select[0] ? store_data[ 7:0] : load_data[ 7:0]; - dmem_write_data[ 15:8] = store_byte_select[1] ? store_data[ 15:8] : load_data[ 15:8]; - dmem_write_data[ 23:16] = store_byte_select[2] ? store_data[ 23:16] : load_data[ 23:16]; - dmem_write_data[ 31:24] = store_byte_select[3] ? store_data[ 31:24] : load_data[ 31:24]; + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + + + end end - end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + data_bus_error_seen <= 1'b0; else begin + + if ((D_ERR_I == 1'b1) && (D_CYC_O == 1'b1)) + data_bus_error_seen <= 1'b1; + + if ((exception_m == 1'b1) && (kill_m == 1'b0)) + data_bus_error_seen <= 1'b0; + end +end + + + + + + + + + always @(*) begin - if (refill == 1'b1) - dmem_write_data = refill_data; - else - dmem_write_data = store_data; -end - end -endgenerate -generate - if (bytes_per_line > 4) -assign dmem_write_address = (refill == 1'b1) - ? {refill_address[ addr_set_msb:addr_set_lsb], refill_offset} - : address_m[ addr_set_msb:addr_offset_lsb]; - else -assign dmem_write_address = (refill == 1'b1) - ? refill_address[ addr_set_msb:addr_set_lsb] - : address_m[ addr_set_msb:addr_offset_lsb]; -endgenerate -assign dmem_read_address = address_x[ addr_set_msb:addr_offset_lsb]; -assign tmem_write_address = (flushing == 1'b1) - ? flush_set - : refill_address[ addr_set_msb:addr_set_lsb]; -assign tmem_read_address = address_x[ addr_set_msb:addr_set_lsb]; -generate - if (bytes_per_line > 4) -assign last_refill = refill_offset == {addr_offset_width{1'b1}}; - else -assign last_refill = 1'b1; -endgenerate -assign read_port_enable = (stall_x == 1'b0); -assign write_port_enable = (refill_ready == 1'b1) || !stall_m; -assign valid_store = (store_q_m == 1'b1) && (check == 1'b1); -generate - if (associativity == 1) - begin : we_1 -assign way_dmem_we[0] = (refill_ready == 1'b1) || ((valid_store == 1'b1) && (way_match[0] == 1'b1)); -assign way_tmem_we[0] = (refill_ready == 1'b1) || (flushing == 1'b1); - end + if ( (icache_refill_request == 1'b1) + || (dcache_refill_request == 1'b1) + ) + valid_a = 1'b0; + else if ( (icache_restart_request == 1'b1) + || (dcache_restart_request == 1'b1) + ) + valid_a = 1'b1; else - begin : we_2 -assign way_dmem_we[0] = ((refill_ready == 1'b1) && (refill_way_select[0] == 1'b1)) || ((valid_store == 1'b1) && (way_match[0] == 1'b1)); -assign way_dmem_we[1] = ((refill_ready == 1'b1) && (refill_way_select[1] == 1'b1)) || ((valid_store == 1'b1) && (way_match[1] == 1'b1)); -assign way_tmem_we[0] = ((refill_ready == 1'b1) && (refill_way_select[0] == 1'b1)) || (flushing == 1'b1); -assign way_tmem_we[1] = ((refill_ready == 1'b1) && (refill_way_select[1] == 1'b1)) || (flushing == 1'b1); - end -endgenerate -assign tmem_write_data[ 0] = ((last_refill == 1'b1) || (valid_store == 1'b1)) && (flushing == 1'b0); -assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; -assign flushing = state[0]; -assign check = state[1]; -assign refill = state[2]; -assign miss = (~(|way_match)) && (load_q_m == 1'b1) && (stall_m == 1'b0); -assign stall_request = (check == 1'b0); -generate - if (associativity >= 2) - begin : way_select + valid_a = !icache_refilling && !dcache_refilling; +end + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + begin + valid_f <= 1'b0; + valid_d <= 1'b0; + valid_x <= 1'b0; + valid_m <= 1'b0; + valid_w <= 1'b0; + end else - begin - if (refill_request == 1'b1) - refill_way_select <= {refill_way_select[0], refill_way_select[1]}; + begin + if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + + valid_f <= valid_a; + + + + + else if (stall_f == 1'b0) + valid_f <= 1'b0; + + if (kill_d == 1'b1) + valid_d <= 1'b0; + else if (stall_f == 1'b0) + valid_d <= valid_f & !kill_f; + else if (stall_d == 1'b0) + valid_d <= 1'b0; + + if (stall_d == 1'b0) + valid_x <= valid_d & !kill_d; + else if (kill_x == 1'b1) + valid_x <= 1'b0; + else if (stall_x == 1'b0) + valid_x <= 1'b0; + + if (kill_m == 1'b1) + valid_m <= 1'b0; + else if (stall_x == 1'b0) + valid_m <= valid_x & !kill_x; + else if (stall_m == 1'b0) + valid_m <= 1'b0; + + if (stall_m == 1'b0) + valid_w <= valid_m & !kill_m; + else + valid_w <= 1'b0; end end - end -endgenerate -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - refilling <= 1'b0; - else - refilling <= refill; -end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - state <= 3'b001; - flush_set <= { addr_set_width{1'b1}}; - refill_request <= 1'b0; - refill_address <= { 32{1'bx}}; - restart_request <= 1'b0; + + + + + operand_0_x <= { 32{1'b0}}; + operand_1_x <= { 32{1'b0}}; + store_operand_x <= { 32{1'b0}}; + branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + x_result_sel_csr_x <= 1'b0; + + + x_result_sel_mc_arith_x <= 1'b0; + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + + x_result_sel_add_x <= 1'b0; + m_result_sel_compare_x <= 1'b0; + + + m_result_sel_shift_x <= 1'b0; + + + w_result_sel_load_x <= 1'b0; + + + w_result_sel_mul_x <= 1'b0; + + + x_bypass_enable_x <= 1'b0; + m_bypass_enable_x <= 1'b0; + write_enable_x <= 1'b0; + write_idx_x <= { 5{1'b0}}; + csr_x <= { 4 {1'b0}}; + load_x <= 1'b0; + store_x <= 1'b0; + size_x <= { 2{1'b0}}; + sign_extend_x <= 1'b0; + adder_op_x <= 1'b0; + adder_op_x_n <= 1'b0; + logic_op_x <= 4'h0; + + + direction_x <= 1'b0; + + + + + + + + branch_x <= 1'b0; + branch_predict_x <= 1'b0; + branch_predict_taken_x <= 1'b0; + condition_x <= 3'b000; + + + + + scall_x <= 1'b0; + eret_x <= 1'b0; + + + + + + + bus_error_x <= 1'b0; + data_bus_error_exception_m <= 1'b0; + + + csr_write_enable_x <= 1'b0; + operand_m <= { 32{1'b0}}; + branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + m_result_sel_compare_m <= 1'b0; + + + m_result_sel_shift_m <= 1'b0; + + + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + + m_bypass_enable_m <= 1'b0; + branch_m <= 1'b0; + branch_predict_m <= 1'b0; + branch_predict_taken_m <= 1'b0; + exception_m <= 1'b0; + load_m <= 1'b0; + store_m <= 1'b0; + write_enable_m <= 1'b0; + write_idx_m <= { 5{1'b0}}; + condition_met_m <= 1'b0; + + + dflush_m <= 1'b0; + + + + + + + + operand_w <= { 32{1'b0}}; + w_result_sel_load_w <= 1'b0; + + + w_result_sel_mul_w <= 1'b0; + + + write_idx_w <= { 5{1'b0}}; + write_enable_w <= 1'b0; + + + + + + exception_w <= 1'b0; + + + + + memop_pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + + end - else + else begin - case (state) - 3'b001: + + + if (stall_x == 1'b0) begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 3'b010; - flush_set <= flush_set - 1'b1; + + + + + operand_0_x <= d_result_0; + operand_1_x <= d_result_1; + store_operand_x <= bypass_data_1; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; + x_result_sel_csr_x <= x_result_sel_csr_d; + + + x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d; + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + + x_result_sel_add_x <= x_result_sel_add_d; + m_result_sel_compare_x <= m_result_sel_compare_d; + + + m_result_sel_shift_x <= m_result_sel_shift_d; + + + w_result_sel_load_x <= w_result_sel_load_d; + + + w_result_sel_mul_x <= w_result_sel_mul_d; + + + x_bypass_enable_x <= x_bypass_enable_d; + m_bypass_enable_x <= m_bypass_enable_d; + load_x <= load_d; + store_x <= store_d; + branch_x <= branch_d; + branch_predict_x <= branch_predict_d; + branch_predict_taken_x <= branch_predict_taken_d; + write_idx_x <= write_idx_d; + csr_x <= csr_d; + size_x <= size_d; + sign_extend_x <= sign_extend_d; + adder_op_x <= adder_op_d; + adder_op_x_n <= ~adder_op_d; + logic_op_x <= logic_op_d; + + + direction_x <= direction_d; + + + + + + + condition_x <= condition_d; + csr_write_enable_x <= csr_write_enable_d; + + + + + scall_x <= scall_d; + + + bus_error_x <= bus_error_d; + + + eret_x <= eret_d; + + + + + write_enable_x <= write_enable_d; end - 3'b010: + + + + if (stall_m == 1'b0) begin - if (stall_a == 1'b0) - restart_request <= 1'b0; - if (miss == 1'b1) + operand_m <= x_result; + m_result_sel_compare_m <= m_result_sel_compare_x; + + + m_result_sel_shift_m <= m_result_sel_shift_x; + + + if (exception_x == 1'b1) begin - refill_request <= 1'b1; - refill_address <= address_m; - state <= 3'b100; + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + end - else if (dflush == 1'b1) - state <= 3'b001; - end - 3'b100: - begin - refill_request <= 1'b0; - if (refill_ready == 1'b1) + else begin - if (last_refill == 1'b1) - begin - restart_request <= 1'b1; - state <= 3'b010; - end + w_result_sel_load_m <= w_result_sel_load_x; + + + w_result_sel_mul_m <= w_result_sel_mul_x; + + end + m_bypass_enable_m <= m_bypass_enable_x; + load_m <= load_x; + store_m <= store_x; + + + branch_m <= branch_x && !branch_taken_x; + + + + + + + + + + + + + + + + + + + + + if (exception_x == 1'b1) + write_idx_m <= 5'd30; + else + write_idx_m <= write_idx_x; + + + condition_met_m <= condition_met_x; + + + + + + + + + + + + + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + + + + + + + + dflush_m <= dflush_x; + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + + + end - endcase + + + if (stall_m == 1'b0) + begin + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + exception_m <= 1'b1; + else + exception_m <= 1'b0; + + + data_bus_error_exception_m <= (data_bus_error_exception == 1'b1) + + + + + ; + + + end + + + + + operand_w <= exception_m == 1'b1 ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result; + + + + + w_result_sel_load_w <= w_result_sel_load_m; + + + w_result_sel_mul_w <= w_result_sel_mul_m; + + + write_idx_w <= write_idx_m; + + + + + + + + + write_enable_w <= write_enable_m; + + + + + + exception_w <= exception_m; + + + + + if ( (stall_m == 1'b0) + && ( (load_q_m == 1'b1) + || (store_q_m == 1'b1) + ) + ) + memop_pc_w <= pc_m; + + end end -generate - if (bytes_per_line > 4) - begin + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else begin - case (state) - 3'b010: - begin - if (miss == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - end - 3'b100: + use_buf <= 1'b0; + reg_data_buf_0 <= { 32{1'b0}}; + reg_data_buf_1 <= { 32{1'b0}}; + end + else + begin + if (stall_d == 1'b0) + use_buf <= 1'b0; + else if (use_buf == 1'b0) + begin + reg_data_buf_0 <= reg_data_live_0; + reg_data_buf_1 <= reg_data_live_1; + use_buf <= 1'b1; + end + if (reg_write_enable_q_w == 1'b1) begin - if (refill_ready == 1'b1) - refill_offset <= refill_offset + 1'b1; + if (write_idx_w == read_idx_0_d) + reg_data_buf_0 <= w_result; + if (write_idx_w == read_idx_1_d) + reg_data_buf_1 <= w_result; end - endcase end end - end -endgenerate -endmodule -module lm32_debug_full_debug ( - clk_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +initial +begin + + + + + + +end + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_full +( + + clk_i, + + + + rst_i, - pc_x, + + stall_a, + stall_x, + stall_m, + kill_x, + kill_m, + exception_m, + store_operand_x, + load_store_address_x, + load_store_address_m, + load_store_address_w, load_x, store_x, - load_store_address_x, - csr_write_enable_x, - csr_write_data, - csr_x, - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - eret_q_x, - bret_q_x, - stall_x, - exception_x, - q_x, + load_q_x, + store_q_x, + load_q_m, + store_q_m, + sign_extend_x, + size_x, + + + dflush, + + + + d_dat_i, + d_ack_i, + d_err_i, + d_rty_i, + + + + dcache_refill_request, - dc_ss, - dc_re, - bp_match, - wp_match + dcache_restart_request, + dcache_stall_request, + dcache_refilling, + + + + + + + + + + + + + load_data_w, + stall_wb_load, + + d_dat_o, + d_adr_o, + d_cyc_o, + d_sel_o, + d_stb_o, + d_we_o, + d_cti_o, + d_lock_o, + d_bte_o ); -parameter breakpoints = 0; -parameter watchpoints = 0; -input clk_i; -input rst_i; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -input load_x; -input store_x; -input [ (32-1):0] load_store_address_x; -input csr_write_enable_x; -input [ (32-1):0] csr_write_data; -input [ (5-1):0] csr_x; -input jtag_csr_write_enable; -input [ (32-1):0] jtag_csr_write_data; -input [ (5-1):0] jtag_csr; -input eret_q_x; -input bret_q_x; -input stall_x; -input exception_x; -input q_x; -input dcache_refill_request; -output dc_ss; -reg dc_ss; -output dc_re; -reg dc_re; -output bp_match; -wire bp_match; -output wp_match; -wire wp_match; -genvar i; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; -reg bp_e[0:breakpoints-1]; -wire [0:breakpoints-1]bp_match_n; -reg [ 1:0] wpc_c[0:watchpoints-1]; -reg [ (32-1):0] wp[0:watchpoints-1]; -wire [0:watchpoints-1]wp_match_n; -wire debug_csr_write_enable; -wire [ (32-1):0] debug_csr_write_data; -wire [ (5-1):0] debug_csr; -reg [ 2:0] state; + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + input clk_i; + +input rst_i; + +input stall_a; +input stall_x; +input stall_m; +input kill_x; +input kill_m; +input exception_m; + +input [ (32-1):0] store_operand_x; +input [ (32-1):0] load_store_address_x; +input [ (32-1):0] load_store_address_m; +input [1:0] load_store_address_w; +input load_x; +input store_x; +input load_q_x; +input store_q_x; +input load_q_m; +input store_q_m; +input sign_extend_x; +input [ 1:0] size_x; + + + +input dflush; + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + +input [ (32-1):0] d_dat_i; +input d_ack_i; +input d_err_i; +input d_rty_i; + + + + + + + +output dcache_refill_request; +wire dcache_refill_request; +output dcache_restart_request; +wire dcache_restart_request; +output dcache_stall_request; +wire dcache_stall_request; +output dcache_refilling; +wire dcache_refilling; + + + + +output [ (32-1):0] load_data_w; +reg [ (32-1):0] load_data_w; +output stall_wb_load; +reg stall_wb_load; + +output [ (32-1):0] d_dat_o; +reg [ (32-1):0] d_dat_o; +output [ (32-1):0] d_adr_o; +reg [ (32-1):0] d_adr_o; +output d_cyc_o; +reg d_cyc_o; +output [ (4-1):0] d_sel_o; +reg [ (4-1):0] d_sel_o; +output d_stb_o; +reg d_stb_o; +output d_we_o; +reg d_we_o; +output [ (3-1):0] d_cti_o; +reg [ (3-1):0] d_cti_o; +output d_lock_o; +reg d_lock_o; +output [ (2-1):0] d_bte_o; +wire [ (2-1):0] d_bte_o; + + + + + + +reg [ 1:0] size_m; +reg [ 1:0] size_w; +reg sign_extend_m; +reg sign_extend_w; +reg [ (32-1):0] store_data_x; +reg [ (32-1):0] store_data_m; +reg [ (4-1):0] byte_enable_x; +reg [ (4-1):0] byte_enable_m; +wire [ (32-1):0] data_m; +reg [ (32-1):0] data_w; + + + + + +wire dcache_select_x; +reg dcache_select_m; +wire [ (32-1):0] dcache_data_m; +wire [ (32-1):0] dcache_refill_address; +reg dcache_refill_ready; +wire [ (3-1):0] first_cycle_type; +wire [ (3-1):0] next_cycle_type; +wire last_word; +wire [ (32-1):0] first_address; + + + + + + + + + + + + +wire wb_select_x; + + + + + + + + + + +reg wb_select_m; +reg [ (32-1):0] wb_data_m; +reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -6320,6 +18802,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -6332,295 +18815,1357 @@ begin clogb2_v1 = i-1; end endfunction -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_comb -assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); - end -endgenerate -generate - if (breakpoints > 0) -assign bp_match = (|bp_match_n) || (state == 3'b011); - else -assign bp_match = state == 3'b011; -endgenerate -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_comb -assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); - end -endgenerate -generate - if (watchpoints > 0) -assign wp_match = |wp_match_n; - else -assign wp_match = 1'b0; -endgenerate -assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); -assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; -assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_seq -always @(posedge clk_i ) + + + + + + + + + + + + +lm32_dcache_full #( + .associativity (associativity), + .sets (sets), + .bytes_per_line (bytes_per_line), + .base_address (base_address), + .limit (limit) + ) dcache ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_a (stall_a), + .stall_x (stall_x), + .stall_m (stall_m), + .address_x (load_store_address_x), + .address_m (load_store_address_m), + .load_q_m (load_q_m & dcache_select_m), + .store_q_m (store_q_m & dcache_select_m), + .store_data (store_data_m), + .store_byte_select (byte_enable_m & {4{dcache_select_m}}), + .refill_ready (dcache_refill_ready), + .refill_data (wb_data_m), + .dflush (dflush), + + .stall_request (dcache_stall_request), + .restart_request (dcache_restart_request), + .refill_request (dcache_refill_request), + .refill_address (dcache_refill_address), + .refilling (dcache_refilling), + .load_data (dcache_data_m) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign dcache_select_x = (load_store_address_x >= 32'h0) + && (load_store_address_x <= 32'h7fffffff) + + + + + + + + + ; + + + + assign wb_select_x = 1'b1 + + + && !dcache_select_x + + + + + + + + + + + ; + + +always @(*) begin - if (rst_i == 1'b1) + case (size_x) + 2'b00: store_data_x = {4{store_operand_x[7:0]}}; + 2'b11: store_data_x = {2{store_operand_x[15:0]}}; + 2'b10: store_data_x = store_operand_x; + default: store_data_x = { 32{1'bx}}; + endcase +end + + +always @(*) +begin + casez ({size_x, load_store_address_x[1:0]}) + { 2'b00, 2'b11}: byte_enable_x = 4'b0001; + { 2'b00, 2'b10}: byte_enable_x = 4'b0010; + { 2'b00, 2'b01}: byte_enable_x = 4'b0100; + { 2'b00, 2'b00}: byte_enable_x = 4'b1000; + { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; + { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; + { 2'b10, 2'b??}: byte_enable_x = 4'b1111; + default: byte_enable_x = 4'bxxxx; + endcase +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_select_m == 1'b1 + ? wb_data_m + : dcache_data_m; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(*) +begin + casez ({size_w, load_store_address_w[1:0]}) + { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; + { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; + { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; + { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; + { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; + { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; + { 2'b10, 2'b??}: load_data_w = data_w; + default: load_data_w = { 32{1'bx}}; + endcase +end + + +assign d_bte_o = 2'b00; + + + + +generate + case (bytes_per_line) + 4: begin - bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - bp_e[i] <= 1'b0; +assign first_cycle_type = 3'b111; +assign next_cycle_type = 3'b111; +assign last_word = 1'b1; +assign first_address = {dcache_refill_address[ 32-1:2], 2'b00}; end - else + 8: begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) - begin - bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - bp_e[i] <= debug_csr_write_data[0]; - end +assign first_cycle_type = 3'b010; +assign next_cycle_type = 3'b111; +assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1; +assign first_address = {dcache_refill_address[ 32-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00}; end -end + 16: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = d_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; +assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1; +assign first_address = {dcache_refill_address[ 32-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00}; end + endcase endgenerate -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_seq + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - wp[i] <= { 32{1'bx}}; - wpc_c[i] <= 2'b00; + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_dat_o <= { 32{1'b0}}; + d_adr_o <= { 32{1'b0}}; + d_sel_o <= { 4{ 1'b0}}; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + d_lock_o <= 1'b0; + wb_data_m <= { 32{1'b0}}; + wb_load_complete <= 1'b0; + stall_wb_load <= 1'b0; + + + dcache_refill_ready <= 1'b0; + + end else begin - if (debug_csr_write_enable == 1'b1) + + + + dcache_refill_ready <= 1'b0; + + + + if (d_cyc_o == 1'b1) begin - if (debug_csr == 5'h8) - wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; - if (debug_csr == 5'h18 + i) - wp[i] <= debug_csr_write_data; + + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) + begin + + + if ((dcache_refilling == 1'b1) && (!last_word)) + begin + + d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + end + else + + + begin + + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_lock_o <= 1'b0; + end + + + d_cti_o <= next_cycle_type; + + dcache_refill_ready <= dcache_refilling; + + + + wb_data_m <= d_dat_i; + + wb_load_complete <= !d_we_o; + end + + if (d_err_i == 1'b1) + $display ("Data bus error. Address: %x", d_adr_o); + end - end -end + else + begin + + + if (dcache_refill_request == 1'b1) + begin + + d_adr_o <= first_address; + d_cyc_o <= 1'b1; + d_sel_o <= { 32/8{ 1'b1}}; + d_stb_o <= 1'b1; + d_we_o <= 1'b0; + d_cti_o <= first_cycle_type; + + end + else + + + if ( (store_q_m == 1'b1) + && (stall_m == 1'b0) + + + + + + + + + ) + begin + + d_dat_o <= store_data_m; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b1; + d_cti_o <= 3'b111; + end + else if ( (load_q_m == 1'b1) + && (wb_select_m == 1'b1) + && (wb_load_complete == 1'b0) + + ) + begin + + stall_wb_load <= 1'b0; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + end + end + + if (stall_m == 1'b0) + wb_load_complete <= 1'b0; + + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) + stall_wb_load <= 1'b1; + + if ((kill_m == 1'b1) || (exception_m == 1'b1)) + stall_wb_load <= 1'b0; end -endgenerate +end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - dc_re <= 1'b0; + begin + sign_extend_m <= 1'b0; + size_m <= 2'b00; + byte_enable_m <= 1'b0; + store_data_m <= { 32{1'b0}}; + + + dcache_select_m <= 1'b0; + + + + + + + + + + + + wb_select_m <= 1'b0; + end else begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - dc_re <= debug_csr_write_data[1]; + if (stall_m == 1'b0) + begin + sign_extend_m <= sign_extend_x; + size_m <= size_x; + byte_enable_m <= byte_enable_x; + store_data_m <= store_data_x; + + + dcache_select_m <= dcache_select_x; + + + + + + + + + + + + wb_select_m <= wb_select_x; + end end -end +end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - state <= 3'b000; - dc_ss <= 1'b0; + size_w <= 2'b00; + data_w <= { 32{1'b0}}; + sign_extend_w <= 1'b0; end else begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - begin - dc_ss <= debug_csr_write_data[0]; - if (debug_csr_write_data[0] == 1'b0) - state <= 3'b000; - else - state <= 3'b001; - end - case (state) - 3'b001: - begin - if ( ( (eret_q_x == 1'b1) - || (bret_q_x == 1'b1) - ) - && (stall_x == 1'b0) - ) - state <= 3'b010; - end - 3'b010: - begin - if ((q_x == 1'b1) && (stall_x == 1'b0)) - state <= 3'b011; - end - 3'b011: - begin - if (dcache_refill_request == 1'b1) - state <= 3'b010; - else - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - begin - dc_ss <= 1'b0; - state <= 3'b100; - end - end - 3'b100: - begin - if (dcache_refill_request == 1'b1) - state <= 3'b010; - else - state <= 3'b000; - end - endcase + size_w <= size_m; + + + + + + data_w <= data_m; + + sign_extend_w <= sign_extend_m; + end +end + + + + + + + + +always @(posedge clk_i) +begin + if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) + begin + if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) + $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) + $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end end + + + endmodule -module lm32_instruction_unit_full_debug ( - clk_i, - rst_i, - stall_a, - stall_f, - stall_d, - stall_x, - stall_m, - valid_f, - valid_d, - kill_f, - branch_predict_taken_d, - branch_predict_address_d, - branch_taken_x, - branch_target_x, - exception_m, - branch_taken_m, - branch_mispredict_taken_m, - branch_target_m, - iflush, - dcache_restart_request, - dcache_refill_request, - dcache_refilling, - i_dat_i, - i_ack_i, - i_err_i, - i_rty_i, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - pc_f, - pc_d, - pc_x, - pc_m, - pc_w, - icache_stall_request, - icache_restart_request, - icache_refill_request, - icache_refilling, - i_dat_o, - i_adr_o, - i_cyc_o, - i_sel_o, - i_stb_o, - i_we_o, - i_cti_o, - i_lock_o, - i_bte_o, - jtag_read_data, - jtag_access_complete, - bus_error_d, - instruction_f, - instruction_d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_full ( + + instruction, + + d_result_sel_0, + d_result_sel_1, + x_result_sel_csr, + + + x_result_sel_mc_arith, + + + + + + + + + x_result_sel_sext, + + + x_result_sel_logic, + + + + + x_result_sel_add, + m_result_sel_compare, + + + m_result_sel_shift, + + + w_result_sel_load, + + + w_result_sel_mul, + + + x_bypass_enable, + m_bypass_enable, + read_enable_0, + read_idx_0, + read_enable_1, + read_idx_1, + write_enable, + write_idx, + immediate, + branch_offset, + load, + store, + size, + sign_extend, + adder_op, + logic_op, + + + direction, + + + + + + + + + + + + + + divide, + modulus, + + + branch, + branch_reg, + condition, + bi_conditional, + bi_unconditional, + + + + + scall, + eret, + + + + + + + + + csr_write_enable ); -parameter eba_reset = 32'h00000000; -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam eba_reset_minus_4 = eba_reset - 4; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_f; -input stall_d; -input stall_x; -input stall_m; -input valid_f; -input valid_d; -input kill_f; -input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -input branch_taken_x; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; -input exception_m; -input branch_taken_m; -input branch_mispredict_taken_m; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; -input iflush; -input dcache_restart_request; -input dcache_refill_request; -input dcache_refilling; -input [ (32-1):0] i_dat_i; -input i_ack_i; -input i_err_i; -input i_rty_i; -input jtag_read_enable; -input jtag_write_enable; -input [ 7:0] jtag_write_data; -input [ (32-1):0] jtag_address; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -output icache_stall_request; -wire icache_stall_request; -output icache_restart_request; -wire icache_restart_request; -output icache_refill_request; -wire icache_refill_request; -output icache_refilling; -wire icache_refilling; -output [ (32-1):0] i_dat_o; -reg [ (32-1):0] i_dat_o; -output [ (32-1):0] i_adr_o; -reg [ (32-1):0] i_adr_o; -output i_cyc_o; -reg i_cyc_o; -output [ (4-1):0] i_sel_o; -reg [ (4-1):0] i_sel_o; -output i_stb_o; -reg i_stb_o; -output i_we_o; -reg i_we_o; -output [ (3-1):0] i_cti_o; -reg [ (3-1):0] i_cti_o; -output i_lock_o; -reg i_lock_o; -output [ (2-1):0] i_bte_o; -wire [ (2-1):0] i_bte_o; -output [ 7:0] jtag_read_data; -reg [ 7:0] jtag_read_data; -output jtag_access_complete; -wire jtag_access_complete; -output bus_error_d; -reg bus_error_d; -output [ (32-1):0] instruction_f; -wire [ (32-1):0] instruction_f; -output [ (32-1):0] instruction_d; -reg [ (32-1):0] instruction_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; -wire icache_read_enable_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; -reg icache_refill_ready; -reg [ (32-1):0] icache_refill_data; -wire [ (32-1):0] icache_data_f; -wire [ (3-1):0] first_cycle_type; -wire [ (3-1):0] next_cycle_type; -wire last_word; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; -reg bus_error_f; -reg jtag_access; + + + + + +input [ (32-1):0] instruction; + + + + + +output [ 0:0] d_result_sel_0; +reg [ 0:0] d_result_sel_0; +output [ 1:0] d_result_sel_1; +reg [ 1:0] d_result_sel_1; +output x_result_sel_csr; +reg x_result_sel_csr; + + +output x_result_sel_mc_arith; +reg x_result_sel_mc_arith; + + + + + + + + + +output x_result_sel_sext; +reg x_result_sel_sext; + + +output x_result_sel_logic; +reg x_result_sel_logic; + + + + + +output x_result_sel_add; +reg x_result_sel_add; +output m_result_sel_compare; +reg m_result_sel_compare; + + +output m_result_sel_shift; +reg m_result_sel_shift; + + +output w_result_sel_load; +reg w_result_sel_load; + + +output w_result_sel_mul; +reg w_result_sel_mul; + + +output x_bypass_enable; +wire x_bypass_enable; +output m_bypass_enable; +wire m_bypass_enable; +output read_enable_0; +wire read_enable_0; +output [ (5-1):0] read_idx_0; +wire [ (5-1):0] read_idx_0; +output read_enable_1; +wire read_enable_1; +output [ (5-1):0] read_idx_1; +wire [ (5-1):0] read_idx_1; +output write_enable; +wire write_enable; +output [ (5-1):0] write_idx; +wire [ (5-1):0] write_idx; +output [ (32-1):0] immediate; +wire [ (32-1):0] immediate; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +output load; +wire load; +output store; +wire store; +output [ 1:0] size; +wire [ 1:0] size; +output sign_extend; +wire sign_extend; +output adder_op; +wire adder_op; +output [ 3:0] logic_op; +wire [ 3:0] logic_op; + + +output direction; +wire direction; + + + + + + + + + + + + + + + + +output divide; +wire divide; +output modulus; +wire modulus; + + +output branch; +wire branch; +output branch_reg; +wire branch_reg; +output [ (3-1):0] condition; +wire [ (3-1):0] condition; +output bi_conditional; +wire bi_conditional; +output bi_unconditional; +wire bi_unconditional; + + + + + +output scall; +wire scall; +output eret; +wire eret; + + + + + + + + + + +output csr_write_enable; +wire csr_write_enable; + + + + + +wire [ (32-1):0] extended_immediate; +wire [ (32-1):0] high_immediate; +wire [ (32-1):0] call_immediate; +wire [ (32-1):0] branch_immediate; +wire sign_extend_immediate; +wire select_high_immediate; +wire select_call_immediate; + +wire op_add; +wire op_and; +wire op_andhi; +wire op_b; +wire op_bi; +wire op_be; +wire op_bg; +wire op_bge; +wire op_bgeu; +wire op_bgu; +wire op_bne; +wire op_call; +wire op_calli; +wire op_cmpe; +wire op_cmpg; +wire op_cmpge; +wire op_cmpgeu; +wire op_cmpgu; +wire op_cmpne; + + +wire op_divu; + + +wire op_lb; +wire op_lbu; +wire op_lh; +wire op_lhu; +wire op_lw; + + +wire op_modu; + + + + +wire op_mul; + + +wire op_nor; +wire op_or; +wire op_orhi; +wire op_raise; +wire op_rcsr; +wire op_sb; + + +wire op_sextb; +wire op_sexth; + + +wire op_sh; + + +wire op_sl; + + +wire op_sr; +wire op_sru; +wire op_sub; +wire op_sw; + + + + +wire op_wcsr; +wire op_xnor; +wire op_xor; + +wire arith; +wire logical; +wire cmp; +wire bra; +wire call; + + +wire shift; + + + + + + + + +wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -6628,6 +20173,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -6640,652 +20186,5452 @@ begin clogb2_v1 = i-1; end endfunction -lm32_icache_full_debug #( - .associativity (associativity), - .sets (sets), - .bytes_per_line (bytes_per_line), - .base_address (base_address), - .limit (limit) - ) icache ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .branch_predict_taken_d (branch_predict_taken_d), - .valid_d (valid_d), - .address_a (pc_a), - .address_f (pc_f), - .read_enable_f (icache_read_enable_f), - .refill_ready (icache_refill_ready), - .refill_data (icache_refill_data), - .iflush (iflush), - .stall_request (icache_stall_request), - .restart_request (icache_restart_request), - .refill_request (icache_refill_request), - .refill_address (icache_refill_address), - .refilling (icache_refilling), - .inst (icache_data_f) - ); -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - && (dcache_restart_request == 1'b0) - ; + + + + + + + + + +assign op_add = instruction[ 30:26] == 5'b01101; +assign op_and = instruction[ 30:26] == 5'b01000; +assign op_andhi = instruction[ 31:26] == 6'b011000; +assign op_b = instruction[ 31:26] == 6'b110000; +assign op_bi = instruction[ 31:26] == 6'b111000; +assign op_be = instruction[ 31:26] == 6'b010001; +assign op_bg = instruction[ 31:26] == 6'b010010; +assign op_bge = instruction[ 31:26] == 6'b010011; +assign op_bgeu = instruction[ 31:26] == 6'b010100; +assign op_bgu = instruction[ 31:26] == 6'b010101; +assign op_bne = instruction[ 31:26] == 6'b010111; +assign op_call = instruction[ 31:26] == 6'b110110; +assign op_calli = instruction[ 31:26] == 6'b111110; +assign op_cmpe = instruction[ 30:26] == 5'b11001; +assign op_cmpg = instruction[ 30:26] == 5'b11010; +assign op_cmpge = instruction[ 30:26] == 5'b11011; +assign op_cmpgeu = instruction[ 30:26] == 5'b11100; +assign op_cmpgu = instruction[ 30:26] == 5'b11101; +assign op_cmpne = instruction[ 30:26] == 5'b11111; + + +assign op_divu = instruction[ 31:26] == 6'b100011; + + +assign op_lb = instruction[ 31:26] == 6'b000100; +assign op_lbu = instruction[ 31:26] == 6'b010000; +assign op_lh = instruction[ 31:26] == 6'b000111; +assign op_lhu = instruction[ 31:26] == 6'b001011; +assign op_lw = instruction[ 31:26] == 6'b001010; + + +assign op_modu = instruction[ 31:26] == 6'b110001; + + + + +assign op_mul = instruction[ 30:26] == 5'b00010; + + +assign op_nor = instruction[ 30:26] == 5'b00001; +assign op_or = instruction[ 30:26] == 5'b01110; +assign op_orhi = instruction[ 31:26] == 6'b011110; +assign op_raise = instruction[ 31:26] == 6'b101011; +assign op_rcsr = instruction[ 31:26] == 6'b100100; +assign op_sb = instruction[ 31:26] == 6'b001100; + + +assign op_sextb = instruction[ 31:26] == 6'b101100; +assign op_sexth = instruction[ 31:26] == 6'b110111; + + +assign op_sh = instruction[ 31:26] == 6'b000011; + + +assign op_sl = instruction[ 30:26] == 5'b01111; + + +assign op_sr = instruction[ 30:26] == 5'b00101; +assign op_sru = instruction[ 30:26] == 5'b00000; +assign op_sub = instruction[ 31:26] == 6'b110010; +assign op_sw = instruction[ 31:26] == 6'b010110; + + + + +assign op_wcsr = instruction[ 31:26] == 6'b110100; +assign op_xnor = instruction[ 30:26] == 5'b01001; +assign op_xor = instruction[ 30:26] == 5'b00110; + + +assign arith = op_add | op_sub; +assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; +assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; +assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; +assign bi_unconditional = op_bi; +assign bra = op_b | bi_unconditional | bi_conditional; +assign call = op_call | op_calli; + + +assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + +assign sext = op_sextb | op_sexth; + + + + + + + + +assign divide = op_divu; +assign modulus = op_modu; + + +assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; +assign store = op_sb | op_sh | op_sw; + + always @(*) begin - if (dcache_restart_request == 1'b1) - pc_a = restart_address; - else - if (branch_taken_m == 1'b1) - if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) - pc_a = pc_x; - else - pc_a = branch_target_m; - else if (branch_taken_x == 1'b1) - pc_a = branch_target_x; - else - if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) - pc_a = branch_predict_address_d; - else - if (icache_restart_request == 1'b1) - pc_a = restart_address; - else - pc_a = pc_f + 1'b1; + + if (call) + d_result_sel_0 = 1'b1; + else + d_result_sel_0 = 1'b0; + if (call) + d_result_sel_1 = 2'b00; + else if ((instruction[31] == 1'b0) && !bra) + d_result_sel_1 = 2'b10; + else + d_result_sel_1 = 2'b01; + + x_result_sel_csr = 1'b0; + + + x_result_sel_mc_arith = 1'b0; + + + + + + + + + x_result_sel_sext = 1'b0; + + + x_result_sel_logic = 1'b0; + + + + + x_result_sel_add = 1'b0; + if (op_rcsr) + x_result_sel_csr = 1'b1; + + + + + + + + + + else if (divide | modulus) + x_result_sel_mc_arith = 1'b1; + + + + + + + + + + + + + + + + + else if (sext) + x_result_sel_sext = 1'b1; + + + else if (logical) + x_result_sel_logic = 1'b1; + + + + + + else + x_result_sel_add = 1'b1; + + + + m_result_sel_compare = cmp; + + + m_result_sel_shift = shift; + + + + + w_result_sel_load = load; + + + w_result_sel_mul = op_mul; + + +end + + +assign x_bypass_enable = arith + | logical + + + + + + + + + + + + | divide + | modulus + + + + + + + + + | sext + + + + + + + | op_rcsr + ; + +assign m_bypass_enable = x_bypass_enable + + + | shift + + + | cmp + ; + +assign read_enable_0 = ~(op_bi | op_calli); +assign read_idx_0 = instruction[25:21]; + +assign read_enable_1 = ~(op_bi | op_calli | load); +assign read_idx_1 = instruction[20:16]; + +assign write_enable = ~(bra | op_raise | store | op_wcsr); +assign write_idx = call + ? 5'd29 + : instruction[31] == 1'b0 + ? instruction[20:16] + : instruction[15:11]; + + +assign size = instruction[27:26]; + +assign sign_extend = instruction[28]; + +assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + +assign logic_op = instruction[29:26]; + + + +assign direction = instruction[29]; + + + +assign branch = bra | call; +assign branch_reg = op_call | op_b; +assign condition = instruction[28:26]; + + + + +assign scall = op_raise & instruction[2]; +assign eret = op_b & (instruction[25:21] == 5'd30); + + + + + + + + + + +assign csr_write_enable = op_wcsr; + + + +assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); +assign select_high_immediate = op_andhi | op_orhi; +assign select_call_immediate = instruction[31]; + +assign high_immediate = {instruction[15:0], 16'h0000}; +assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; +assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; +assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + +assign immediate = select_high_immediate == 1'b1 + ? high_immediate + : extended_immediate; + +assign branch_offset = select_call_immediate == 1'b1 + ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) + : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_icache_full ( + + clk_i, + rst_i, + stall_a, + stall_f, + address_a, + address_f, + read_enable_f, + refill_ready, + refill_data, + iflush, + + + + + valid_d, + branch_predict_taken_d, + + stall_request, + restart_request, + refill_request, + refill_address, + refilling, + inst + ); + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + +localparam addr_offset_width = clogb2(bytes_per_line)-1-2; +localparam addr_set_width = clogb2(sets)-1; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); +localparam addr_set_lsb = (addr_offset_msb+1); +localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); +localparam addr_tag_lsb = (addr_set_msb+1); +localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; +localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + +input clk_i; +input rst_i; + +input stall_a; +input stall_f; + +input valid_d; +input branch_predict_taken_d; + +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; +input read_enable_f; + +input refill_ready; +input [ (32-1):0] refill_data; + +input iflush; + + + + + + + + + +output stall_request; +wire stall_request; +output restart_request; +reg restart_request; +output refill_request; +wire refill_request; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +output refilling; +reg refilling; +output [ (32-1):0] inst; +wire [ (32-1):0] inst; + + + + + +wire enable; +wire [0:associativity-1] way_mem_we; +wire [ (32-1):0] way_data[0:associativity-1]; +wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; +wire [0:associativity-1] way_valid; +wire [0:associativity-1] way_match; +wire miss; + +wire [ (addr_set_width-1):0] tmem_read_address; +wire [ (addr_set_width-1):0] tmem_write_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; +wire [ ((addr_tag_width+1)-1):0] tmem_write_data; + +reg [ 3:0] state; +wire flushing; +wire check; +wire refill; + +reg [associativity-1:0] refill_way_select; +reg [ addr_offset_msb:addr_offset_lsb] refill_offset; +wire last_refill; +reg [ (addr_set_width-1):0] flush_set; + +genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -assign instruction_f = icache_data_f; -assign i_bte_o = 2'b00; +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + generate + for (i = 0; i < associativity; i = i + 1) + begin : memories + + lm32_ram + #( + + .data_width (32), + .address_width ( (addr_offset_width+addr_set_width)) + +) + way_0_data_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (dmem_read_address), + .enable_read (enable), + .write_address (dmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i]), + .write_data (refill_data), + + .read_data (way_data[i]) + ); + + lm32_ram + #( + + .data_width ( (addr_tag_width+1)), + .address_width ( addr_set_width) + + ) + way_0_tag_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (tmem_read_address), + .enable_read (enable), + .write_address (tmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i] | flushing), + .write_data (tmem_write_data), + + .read_data ({way_tag[i], way_valid[i]}) + ); + + end +endgenerate + + + + + + generate - case (bytes_per_line) - 4: - begin -assign first_cycle_type = 3'b111; -assign next_cycle_type = 3'b111; -assign last_word = 1'b1; -assign first_address = icache_refill_address; + for (i = 0; i < associativity; i = i + 1) + begin : match +assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); end - 8: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = 3'b111; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; +endgenerate + + +generate + if (associativity == 1) + begin : inst_1 +assign inst = way_match[0] ? way_data[0] : 32'b0; end - 16: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + else if (associativity == 2) + begin : inst_2 +assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); end - endcase endgenerate -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + + +generate + if (bytes_per_line > 4) +assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; + else +assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; +endgenerate + +assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + +assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; +assign tmem_write_address = flushing + ? flush_set + : refill_address[ addr_set_msb:addr_set_lsb]; + + +generate + if (bytes_per_line > 4) +assign last_refill = refill_offset == {addr_offset_width{1'b1}}; + else +assign last_refill = 1'b1; +endgenerate + + +assign enable = (stall_a == 1'b0); + + +generate + if (associativity == 1) + begin : we_1 +assign way_mem_we[0] = (refill_ready == 1'b1); end else - begin - if (stall_f == 1'b0) - pc_f <= pc_a; - if (stall_d == 1'b0) - pc_d <= pc_f; - if (stall_x == 1'b0) - pc_x <= pc_d; - if (stall_m == 1'b0) - pc_m <= pc_x; - pc_w <= pc_m; + begin : we_2 +assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); +assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); end -end +endgenerate + + +assign tmem_write_data[ 0] = last_refill & !flushing; +assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + +assign flushing = |state[1:0]; +assign check = state[2]; +assign refill = state[3]; + +assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); +assign stall_request = (check == 1'b0); +assign refill_request = (refill == 1'b1); + + + + + + +generate + if (associativity >= 2) + begin : way_select always @(posedge clk_i ) begin if (rst_i == 1'b1) - restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; else - begin - if (dcache_refill_request == 1'b1) - restart_address <= pc_w; - else if ((icache_refill_request == 1'b1) && (!dcache_refilling) && (!dcache_restart_request)) - restart_address <= icache_refill_address; + begin + if (miss == 1'b1) + refill_way_select <= {refill_way_select[0], refill_way_select[1]}; end end -assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); -always @(*) + end +endgenerate + + +always @(posedge clk_i ) begin - case (jtag_address[1:0]) - 2'b00: jtag_read_data = i_dat_i[ 31:24]; - 2'b01: jtag_read_data = i_dat_i[ 23:16]; - 2'b10: jtag_read_data = i_dat_i[ 15:8]; - 2'b11: jtag_read_data = i_dat_i[ 7:0]; - endcase + if (rst_i == 1'b1) + refilling <= 1'b0; + else + refilling <= refill; end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - bus_error_f <= 1'b0; - i_we_o <= 1'b0; - i_sel_o <= 4'b1111; - jtag_access <= 1'b0; + state <= 4'b0001; + flush_set <= { addr_set_width{1'b1}}; + refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + restart_request <= 1'b0; end - else - begin - icache_refill_ready <= 1'b0; - if (i_cyc_o == 1'b1) - begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + else + begin + case (state) + + + 4'b0001: + begin + if (flush_set == { addr_set_width{1'b0}}) + state <= 4'b0100; + flush_set <= flush_set - 1'b1; + end + + + 4'b0010: + begin + if (flush_set == { addr_set_width{1'b0}}) + + + + + + + state <= 4'b0100; + + flush_set <= flush_set - 1'b1; + end + + + 4'b0100: + begin + if (stall_a == 1'b0) + restart_request <= 1'b0; + if (iflush == 1'b1) begin - if (jtag_access == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_we_o <= 1'b0; - jtag_access <= 1'b0; - end - else - begin - if (last_word == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end + refill_address <= address_f; + state <= 4'b0010; end - if (i_err_i == 1'b1) + else if (miss == 1'b1) begin - bus_error_f <= 1'b1; - $display ("Instruction bus error. Address: %x", i_adr_o); + refill_address <= address_f; + state <= 4'b1000; end end - else - begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) - begin - i_sel_o <= 4'b1111; - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; - bus_error_f <= 1'b0; - end - else + + + 4'b1000: + begin + if (refill_ready == 1'b1) begin - if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + if (last_refill == 1'b1) begin - case (jtag_address[1:0]) - 2'b00: i_sel_o <= 4'b1000; - 2'b01: i_sel_o <= 4'b0100; - 2'b10: i_sel_o <= 4'b0010; - 2'b11: i_sel_o <= 4'b0001; - endcase - i_adr_o <= jtag_address; - i_dat_o <= {4{jtag_write_data}}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_we_o <= jtag_write_enable; - i_cti_o <= 3'b111; - jtag_access <= 1'b1; + restart_request <= 1'b1; + state <= 4'b0100; end - end - if (branch_taken_x == 1'b1) - bus_error_f <= 1'b0; - if (branch_taken_m == 1'b1) - bus_error_f <= 1'b0; + end end + + endcase end end + +generate + if (bytes_per_line > 4) + begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else begin - instruction_d <= { 32{1'b0}}; - bus_error_d <= 1'b0; - end - else - begin - if (stall_d == 1'b0) - begin - instruction_d <= instruction_f; - bus_error_d <= bus_error_f; + case (state) + + + 4'b0100: + begin + if (iflush == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else if (miss == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + end + + + 4'b1000: + begin + if (refill_ready == 1'b1) + refill_offset <= refill_offset + 1'b1; end + + endcase + end +end end -end +endgenerate + endmodule -module lm32_jtag_full_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_dcache_full ( + clk_i, - rst_i, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - csr, - csr_write_enable, - csr_write_data, + rst_i, + stall_a, stall_x, - jtag_read_data, - jtag_access_complete, - exception_q_w, - jtx_csr_read_data, - jrx_csr_read_data, - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - jtag_break, - jtag_reset, - jtag_reg_d, - jtag_reg_addr_d + stall_m, + address_x, + address_m, + load_q_m, + store_q_m, + store_data, + store_byte_select, + refill_ready, + refill_data, + dflush, + + stall_request, + restart_request, + refill_request, + refill_address, + refilling, + load_data ); + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + +localparam addr_offset_width = clogb2(bytes_per_line)-1-2; +localparam addr_set_width = clogb2(sets)-1; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); +localparam addr_set_lsb = (addr_offset_msb+1); +localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); +localparam addr_tag_lsb = (addr_set_msb+1); +localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; +localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + input clk_i; input rst_i; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; -input [ (5-1):0] csr; -input csr_write_enable; -input [ (32-1):0] csr_write_data; + +input stall_a; input stall_x; -input [ 7:0] jtag_read_data; -input jtag_access_complete; -input exception_q_w; -output [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jtx_csr_read_data; -output [ (32-1):0] jrx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; -output jtag_csr_write_enable; -reg jtag_csr_write_enable; -output [ (32-1):0] jtag_csr_write_data; -wire [ (32-1):0] jtag_csr_write_data; -output [ (5-1):0] jtag_csr; -wire [ (5-1):0] jtag_csr; -output jtag_read_enable; -reg jtag_read_enable; -output jtag_write_enable; -reg jtag_write_enable; -output [ 7:0] jtag_write_data; -wire [ 7:0] jtag_write_data; -output [ (32-1):0] jtag_address; -wire [ (32-1):0] jtag_address; -output jtag_break; -reg jtag_break; -output jtag_reset; -reg jtag_reset; -output [ 7:0] jtag_reg_d; -reg [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; -reg rx_update; -reg rx_update_r; -reg rx_update_r_r; -reg rx_update_r_r_r; -wire [ 7:0] rx_byte; -wire [2:0] rx_addr; -reg [ 7:0] uart_tx_byte; -reg uart_tx_valid; -reg [ 7:0] uart_rx_byte; -reg uart_rx_valid; -reg [ 3:0] command; -reg [ 7:0] jtag_byte_0; -reg [ 7:0] jtag_byte_1; -reg [ 7:0] jtag_byte_2; -reg [ 7:0] jtag_byte_3; -reg [ 7:0] jtag_byte_4; -reg processing; -reg [ 3:0] state; -assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_csr = jtag_byte_4[ (5-1):0]; -assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_write_data = jtag_byte_4; -assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; -assign jtag_reg_addr_d[2] = processing; -assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; -assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; -assign rx_byte = jtag_reg_q; -assign rx_addr = jtag_reg_addr_q; -always @(posedge clk_i ) +input stall_m; + +input [ (32-1):0] address_x; +input [ (32-1):0] address_m; +input load_q_m; +input store_q_m; +input [ (32-1):0] store_data; +input [ (4-1):0] store_byte_select; + +input refill_ready; +input [ (32-1):0] refill_data; + +input dflush; + + + + + +output stall_request; +wire stall_request; +output restart_request; +reg restart_request; +output refill_request; +reg refill_request; +output [ (32-1):0] refill_address; +reg [ (32-1):0] refill_address; +output refilling; +reg refilling; +output [ (32-1):0] load_data; +wire [ (32-1):0] load_data; + + + + + +wire read_port_enable; +wire write_port_enable; +wire [0:associativity-1] way_tmem_we; +wire [0:associativity-1] way_dmem_we; +wire [ (32-1):0] way_data[0:associativity-1]; +wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; +wire [0:associativity-1] way_valid; +wire [0:associativity-1] way_match; +wire miss; + +wire [ (addr_set_width-1):0] tmem_read_address; +wire [ (addr_set_width-1):0] tmem_write_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; +wire [ ((addr_tag_width+1)-1):0] tmem_write_data; +reg [ (32-1):0] dmem_write_data; + +reg [ 2:0] state; +wire flushing; +wire check; +wire refill; + +wire valid_store; +reg [associativity-1:0] refill_way_select; +reg [ addr_offset_msb:addr_offset_lsb] refill_offset; +wire last_refill; +reg [ (addr_set_width-1):0] flush_set; + +genvar i, j; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + generate + for (i = 0; i < associativity; i = i + 1) + begin : memories + + if ( (addr_offset_width+addr_set_width) < 11) + begin : data_memories + lm32_ram + #( + + .data_width (32), + .address_width ( (addr_offset_width+addr_set_width)) + + ) way_0_data_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (dmem_read_address), + .enable_read (read_port_enable), + .write_address (dmem_write_address), + .enable_write (write_port_enable), + .write_enable (way_dmem_we[i]), + .write_data (dmem_write_data), + + .read_data (way_data[i]) + ); + end + else + begin + for (j = 0; j < 4; j = j + 1) + begin : byte_memories + lm32_ram + #( + + .data_width (8), + .address_width ( (addr_offset_width+addr_set_width)) + + ) way_0_data_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (dmem_read_address), + .enable_read (read_port_enable), + .write_address (dmem_write_address), + .enable_write (write_port_enable), + .write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)), + .write_data (dmem_write_data[(j+1)*8-1:j*8]), + + .read_data (way_data[i][(j+1)*8-1:j*8]) + ); + end + end + + + lm32_ram + #( + + .data_width ( (addr_tag_width+1)), + .address_width ( addr_set_width) + + ) way_0_tag_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (tmem_read_address), + .enable_read (read_port_enable), + .write_address (tmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_tmem_we[i]), + .write_data (tmem_write_data), + + .read_data ({way_tag[i], way_valid[i]}) + ); + end + + endgenerate + + + + + + +generate + for (i = 0; i < associativity; i = i + 1) + begin : match +assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[ addr_tag_msb:addr_tag_lsb], 1'b1}); + end +endgenerate + + +generate + if (associativity == 1) + begin : data_1 +assign load_data = way_data[0]; + end + else if (associativity == 2) + begin : data_2 +assign load_data = way_match[0] ? way_data[0] : way_data[1]; + end +endgenerate + +generate + if ( (addr_offset_width+addr_set_width) < 11) + begin + +always @(*) begin - if (rst_i == 1'b1) + if (refill == 1'b1) + dmem_write_data = refill_data; + else begin - rx_update <= 1'b0; - rx_update_r <= 1'b0; - rx_update_r_r <= 1'b0; - rx_update_r_r_r <= 1'b0; + dmem_write_data[ 7:0] = store_byte_select[0] ? store_data[ 7:0] : load_data[ 7:0]; + dmem_write_data[ 15:8] = store_byte_select[1] ? store_data[ 15:8] : load_data[ 15:8]; + dmem_write_data[ 23:16] = store_byte_select[2] ? store_data[ 23:16] : load_data[ 23:16]; + dmem_write_data[ 31:24] = store_byte_select[3] ? store_data[ 31:24] : load_data[ 31:24]; + end +end end else begin - rx_update <= jtag_update; - rx_update_r <= rx_update; - rx_update_r_r <= rx_update_r; - rx_update_r_r_r <= rx_update_r_r; + +always @(*) +begin + if (refill == 1'b1) + dmem_write_data = refill_data; + else + dmem_write_data = store_data; +end + end +endgenerate + + +generate + if (bytes_per_line > 4) +assign dmem_write_address = (refill == 1'b1) + ? {refill_address[ addr_set_msb:addr_set_lsb], refill_offset} + : address_m[ addr_set_msb:addr_offset_lsb]; + else +assign dmem_write_address = (refill == 1'b1) + ? refill_address[ addr_set_msb:addr_set_lsb] + : address_m[ addr_set_msb:addr_offset_lsb]; +endgenerate +assign dmem_read_address = address_x[ addr_set_msb:addr_offset_lsb]; + +assign tmem_write_address = (flushing == 1'b1) + ? flush_set + : refill_address[ addr_set_msb:addr_set_lsb]; +assign tmem_read_address = address_x[ addr_set_msb:addr_set_lsb]; + + +generate + if (bytes_per_line > 4) +assign last_refill = refill_offset == {addr_offset_width{1'b1}}; + else +assign last_refill = 1'b1; +endgenerate + + +assign read_port_enable = (stall_x == 1'b0); +assign write_port_enable = (refill_ready == 1'b1) || !stall_m; + + +assign valid_store = (store_q_m == 1'b1) && (check == 1'b1); + + +generate + if (associativity == 1) + begin : we_1 +assign way_dmem_we[0] = (refill_ready == 1'b1) || ((valid_store == 1'b1) && (way_match[0] == 1'b1)); +assign way_tmem_we[0] = (refill_ready == 1'b1) || (flushing == 1'b1); + end + else + begin : we_2 +assign way_dmem_we[0] = ((refill_ready == 1'b1) && (refill_way_select[0] == 1'b1)) || ((valid_store == 1'b1) && (way_match[0] == 1'b1)); +assign way_dmem_we[1] = ((refill_ready == 1'b1) && (refill_way_select[1] == 1'b1)) || ((valid_store == 1'b1) && (way_match[1] == 1'b1)); +assign way_tmem_we[0] = ((refill_ready == 1'b1) && (refill_way_select[0] == 1'b1)) || (flushing == 1'b1); +assign way_tmem_we[1] = ((refill_ready == 1'b1) && (refill_way_select[1] == 1'b1)) || (flushing == 1'b1); + end +endgenerate + + +assign tmem_write_data[ 0] = ((last_refill == 1'b1) || (valid_store == 1'b1)) && (flushing == 1'b0); +assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + +assign flushing = state[0]; +assign check = state[1]; +assign refill = state[2]; + +assign miss = (~(|way_match)) && (load_q_m == 1'b1) && (stall_m == 1'b0); +assign stall_request = (check == 1'b0); + + + + + + +generate + if (associativity >= 2) + begin : way_select +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + else + begin + if (refill_request == 1'b1) + refill_way_select <= {refill_way_select[0], refill_way_select[1]}; end end + end +endgenerate + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refilling <= 1'b0; + else + refilling <= refill; +end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - state <= 4'h0; - command <= 4'b0000; - jtag_reg_d <= 8'h00; - processing <= 1'b0; - jtag_csr_write_enable <= 1'b0; - jtag_read_enable <= 1'b0; - jtag_write_enable <= 1'b0; - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - uart_tx_byte <= 8'h00; - uart_tx_valid <= 1'b0; - uart_rx_byte <= 8'h00; - uart_rx_valid <= 1'b0; + state <= 3'b001; + flush_set <= { addr_set_width{1'b1}}; + refill_request <= 1'b0; + refill_address <= { 32{1'bx}}; + restart_request <= 1'b0; end - else + else begin - if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) - begin - case (csr) - 5'he: - begin - uart_tx_byte <= csr_write_data[ 7:0]; - uart_tx_valid <= 1'b1; - end - 5'hf: - begin - uart_rx_valid <= 1'b0; - end - endcase - end - if (exception_q_w == 1'b1) - begin - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - end case (state) - 4'h0: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - command <= rx_byte[7:4]; - case (rx_addr) - 3'b000: - begin - case (rx_byte[7:4]) - 4'b0001: - state <= 4'h1; - 4'b0011: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 4'h6; - end - 4'b0010: - state <= 4'h1; - 4'b0100: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 5; - end - 4'b0101: - state <= 4'h1; - 4'b0110: - begin - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - jtag_break <= 1'b1; - end - 4'b0111: - begin - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - jtag_reset <= 1'b1; - end - endcase - end - 3'b001: - begin - uart_rx_byte <= rx_byte; - uart_rx_valid <= 1'b1; - end - 3'b010: - begin - jtag_reg_d <= uart_tx_byte; - uart_tx_valid <= 1'b0; - end - default: - ; - endcase - end - end - 4'h1: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_0 <= rx_byte; - state <= 4'h2; - end - end - 4'h2: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_1 <= rx_byte; - state <= 4'h3; - end - end - 4'h3: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_2 <= rx_byte; - state <= 4'h4; - end - end - 4'h4: + + + 3'b001: begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_3 <= rx_byte; - if (command == 4'b0001) - state <= 4'h6; - else - state <= 4'h5; - end + if (flush_set == { addr_set_width{1'b0}}) + state <= 3'b010; + flush_set <= flush_set - 1'b1; end - 4'h5: + + + 3'b010: begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + if (stall_a == 1'b0) + restart_request <= 1'b0; + if (miss == 1'b1) begin - jtag_byte_4 <= rx_byte; - state <= 4'h6; + refill_request <= 1'b1; + refill_address <= address_m; + state <= 3'b100; end + else if (dflush == 1'b1) + state <= 3'b001; end - 4'h6: + + + 3'b100: begin - case (command) - 4'b0001, - 4'b0011: - begin - jtag_read_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0010, - 4'b0100: - begin - jtag_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0101: + refill_request <= 1'b0; + if (refill_ready == 1'b1) begin - jtag_csr_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h8; + if (last_refill == 1'b1) + begin + restart_request <= 1'b1; + state <= 3'b010; + end end - endcase end - 4'h7: + + endcase + end +end + +generate + if (bytes_per_line > 4) + begin + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else + begin + case (state) + + + 3'b010: begin - if (jtag_access_complete == 1'b1) - begin - jtag_read_enable <= 1'b0; - jtag_reg_d <= jtag_read_data; - jtag_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - end - 4'h8: + if (miss == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + end + + + 3'b100: begin - jtag_csr_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - endcase + if (refill_ready == 1'b1) + refill_offset <= refill_offset + 1'b1; + end + + endcase + end +end + end +endgenerate + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_full ( + + clk_i, + rst_i, + + stall_a, + stall_f, + stall_d, + stall_x, + stall_m, + valid_f, + valid_d, + kill_f, + branch_predict_taken_d, + branch_predict_address_d, + + + branch_taken_x, + branch_target_x, + + + exception_m, + branch_taken_m, + branch_mispredict_taken_m, + branch_target_m, + + + iflush, + + + + + dcache_restart_request, + dcache_refill_request, + dcache_refilling, + + + + + + i_dat_i, + i_ack_i, + i_err_i, + i_rty_i, + + + + + + + + + + + + pc_f, + pc_d, + pc_x, + pc_m, + pc_w, + + + icache_stall_request, + icache_restart_request, + icache_refill_request, + icache_refilling, + + + + + + i_dat_o, + i_adr_o, + i_cyc_o, + i_sel_o, + i_stb_o, + i_we_o, + i_cti_o, + i_lock_o, + i_bte_o, + + + + + + + + + + + + + + + + bus_error_d, + + + + + instruction_f, + + + instruction_d + ); + + + + + +parameter eba_reset = 32'h00000000; +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam eba_reset_minus_4 = eba_reset - 4; +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + +input clk_i; +input rst_i; + +input stall_a; +input stall_f; +input stall_d; +input stall_x; +input stall_m; +input valid_f; +input valid_d; +input kill_f; + +input branch_predict_taken_d; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; + + + +input branch_taken_x; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; + + +input exception_m; +input branch_taken_m; +input branch_mispredict_taken_m; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; + + + +input iflush; + + + + +input dcache_restart_request; +input dcache_refill_request; +input dcache_refilling; + + + + + + +input [ (32-1):0] i_dat_i; +input i_ack_i; +input i_err_i; +input i_rty_i; + + + + + + + + + + + + + + + +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + +output icache_stall_request; +wire icache_stall_request; +output icache_restart_request; +wire icache_restart_request; +output icache_refill_request; +wire icache_refill_request; +output icache_refilling; +wire icache_refilling; + + + + + +output [ (32-1):0] i_dat_o; + + + + +wire [ (32-1):0] i_dat_o; + + +output [ (32-1):0] i_adr_o; +reg [ (32-1):0] i_adr_o; +output i_cyc_o; +reg i_cyc_o; +output [ (4-1):0] i_sel_o; + + + + +wire [ (4-1):0] i_sel_o; + + +output i_stb_o; +reg i_stb_o; +output i_we_o; + + + + +wire i_we_o; + + +output [ (3-1):0] i_cti_o; +reg [ (3-1):0] i_cti_o; +output i_lock_o; +reg i_lock_o; +output [ (2-1):0] i_bte_o; +wire [ (2-1):0] i_bte_o; + + + + + + + + + + + + + +output bus_error_d; +reg bus_error_d; + + + + +output [ (32-1):0] instruction_f; +wire [ (32-1):0] instruction_f; + + +output [ (32-1):0] instruction_d; +reg [ (32-1):0] instruction_d; + + + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + + + + + +wire icache_read_enable_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; +reg icache_refill_ready; +reg [ (32-1):0] icache_refill_data; +wire [ (32-1):0] icache_data_f; +wire [ (3-1):0] first_cycle_type; +wire [ (3-1):0] next_cycle_type; +wire last_word; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + + + + + + + + + + + + + + + + + + + + +reg bus_error_f; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + + + + +lm32_icache_full #( + .associativity (associativity), + .sets (sets), + .bytes_per_line (bytes_per_line), + .base_address (base_address), + .limit (limit) + ) icache ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_a (stall_a), + .stall_f (stall_f), + .branch_predict_taken_d (branch_predict_taken_d), + .valid_d (valid_d), + .address_a (pc_a), + .address_f (pc_f), + .read_enable_f (icache_read_enable_f), + .refill_ready (icache_refill_ready), + .refill_data (icache_refill_data), + .iflush (iflush), + + .stall_request (icache_stall_request), + .restart_request (icache_restart_request), + .refill_request (icache_refill_request), + .refill_address (icache_refill_address), + .refilling (icache_refilling), + .inst (icache_data_f) + ); + + + + + + + + + + + assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + + && (dcache_restart_request == 1'b0) + + + + + + + ; + + + + +always @(*) +begin + + + + if (dcache_restart_request == 1'b1) + pc_a = restart_address; + else + + + if (branch_taken_m == 1'b1) + if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) + pc_a = pc_x; + else + pc_a = branch_target_m; + + + else if (branch_taken_x == 1'b1) + pc_a = branch_target_x; + + + else + if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) + pc_a = branch_predict_address_d; + else + + + if (icache_restart_request == 1'b1) + pc_a = restart_address; + else + + + pc_a = pc_f + 1'b1; +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_f = icache_data_f; + + + + + + + + + + + + + + +assign i_dat_o = 32'd0; +assign i_we_o = 1'b0; +assign i_sel_o = 4'b1111; + + +assign i_bte_o = 2'b00; + + + + + + +generate + case (bytes_per_line) + 4: + begin +assign first_cycle_type = 3'b111; +assign next_cycle_type = 3'b111; +assign last_word = 1'b1; +assign first_address = icache_refill_address; + end + 8: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = 3'b111; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + 16: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + endcase +endgenerate + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + end + else + begin + if (stall_f == 1'b0) + pc_f <= pc_a; + if (stall_d == 1'b0) + pc_d <= pc_f; + if (stall_x == 1'b0) + pc_x <= pc_d; + if (stall_m == 1'b0) + pc_m <= pc_x; + pc_w <= pc_m; end end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + else + begin + + + + + + if (dcache_refill_request == 1'b1) + restart_address <= pc_w; + else if ((icache_refill_request == 1'b1) && (!dcache_refilling) && (!dcache_restart_request)) + restart_address <= icache_refill_address; + + + + + + + + + + + + + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + bus_error_f <= 1'b0; + + + + + + + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + + + + + + + + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + if (i_err_i == 1'b1) + begin + bus_error_f <= 1'b1; + $display ("Instruction bus error. Address: %x", i_adr_o); + end + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + bus_error_f <= 1'b0; + + + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (branch_taken_x == 1'b1) + bus_error_f <= 1'b0; + + + if (branch_taken_m == 1'b1) + bus_error_f <= 1'b0; + + + end + end + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + bus_error_d <= 1'b0; + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + bus_error_d <= bus_error_f; + + + end + end + end + endmodule -module lm32_interrupt_full_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_full ( + clk_i, rst_i, + interrupt, + stall_x, - non_debug_exception, - debug_exception, + + + + + + exception, + + eret_q_x, - bret_q_x, + + + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; -input non_debug_exception; -input debug_exception; + + + + + + +input exception; + + input eret_q_x; -input bret_q_x; -input [ (5-1):0] csr; + + + + + +input [ (4 -1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; -reg bie; + + + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, - bie, + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + eie, ie }; - 5'h2: csr_read_data = ip; - 5'h1: csr_read_data = im; + 4 'h2: csr_read_data = ip; + 4 'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end end else begin + always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, - bie, + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + eie, ie }; - 5'h2: csr_read_data = ip; + 4 'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; - bie <= 1'b0; + + + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; - if (non_debug_exception == 1'b1) + + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end - else if (debug_exception == 1'b1) - begin - bie <= ie; - ie <= 1'b0; - end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end - else if (bret_q_x == 1'b1) - ie <= bie; + + + + + + + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - bie <= csr_write_data[2]; + + + + end - if (csr == 5'h1) + if (csr == 4 'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 5'h2) + if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -7294,49 +25640,80 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; - bie <= 1'b0; + + + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; - if (non_debug_exception == 1'b1) + + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end - else if (debug_exception == 1'b1) - begin - bie <= ie; - ie <= 1'b0; - end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end - else if (bret_q_x == 1'b1) - ie <= bie; + + + + + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - bie <= csr_write_data[2]; + + + + end - if (csr == 5'h2) + if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -7344,19 +25721,635 @@ always @(posedge clk_i ) end end endgenerate + endmodule -module lm32_top_medium ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_medium_debug ( + clk_i, rst_i, + + interrupt, + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -7366,6 +26359,9 @@ module lm32_top_medium ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -7376,19 +26372,58 @@ module lm32_top_medium ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -7407,6 +26442,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -7425,6 +26463,72 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + +wire [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_q; +wire jtag_update; +wire [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_q; +wire jtck; +wire jrstn; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -7432,6 +26536,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -7444,22 +26549,89 @@ begin clogb2_v1 = i-1; end endfunction -lm32_cpu_medium + + + + + + + + +lm32_cpu_medium_debug #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), + + + + + + + + + + + + .jtag_clk (jtck), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + + + .I_DAT_I (I_DAT_I), .I_ACK_I (I_ACK_I), .I_ERR_I (I_ERR_I), .I_RTY_I (I_RTY_I), + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d), + + + + + + + + + + + + .I_DAT_O (I_DAT_O), .I_ADR_O (I_ADR_O), .I_CYC_O (I_CYC_O), @@ -7469,6 +26641,9 @@ lm32_cpu_medium .I_CTI_O (I_CTI_O), .I_LOCK_O (I_LOCK_O), .I_BTE_O (I_BTE_O), + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -7479,33 +26654,515 @@ lm32_cpu_medium .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); + + + + +jtag_cores jtag_cores ( + + .reg_d (jtag_reg_d), + .reg_addr_d (jtag_reg_addr_d), + + .reg_update (jtag_update), + .reg_q (jtag_reg_q), + .reg_addr_q (jtag_reg_addr_q), + .jtck (jtck), + .jrstn (jrstn) + ); + + + endmodule -module lm32_mc_arithmetic_medium ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_medium_debug ( + clk_i, rst_i, stall_d, kill_x, + + + + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + + + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + + + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -7514,11 +27171,23 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + + + case (state) 3'b000: begin @@ -7528,24 +27197,587 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule -module lm32_cpu_medium ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_medium_debug ( + clk_i, + + + + rst_i, + + + interrupt, + + + + + + + + + + + + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + + + + + jtag_reg_d, + jtag_reg_addr_d, + + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -7555,6 +27787,23 @@ module lm32_cpu_medium ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -7564,33 +27813,168 @@ module lm32_cpu_medium ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; + + +parameter deba_reset = 32'h10000000; + + parameter sdb_address = 32'h00000000; -parameter icache_associativity = 1; -parameter icache_sets = 512; -parameter icache_bytes_per_line = 16; -parameter icache_base_address = 0; -parameter icache_limit = 0; + + + +parameter icache_associativity = 1; +parameter icache_sets = 256; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 32'h0; +parameter icache_limit = 32'h7fffffff; + + + + + + + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 512; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 0; parameter dcache_limit = 0; -parameter watchpoints = 0; + + + + + +parameter watchpoints = 32'h4; + + + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; + + + + + + + + + + + +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + +output [ 7:0] jtag_reg_d; +wire [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -7609,6 +27993,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -7627,11 +28014,33 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + +reg valid_a; + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -7650,8 +28059,8 @@ reg [ 1:0] size_x; wire branch_d; wire branch_predict_d; wire branch_predict_taken_d; -wire [ ((32-2)+2-1):2] branch_predict_address_d; -wire [ ((32-2)+2-1):2] branch_target_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; wire bi_unconditional; wire bi_conditional; reg branch_x; @@ -7663,32 +28072,61 @@ reg branch_predict_taken_m; wire branch_mispredict_taken_m; wire branch_flushX_m; wire branch_reg_d; -wire [ ((32-2)+2-1):2] branch_offset_d; -reg [ ((32-2)+2-1):2] branch_target_x; -reg [ ((32-2)+2-1):2] branch_target_m; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; + + + + + + + + + + + + + wire x_result_sel_sext_d; reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + wire m_result_sel_shift_d; reg m_result_sel_shift_x; reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + wire w_result_sel_mul_d; reg w_result_sel_mul_x; reg w_result_sel_mul_m; reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -7711,99 +28149,401 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (4 -1):0] csr_d; -reg [ (4 -1):0] csr_x; +wire [ (5-1):0] csr_d; +reg [ (5-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + +wire break_d; +reg break_x; + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; + + + + + + + +wire bret_d; +reg bret_x; +wire bret_q_x; + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + + + + + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; + + + + wire [ (32-1):0] sextb_result_x; wire [ (32-1):0] sexth_result_x; wire [ (32-1):0] sext_result_x; + + + + + + + + + + + wire direction_d; reg direction_x; wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; -wire [ ((32-2)+2-1):2] pc_f; -wire [ ((32-2)+2-1):2] pc_d; -wire [ ((32-2)+2-1):2] pc_x; -wire [ ((32-2)+2-1):2] pc_m; -wire [ ((32-2)+2-1):2] pc_w; + + +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; + + +wire iflush; +wire icache_stall_request; +wire icache_restart_request; +wire icache_refill_request; +wire icache_refilling; + + + + + + + + + + + + + wire [ (32-1):0] load_data_w; wire stall_wb_load; + + + + + + +wire [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + + + + +wire jtag_csr_write_enable; +wire [ (32-1):0] jtag_csr_write_data; +wire [ (5-1):0] jtag_csr; +wire jtag_read_enable; +wire [ 7:0] jtag_read_data; +wire jtag_write_enable; +wire [ 7:0] jtag_write_data; +wire [ (32-1):0] jtag_address; +wire jtag_access_complete; + + + + +wire jtag_break; + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; -reg [ (32-2)+2-1:8] eba; + +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + + +reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; + + reg [ (3-1):0] eid_x; + + + + + + + + + + +wire dc_ss; + + +wire dc_re; +wire bp_match; +wire wp_match; wire exception_x; -reg exception_m; -reg exception_w; -wire exception_q_w; +reg exception_m; +wire debug_exception_x; +reg debug_exception_m; +reg debug_exception_w; +wire debug_exception_q_w; +wire non_debug_exception_x; +reg non_debug_exception_m; +reg non_debug_exception_w; +wire non_debug_exception_q_w; + + + + + + + + + + + + +wire reset_exception; + + + + + + wire interrupt_exception; + + + + +wire breakpoint_exception; +wire watchpoint_exception; + + + + + + + + + + + wire system_call_exception; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -7811,6 +28551,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -7823,7 +28564,16 @@ begin clogb2_v1 = i-1; end endfunction -lm32_instruction_unit_medium #( + + + + + + + + + +lm32_instruction_unit_medium_debug #( .eba_reset (eba_reset), .associativity (icache_associativity), .sets (icache_sets), @@ -7831,8 +28581,10 @@ lm32_instruction_unit_medium #( .base_address (icache_base_address), .limit (icache_limit) ) instruction_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_f (stall_f), .stall_d (stall_d), @@ -7843,19 +28595,61 @@ lm32_instruction_unit_medium #( .kill_f (kill_f), .branch_predict_taken_d (branch_predict_taken_d), .branch_predict_address_d (branch_predict_address_d), + + + + + .exception_m (exception_m), .branch_taken_m (branch_taken_m), .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), + + + .iflush (iflush), + + + + + + + + + + + .i_dat_i (I_DAT_I), .i_ack_i (I_ACK_I), .i_err_i (I_ERR_I), .i_rty_i (I_RTY_I), + + + + + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + + + + .pc_f (pc_f), .pc_d (pc_d), .pc_x (pc_x), .pc_m (pc_m), .pc_w (pc_w), + + + .icache_stall_request (icache_stall_request), + .icache_restart_request (icache_restart_request), + .icache_refill_request (icache_refill_request), + .icache_refilling (icache_refilling), + + + + + .i_dat_o (I_DAT_O), .i_adr_o (I_ADR_O), .i_cyc_o (I_CYC_O), @@ -7865,21 +28659,78 @@ lm32_instruction_unit_medium #( .i_cti_o (I_CTI_O), .i_lock_o (I_LOCK_O), .i_bte_o (I_BTE_O), + + + + + + + + + + + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + + + + + + + + .instruction_f (instruction_f), + + + + .instruction_d (instruction_d) + + + ); -lm32_decoder_medium decoder ( + + +lm32_decoder_medium_debug decoder ( + .instruction (instruction_d), + .d_result_sel_0 (d_result_sel_0_d), .d_result_sel_1 (d_result_sel_1_d), .x_result_sel_csr (x_result_sel_csr_d), + + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + .x_result_sel_logic (x_result_sel_logic_d), + + + + .x_result_sel_add (x_result_sel_add_d), .m_result_sel_compare (m_result_sel_compare_d), + + .m_result_sel_shift (m_result_sel_shift_d), + + .w_result_sel_load (w_result_sel_load_d), + + .w_result_sel_mul (w_result_sel_mul_d), + + .x_bypass_enable (x_bypass_enable_d), .m_bypass_enable (m_bypass_enable_d), .read_enable_0 (read_enable_0_d), @@ -7896,25 +28747,61 @@ lm32_decoder_medium decoder ( .sign_extend (sign_extend_d), .adder_op (adder_op_d), .logic_op (logic_op_d), + + .direction (direction_d), + + + + + + + + + + + + + + + + .branch (branch_d), .bi_unconditional (bi_unconditional), .bi_conditional (bi_conditional), .branch_reg (branch_reg_d), .condition (condition_d), + + + .break_opcode (break_d), + + .scall (scall_d), .eret (eret_d), + + + .bret (bret_d), + + + + + + .csr_write_enable (csr_write_enable_d) ); -lm32_load_store_unit_medium #( + + +lm32_load_store_unit_medium_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), .base_address (dcache_base_address), .limit (dcache_limit) ) load_store_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_x (stall_x), .stall_m (stall_m), @@ -7933,12 +28820,39 @@ lm32_load_store_unit_medium #( .store_q_m (store_q_m), .sign_extend_x (sign_extend_x), .size_x (size_x), + + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), .d_ack_i (D_ACK_I), .d_err_i (D_ERR_I), .d_rty_i (D_RTY_I), + + + + + + + + + .load_data_w (load_data_w), .stall_wb_load (stall_wb_load), + .d_dat_o (D_DAT_O), .d_adr_o (D_ADR_O), .d_cyc_o (D_CYC_O), @@ -7949,22 +28863,36 @@ lm32_load_store_unit_medium #( .d_lock_o (D_LOCK_O), .d_bte_o (D_BTE_O) ); + + lm32_adder adder ( + .adder_op_x (adder_op_x), .adder_op_x_n (adder_op_x_n), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .adder_result_x (adder_result_x), .adder_carry_n_x (adder_carry_n_x), .adder_overflow_x (adder_overflow_x) ); + + lm32_logic_op logic_op ( + .logic_op_x (logic_op_x), .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + .logic_result_x (logic_result_x) ); + + + + lm32_shifter shifter ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), @@ -7972,34 +28900,235 @@ lm32_shifter shifter ( .sign_extend_x (sign_extend_x), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .shifter_result_m (shifter_result_m) ); + + + + + + lm32_multiplier multiplier ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), .stall_m (stall_m), .operand_0 (d_result_0), .operand_1 (d_result_1), + .result (multiplier_result_w) ); -lm32_interrupt_medium interrupt_unit ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +lm32_interrupt_medium_debug interrupt_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .interrupt (interrupt), + .stall_x (stall_x), - .exception (exception_q_w), + + + .non_debug_exception (non_debug_exception_q_w), + .debug_exception (debug_exception_q_w), + + + + .eret_q_x (eret_q_x), + + + .bret_q_x (bret_q_x), + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), + .interrupt_exception (interrupt_exception), + .csr_read_data (interrupt_csr_read_data_x) ); + + + + + + +lm32_jtag_medium_debug jtag ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .jtag_clk (jtag_clk), + .jtag_update (jtag_update), + .jtag_reg_q (jtag_reg_q), + .jtag_reg_addr_q (jtag_reg_addr_q), + + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + .stall_x (stall_x), + + + + + .jtag_read_data (jtag_read_data), + .jtag_access_complete (jtag_access_complete), + + + + + .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), + + + + + + + .jtx_csr_read_data (jtx_csr_read_data), + .jrx_csr_read_data (jrx_csr_read_data), + + + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + .jtag_read_enable (jtag_read_enable), + .jtag_write_enable (jtag_write_enable), + .jtag_write_data (jtag_write_data), + .jtag_address (jtag_address), + + + + + .jtag_break (jtag_break), + .jtag_reset (reset_exception), + + + + .jtag_reg_d (jtag_reg_d), + .jtag_reg_addr_d (jtag_reg_addr_d) + ); + + + + + + +lm32_debug_medium_debug #( + .breakpoints (breakpoints), + .watchpoints (watchpoints) + ) hw_debug ( + + .clk_i (clk_i), + .rst_i (rst_i), + .pc_x (pc_x), + .load_x (load_x), + .store_x (store_x), + .load_store_address_x (adder_result_x), + .csr_write_enable_x (csr_write_enable_q_x), + .csr_write_data (operand_1_x), + .csr_x (csr_x), + + + .jtag_csr_write_enable (jtag_csr_write_enable), + .jtag_csr_write_data (jtag_csr_write_data), + .jtag_csr (jtag_csr), + + + + + .eret_q_x (eret_q_x), + .bret_q_x (bret_q_x), + .stall_x (stall_x), + .exception_x (exception_x), + .q_x (q_x), + + + + + + + + + + .dc_ss (dc_ss), + + + .dc_re (dc_re), + .bp_match (bp_match), + .wp_match (wp_match) + ); + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; reg [31:0] w_result_d; reg regfile_raw_0, regfile_raw_0_nxt; reg regfile_raw_1, regfile_raw_1_nxt; + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) begin if (reg_write_enable_q_w @@ -8007,22 +29136,39 @@ lm32_interrupt_medium interrupt_unit ( regfile_raw_0_nxt = 1'b1; else regfile_raw_0_nxt = 1'b0; + if (reg_write_enable_q_w && (write_idx_w == instruction_f[20:16])) regfile_raw_1_nxt = 1'b1; else regfile_raw_1_nxt = 1'b0; end + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) if (regfile_raw_0) reg_data_live_0 = w_result_d; else reg_data_live_0 = regfile_data_0; + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) if (regfile_raw_1) reg_data_live_1 = w_result_d; else reg_data_live_1 = regfile_data_1; + + + + always @(posedge clk_i ) if (rst_i == 1'b1) begin @@ -8036,22 +29182,31 @@ lm32_interrupt_medium interrupt_unit ( regfile_raw_1 <= regfile_raw_1_nxt; w_result_d <= w_result; end + + + + + lm32_dp_ram #( + .addr_depth(1<<5), .addr_width(5), .data_width(32) ) reg_0 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[25:21]), + .rdata_o (regfile_data_0) ); + lm32_dp_ram #( .addr_depth(1<<5), @@ -8060,582 +29215,4577 @@ lm32_interrupt_medium interrupt_unit ( ) reg_1 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[20:16]), + .rdata_o (regfile_data_1) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + +always @(*) +begin + if ( ( (x_bypass_enable_x == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) + ) + ) + || ( (m_bypass_enable_m == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) + ) + ) + ) + interlock = 1'b1; + else + interlock = 1'b0; +end + + +always @(*) +begin + if (raw_x_0 == 1'b1) + bypass_data_0 = x_result; + else if (raw_m_0 == 1'b1) + bypass_data_0 = m_result; + else if (raw_w_0 == 1'b1) + bypass_data_0 = w_result; + else + bypass_data_0 = reg_data_0; +end + + +always @(*) +begin + if (raw_x_1 == 1'b1) + bypass_data_1 = x_result; + else if (raw_m_1 == 1'b1) + bypass_data_1 = m_result; + else if (raw_w_1 == 1'b1) + bypass_data_1 = w_result; + else + bypass_data_1 = reg_data_1; +end + + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; + assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + + assign branch_target_d = pc_d + branch_offset_d; + + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + +always @(*) +begin + d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; + case (d_result_sel_1_d) + 2'b00: d_result_1 = { 32{1'b0}}; + 2'b01: d_result_1 = bypass_data_1; + 2'b10: d_result_1 = immediate_d; + default: d_result_1 = { 32{1'bx}}; + endcase +end + + + + + + + + + + + +assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; +assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; +assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + +assign cmp_zero = operand_0_x == operand_1_x; +assign cmp_negative = adder_result_x[ 32-1]; +assign cmp_overflow = adder_overflow_x; +assign cmp_carry_n = adder_carry_n_x; +always @(*) +begin + case (condition_x) + 3'b000: condition_met_x = 1'b1; + 3'b110: condition_met_x = 1'b1; + 3'b001: condition_met_x = cmp_zero; + 3'b111: condition_met_x = !cmp_zero; + 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); + 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; + 3'b011: condition_met_x = cmp_negative == cmp_overflow; + 3'b100: condition_met_x = cmp_carry_n; + default: condition_met_x = 1'bx; + endcase +end + + +always @(*) +begin + x_result = x_result_sel_add_x ? adder_result_x + : x_result_sel_csr_x ? csr_read_data_x + + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + + + : logic_result_x; +end + + +always @(*) +begin + m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + + : m_result_sel_shift_m ? shifter_result_m + + + : operand_m; +end + + +always @(*) +begin + w_result = w_result_sel_load_w ? load_data_w + + + : w_result_sel_mul_w ? multiplier_result_w + + + : operand_w; +end + + + + + + + + + + + + + +assign branch_taken_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( ( (condition_met_m == 1'b1) + && (branch_predict_taken_m == 1'b0) + ) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign branch_mispredict_taken_m = (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1); + + +assign branch_flushX_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( (condition_met_m == 1'b1) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign kill_f = ( (valid_d == 1'b1) + && (branch_predict_taken_d == 1'b1) + ) + || (branch_taken_m == 1'b1) + + + + + + + || (icache_refill_request == 1'b1) + + + + + + + ; +assign kill_d = (branch_taken_m == 1'b1) + + + + + + + || (icache_refill_request == 1'b1) + + + + + + + ; +assign kill_x = (branch_flushX_m == 1'b1) + + + + + ; +assign kill_m = 1'b0 + + + + + ; +assign kill_w = 1'b0 + + + + + ; + + + + + +assign breakpoint_exception = ( ( (break_x == 1'b1) + || (bp_match == 1'b1) + ) + && (valid_x == 1'b1) + ) + + + || (jtag_break == 1'b1) + + + ; + + + + + +assign watchpoint_exception = wp_match == 1'b1; + + + + + + + + + + + + + + + + +assign system_call_exception = ( (scall_x == 1'b1) + + + + + ); + + + +assign debug_exception_x = (breakpoint_exception == 1'b1) + || (watchpoint_exception == 1'b1) + ; + +assign non_debug_exception_x = (system_call_exception == 1'b1) + + + || (reset_exception == 1'b1) + + + + + + + + + + + + + + || ( (interrupt_exception == 1'b1) + + + && (dc_ss == 1'b0) + + + + + + + + ) + + + ; + +assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin - if ( ( (x_bypass_enable_x == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) - ) - ) - || ( (m_bypass_enable_m == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) - ) - ) - ) - interlock = 1'b1; + + + + + if (reset_exception == 1'b1) + eid_x = 3'h0; + else + + + + + + + + + if (breakpoint_exception == 1'b1) + eid_x = 3'd1; + else + + + + + + + + + + + + + + if (watchpoint_exception == 1'b1) + eid_x = 3'd3; + else + + + + + + + + + + + if ( (interrupt_exception == 1'b1) + + + && (dc_ss == 1'b0) + + + ) + eid_x = 3'h6; + else + + + eid_x = 3'h7; +end + + + +assign stall_a = (stall_f == 1'b1); + +assign stall_f = (stall_d == 1'b1); + +assign stall_d = (stall_x == 1'b1) + || ( (interlock == 1'b1) + && (kill_d == 1'b0) + ) + || ( ( (eret_d == 1'b1) + || (scall_d == 1'b1) + + + + + ) + && ( (load_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_x == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + + || ( ( (break_d == 1'b1) + || (bret_d == 1'b1) + ) + && ( (load_q_x == 1'b1) + || (store_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + + || ( (csr_write_enable_d == 1'b1) + && (load_q_x == 1'b1) + ) + + + + + + + + + + + ; + +assign stall_x = (stall_m == 1'b1) + + + + + + + + + ; + +assign stall_m = (stall_wb_load == 1'b1) + + + + + || ( (D_CYC_O == 1'b1) + && ( (store_m == 1'b1) + + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + + || (load_m == 1'b1) + || (load_x == 1'b1) + ) + ) + + + + + + + + + || (icache_stall_request == 1'b1) + || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) + + + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + +assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); +assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); +assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + +assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); + + +assign load_q_x = (load_x == 1'b1) + && (q_x == 1'b1) + + + && (bp_match == 1'b0) + + + ; +assign store_q_x = (store_x == 1'b1) + && (q_x == 1'b1) + + + && (bp_match == 1'b0) + + + ; + + + + +assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); +assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); +assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + +assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); +assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); + + + + + +assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); +assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); +assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + +assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + +assign cfg = { + 6'h02, + watchpoints[3:0], + breakpoints[3:0], + interrupts[5:0], + + + 1'b1, + + + + + + + + + 1'b0, + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + + + 1'b0, + + + + + 1'b1 + + + + + }; + +assign cfg2 = { + 30'b0, + + + + + 1'b0, + + + + + + + 1'b0 + + + }; + + + + +assign iflush = ( (csr_write_enable_d == 1'b1) + && (csr_d == 5'h3) + && (stall_d == 1'b0) + && (kill_d == 1'b0) + && (valid_d == 1'b1)) + + + + || + ( (jtag_csr_write_enable == 1'b1) + && (jtag_csr == 5'h3)) + + + ; + + + + + + + + + + + + + + + + +assign csr_d = read_idx_0_d[ (5-1):0]; + + +always @(*) +begin + case (csr_x) + + + 5'h0, + 5'h1, + 5'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + + 5'h6: csr_read_data_x = cfg; + 5'h7: csr_read_data_x = {eba, 8'h00}; + + + 5'h9: csr_read_data_x = {deba, 8'h00}; + + + + + 5'he: csr_read_data_x = jtx_csr_read_data; + 5'hf: csr_read_data_x = jrx_csr_read_data; + + + 5'ha: csr_read_data_x = cfg2; + 5'hb: csr_read_data_x = sdb_address; + + default: csr_read_data_x = { 32{1'bx}}; + endcase +end + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + else + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) + eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + end +end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + else + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) + deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) + deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(*) +begin + if (icache_refill_request == 1'b1) + valid_a = 1'b0; + else if (icache_restart_request == 1'b1) + valid_a = 1'b1; + else + valid_a = !icache_refilling; +end + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + valid_f <= 1'b0; + valid_d <= 1'b0; + valid_x <= 1'b0; + valid_m <= 1'b0; + valid_w <= 1'b0; + end + else + begin + if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + + valid_f <= valid_a; + + + + + else if (stall_f == 1'b0) + valid_f <= 1'b0; + + if (kill_d == 1'b1) + valid_d <= 1'b0; + else if (stall_f == 1'b0) + valid_d <= valid_f & !kill_f; + else if (stall_d == 1'b0) + valid_d <= 1'b0; + + if (stall_d == 1'b0) + valid_x <= valid_d & !kill_d; + else if (kill_x == 1'b1) + valid_x <= 1'b0; + else if (stall_x == 1'b0) + valid_x <= 1'b0; + + if (kill_m == 1'b1) + valid_m <= 1'b0; + else if (stall_x == 1'b0) + valid_m <= valid_x & !kill_x; + else if (stall_m == 1'b0) + valid_m <= 1'b0; + + if (stall_m == 1'b0) + valid_w <= valid_m & !kill_m; + else + valid_w <= 1'b0; + end +end + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + + + + + operand_0_x <= { 32{1'b0}}; + operand_1_x <= { 32{1'b0}}; + store_operand_x <= { 32{1'b0}}; + branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + x_result_sel_csr_x <= 1'b0; + + + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + + x_result_sel_add_x <= 1'b0; + m_result_sel_compare_x <= 1'b0; + + + m_result_sel_shift_x <= 1'b0; + + + w_result_sel_load_x <= 1'b0; + + + w_result_sel_mul_x <= 1'b0; + + + x_bypass_enable_x <= 1'b0; + m_bypass_enable_x <= 1'b0; + write_enable_x <= 1'b0; + write_idx_x <= { 5{1'b0}}; + csr_x <= { 5{1'b0}}; + load_x <= 1'b0; + store_x <= 1'b0; + size_x <= { 2{1'b0}}; + sign_extend_x <= 1'b0; + adder_op_x <= 1'b0; + adder_op_x_n <= 1'b0; + logic_op_x <= 4'h0; + + + direction_x <= 1'b0; + + + + + + + + branch_x <= 1'b0; + branch_predict_x <= 1'b0; + branch_predict_taken_x <= 1'b0; + condition_x <= 3'b000; + + + break_x <= 1'b0; + + + scall_x <= 1'b0; + eret_x <= 1'b0; + + + bret_x <= 1'b0; + + + + + + + + csr_write_enable_x <= 1'b0; + operand_m <= { 32{1'b0}}; + branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + m_result_sel_compare_m <= 1'b0; + + + m_result_sel_shift_m <= 1'b0; + + + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + + m_bypass_enable_m <= 1'b0; + branch_m <= 1'b0; + branch_predict_m <= 1'b0; + branch_predict_taken_m <= 1'b0; + exception_m <= 1'b0; + load_m <= 1'b0; + store_m <= 1'b0; + write_enable_m <= 1'b0; + write_idx_m <= { 5{1'b0}}; + condition_met_m <= 1'b0; + + + + + + + debug_exception_m <= 1'b0; + non_debug_exception_m <= 1'b0; + + + operand_w <= { 32{1'b0}}; + w_result_sel_load_w <= 1'b0; + + + w_result_sel_mul_w <= 1'b0; + + + write_idx_w <= { 5{1'b0}}; + write_enable_w <= 1'b0; + + + debug_exception_w <= 1'b0; + non_debug_exception_w <= 1'b0; + + + + + + + + + end else - interlock = 1'b0; + begin + + + if (stall_x == 1'b0) + begin + + + + + operand_0_x <= d_result_0; + operand_1_x <= d_result_1; + store_operand_x <= bypass_data_1; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; + x_result_sel_csr_x <= x_result_sel_csr_d; + + + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + + x_result_sel_add_x <= x_result_sel_add_d; + m_result_sel_compare_x <= m_result_sel_compare_d; + + + m_result_sel_shift_x <= m_result_sel_shift_d; + + + w_result_sel_load_x <= w_result_sel_load_d; + + + w_result_sel_mul_x <= w_result_sel_mul_d; + + + x_bypass_enable_x <= x_bypass_enable_d; + m_bypass_enable_x <= m_bypass_enable_d; + load_x <= load_d; + store_x <= store_d; + branch_x <= branch_d; + branch_predict_x <= branch_predict_d; + branch_predict_taken_x <= branch_predict_taken_d; + write_idx_x <= write_idx_d; + csr_x <= csr_d; + size_x <= size_d; + sign_extend_x <= sign_extend_d; + adder_op_x <= adder_op_d; + adder_op_x_n <= ~adder_op_d; + logic_op_x <= logic_op_d; + + + direction_x <= direction_d; + + + + + + + condition_x <= condition_d; + csr_write_enable_x <= csr_write_enable_d; + + + break_x <= break_d; + + + scall_x <= scall_d; + + + + + eret_x <= eret_d; + + + bret_x <= bret_d; + + + write_enable_x <= write_enable_d; + end + + + + if (stall_m == 1'b0) + begin + operand_m <= x_result; + m_result_sel_compare_m <= m_result_sel_compare_x; + + + m_result_sel_shift_m <= m_result_sel_shift_x; + + + if (exception_x == 1'b1) + begin + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + + end + else + begin + w_result_sel_load_m <= w_result_sel_load_x; + + + w_result_sel_mul_m <= w_result_sel_mul_x; + + + end + m_bypass_enable_m <= m_bypass_enable_x; + load_m <= load_x; + store_m <= store_x; + + + + + branch_m <= branch_x; + branch_predict_m <= branch_predict_x; + branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + + if (non_debug_exception_x == 1'b1) + write_idx_m <= 5'd30; + else if (debug_exception_x == 1'b1) + write_idx_m <= 5'd31; + else + write_idx_m <= write_idx_x; + + + + + + + + condition_met_m <= condition_met_x; + + + if (exception_x == 1'b1) + if ((dc_re == 1'b1) + || ((debug_exception_x == 1'b1) + && (non_debug_exception_x == 1'b0))) + branch_target_m <= {deba, eid_x, {3{1'b0}}}; + else + branch_target_m <= {eba, eid_x, {3{1'b0}}}; + else + branch_target_m <= branch_target_x; + + + + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + debug_exception_m <= debug_exception_x; + non_debug_exception_m <= non_debug_exception_x; + + + end + + + if (stall_m == 1'b0) + begin + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + exception_m <= 1'b1; + else + exception_m <= 1'b0; + + + + + + + + + end + + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + + w_result_sel_load_w <= w_result_sel_load_m; + + + w_result_sel_mul_w <= w_result_sel_mul_m; + + + write_idx_w <= write_idx_m; + + + + + + + + + write_enable_w <= write_enable_m; + + + debug_exception_w <= debug_exception_m; + non_debug_exception_w <= non_debug_exception_m; + + + + + + + + + + + + + + end end -always @(*) + + + + + +always @(posedge clk_i ) begin - if (raw_x_0 == 1'b1) - bypass_data_0 = x_result; - else if (raw_m_0 == 1'b1) - bypass_data_0 = m_result; - else if (raw_w_0 == 1'b1) - bypass_data_0 = w_result; + if (rst_i == 1'b1) + begin + use_buf <= 1'b0; + reg_data_buf_0 <= { 32{1'b0}}; + reg_data_buf_1 <= { 32{1'b0}}; + end else - bypass_data_0 = reg_data_0; + begin + if (stall_d == 1'b0) + use_buf <= 1'b0; + else if (use_buf == 1'b0) + begin + reg_data_buf_0 <= reg_data_live_0; + reg_data_buf_1 <= reg_data_live_1; + use_buf <= 1'b1; + end + if (reg_write_enable_q_w == 1'b1) + begin + if (write_idx_w == read_idx_0_d) + reg_data_buf_0 <= w_result; + if (write_idx_w == read_idx_1_d) + reg_data_buf_1 <= w_result; + end + end end -always @(*) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +initial begin - if (raw_x_1 == 1'b1) - bypass_data_1 = x_result; - else if (raw_m_1 == 1'b1) - bypass_data_1 = m_result; - else if (raw_w_1 == 1'b1) - bypass_data_1 = w_result; - else - bypass_data_1 = reg_data_1; + + + + + + end - assign branch_predict_d = bi_unconditional | bi_conditional; - assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); - assign branch_target_d = pc_d + branch_offset_d; - assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; -always @(*) + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_medium_debug +( + + clk_i, + + + + + rst_i, + + stall_a, + stall_x, + stall_m, + kill_x, + kill_m, + exception_m, + store_operand_x, + load_store_address_x, + load_store_address_m, + load_store_address_w, + load_x, + store_x, + load_q_x, + store_q_x, + load_q_m, + store_q_m, + sign_extend_x, + size_x, + + + + + + d_dat_i, + d_ack_i, + d_err_i, + d_rty_i, + + + + + + + + + + + + + + + + + + + + load_data_w, + stall_wb_load, + + d_dat_o, + d_adr_o, + d_cyc_o, + d_sel_o, + d_stb_o, + d_we_o, + d_cti_o, + d_lock_o, + d_bte_o + ); + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + input clk_i; + +input rst_i; + +input stall_a; +input stall_x; +input stall_m; +input kill_x; +input kill_m; +input exception_m; + +input [ (32-1):0] store_operand_x; +input [ (32-1):0] load_store_address_x; +input [ (32-1):0] load_store_address_m; +input [1:0] load_store_address_w; +input load_x; +input store_x; +input load_q_x; +input store_q_x; +input load_q_m; +input store_q_m; +input sign_extend_x; +input [ 1:0] size_x; + + + + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + +input [ (32-1):0] d_dat_i; +input d_ack_i; +input d_err_i; +input d_rty_i; + + + + + + + + + + + + + + + + + + +output [ (32-1):0] load_data_w; +reg [ (32-1):0] load_data_w; +output stall_wb_load; +reg stall_wb_load; + +output [ (32-1):0] d_dat_o; +reg [ (32-1):0] d_dat_o; +output [ (32-1):0] d_adr_o; +reg [ (32-1):0] d_adr_o; +output d_cyc_o; +reg d_cyc_o; +output [ (4-1):0] d_sel_o; +reg [ (4-1):0] d_sel_o; +output d_stb_o; +reg d_stb_o; +output d_we_o; +reg d_we_o; +output [ (3-1):0] d_cti_o; +reg [ (3-1):0] d_cti_o; +output d_lock_o; +reg d_lock_o; +output [ (2-1):0] d_bte_o; +wire [ (2-1):0] d_bte_o; + + + + + + +reg [ 1:0] size_m; +reg [ 1:0] size_w; +reg sign_extend_m; +reg sign_extend_w; +reg [ (32-1):0] store_data_x; +reg [ (32-1):0] store_data_m; +reg [ (4-1):0] byte_enable_x; +reg [ (4-1):0] byte_enable_m; +wire [ (32-1):0] data_m; +reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + +wire wb_select_x; + + + + + + + + + + +reg wb_select_m; +reg [ (32-1):0] wb_data_m; +reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; - case (d_result_sel_1_d) - 2'b00: d_result_1 = { 32{1'b0}}; - 2'b01: d_result_1 = bypass_data_1; - 2'b10: d_result_1 = immediate_d; - default: d_result_1 = { 32{1'bx}}; - endcase + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; -assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; -assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; -assign cmp_zero = operand_0_x == operand_1_x; -assign cmp_negative = adder_result_x[ 32-1]; -assign cmp_overflow = adder_overflow_x; -assign cmp_carry_n = adder_carry_n_x; -always @(*) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - case (condition_x) - 3'b000: condition_met_x = 1'b1; - 3'b110: condition_met_x = 1'b1; - 3'b001: condition_met_x = cmp_zero; - 3'b111: condition_met_x = !cmp_zero; - 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); - 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; - 3'b011: condition_met_x = cmp_negative == cmp_overflow; - 3'b100: condition_met_x = cmp_carry_n; - default: condition_met_x = 1'bx; - endcase + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end +endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + + + ; + + always @(*) begin - x_result = x_result_sel_add_x ? adder_result_x - : x_result_sel_csr_x ? csr_read_data_x - : x_result_sel_sext_x ? sext_result_x - : logic_result_x; + case (size_x) + 2'b00: store_data_x = {4{store_operand_x[7:0]}}; + 2'b11: store_data_x = {2{store_operand_x[15:0]}}; + 2'b10: store_data_x = store_operand_x; + default: store_data_x = { 32{1'bx}}; + endcase end + + always @(*) begin - m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} - : m_result_sel_shift_m ? shifter_result_m - : operand_m; + casez ({size_x, load_store_address_x[1:0]}) + { 2'b00, 2'b11}: byte_enable_x = 4'b0001; + { 2'b00, 2'b10}: byte_enable_x = 4'b0010; + { 2'b00, 2'b01}: byte_enable_x = 4'b0100; + { 2'b00, 2'b00}: byte_enable_x = 4'b1000; + { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; + { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; + { 2'b10, 2'b??}: byte_enable_x = 4'b1111; + default: byte_enable_x = 4'bxxxx; + endcase end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_data_m; + + + + + + + + always @(*) begin - w_result = w_result_sel_load_w ? load_data_w - : w_result_sel_mul_w ? multiplier_result_w - : operand_w; + casez ({size_w, load_store_address_w[1:0]}) + { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; + { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; + { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; + { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; + { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; + { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; + { 2'b10, 2'b??}: load_data_w = data_w; + default: load_data_w = { 32{1'bx}}; + endcase end -assign branch_taken_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( ( (condition_met_m == 1'b1) - && (branch_predict_taken_m == 1'b0) - ) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign branch_mispredict_taken_m = (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1); -assign branch_flushX_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( (condition_met_m == 1'b1) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign kill_f = ( (valid_d == 1'b1) - && (branch_predict_taken_d == 1'b1) - ) - || (branch_taken_m == 1'b1) - ; -assign kill_d = (branch_taken_m == 1'b1) - ; -assign kill_x = (branch_flushX_m == 1'b1) - ; -assign kill_m = 1'b0 - ; -assign kill_w = 1'b0 - ; -assign system_call_exception = ( (scall_x == 1'b1) - ); -assign exception_x = (system_call_exception == 1'b1) - || ( (interrupt_exception == 1'b1) - ) - ; -always @(*) + + +assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) begin - if ( (interrupt_exception == 1'b1) - ) - eid_x = 3'h6; + if (rst_i == 1'b1) + begin + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_dat_o <= { 32{1'b0}}; + d_adr_o <= { 32{1'b0}}; + d_sel_o <= { 4{ 1'b0}}; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + d_lock_o <= 1'b0; + wb_data_m <= { 32{1'b0}}; + wb_load_complete <= 1'b0; + stall_wb_load <= 1'b0; + + + + + end else - eid_x = 3'h7; -end -assign stall_a = (stall_f == 1'b1); -assign stall_f = (stall_d == 1'b1); -assign stall_d = (stall_x == 1'b1) - || ( (interlock == 1'b1) - && (kill_d == 1'b0) - ) - || ( ( (eret_d == 1'b1) - || (scall_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_x == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( (csr_write_enable_d == 1'b1) - && (load_q_x == 1'b1) - ) - ; -assign stall_x = (stall_m == 1'b1) - ; -assign stall_m = (stall_wb_load == 1'b1) - || ( (D_CYC_O == 1'b1) - && ( (store_m == 1'b1) - || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) - || (load_m == 1'b1) - || (load_x == 1'b1) - ) - ) - || (I_CYC_O == 1'b1) - ; -assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); -assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); -assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); -assign load_q_x = (load_x == 1'b1) - && (q_x == 1'b1) - ; -assign store_q_x = (store_x == 1'b1) - && (q_x == 1'b1) - ; -assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); -assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); -assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); -assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); -assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); -assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); -assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); -assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); -assign cfg = { - 6'h02, - watchpoints[3:0], - breakpoints[3:0], - interrupts[5:0], - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b1, - 1'b1, - 1'b0, - 1'b1 - }; -assign cfg2 = { - 30'b0, - 1'b0, - 1'b0 - }; -assign csr_d = read_idx_0_d[ (4 -1):0]; -always @(*) -begin - case (csr_x) - 4 'h0, - 4 'h1, - 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; - 4 'h6: csr_read_data_x = cfg; - 4 'h7: csr_read_data_x = {eba, 8'h00}; - 4 'ha: csr_read_data_x = cfg2; - 4 'hb: csr_read_data_x = sdb_address; - default: csr_read_data_x = { 32{1'bx}}; - endcase + begin + + + + + + + if (d_cyc_o == 1'b1) + begin + + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) + begin + + + + + + + + + + begin + + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_lock_o <= 1'b0; + end + + + + + + + + wb_data_m <= d_dat_i; + + wb_load_complete <= !d_we_o; + end + + if (d_err_i == 1'b1) + $display ("Data bus error. Address: %x", d_adr_o); + + end + else + begin + + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) + && (stall_m == 1'b0) + + + + + + + + + ) + begin + + d_dat_o <= store_data_m; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b1; + d_cti_o <= 3'b111; + end + else if ( (load_q_m == 1'b1) + && (wb_select_m == 1'b1) + && (wb_load_complete == 1'b0) + + ) + begin + + stall_wb_load <= 1'b0; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + end + end + + if (stall_m == 1'b0) + wb_load_complete <= 1'b0; + + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) + stall_wb_load <= 1'b1; + + if ((kill_m == 1'b1) || (exception_m == 1'b1)) + stall_wb_load <= 1'b0; + end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - eba <= eba_reset[ (32-2)+2-1:8]; + begin + sign_extend_m <= 1'b0; + size_m <= 2'b00; + byte_enable_m <= 1'b0; + store_data_m <= { 32{1'b0}}; + + + + + + + + + + + + + + wb_select_m <= 1'b0; + end else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) - eba <= operand_1_x[ (32-2)+2-1:8]; + if (stall_m == 1'b0) + begin + sign_extend_m <= sign_extend_x; + size_m <= size_x; + byte_enable_m <= byte_enable_x; + store_data_m <= store_data_x; + + + + + + + + + + + + + + wb_select_m <= wb_select_x; + end end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - valid_f <= 1'b0; - valid_d <= 1'b0; - valid_x <= 1'b0; - valid_m <= 1'b0; - valid_w <= 1'b0; + size_w <= 2'b00; + data_w <= { 32{1'b0}}; + sign_extend_w <= 1'b0; end else - begin - if ((kill_f == 1'b1) || (stall_a == 1'b0)) - valid_f <= 1'b1; - else if (stall_f == 1'b0) - valid_f <= 1'b0; - if (kill_d == 1'b1) - valid_d <= 1'b0; - else if (stall_f == 1'b0) - valid_d <= valid_f & !kill_f; - else if (stall_d == 1'b0) - valid_d <= 1'b0; - if (stall_d == 1'b0) - valid_x <= valid_d & !kill_d; - else if (kill_x == 1'b1) - valid_x <= 1'b0; - else if (stall_x == 1'b0) - valid_x <= 1'b0; - if (kill_m == 1'b1) - valid_m <= 1'b0; - else if (stall_x == 1'b0) - valid_m <= valid_x & !kill_x; - else if (stall_m == 1'b0) - valid_m <= 1'b0; - if (stall_m == 1'b0) - valid_w <= valid_m & !kill_m; - else - valid_w <= 1'b0; + begin + size_w <= size_m; + + + + + + data_w <= data_m; + + sign_extend_w <= sign_extend_m; end end -always @(posedge clk_i ) + + + + + + + + +always @(posedge clk_i) +begin + if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) + begin + if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) + $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) + $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + end +end + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_medium_debug ( + + instruction, + + d_result_sel_0, + d_result_sel_1, + x_result_sel_csr, + + + + + + + + + + + x_result_sel_sext, + + + x_result_sel_logic, + + + + + x_result_sel_add, + m_result_sel_compare, + + + m_result_sel_shift, + + + w_result_sel_load, + + + w_result_sel_mul, + + + x_bypass_enable, + m_bypass_enable, + read_enable_0, + read_idx_0, + read_enable_1, + read_idx_1, + write_enable, + write_idx, + immediate, + branch_offset, + load, + store, + size, + sign_extend, + adder_op, + logic_op, + + + direction, + + + + + + + + + + + + + + + + + branch, + branch_reg, + condition, + bi_conditional, + bi_unconditional, + + + break_opcode, + + + scall, + eret, + + + bret, + + + + + + + csr_write_enable + ); + + + + + +input [ (32-1):0] instruction; + + + + + +output [ 0:0] d_result_sel_0; +reg [ 0:0] d_result_sel_0; +output [ 1:0] d_result_sel_1; +reg [ 1:0] d_result_sel_1; +output x_result_sel_csr; +reg x_result_sel_csr; + + + + + + + + + + + + +output x_result_sel_sext; +reg x_result_sel_sext; + + +output x_result_sel_logic; +reg x_result_sel_logic; + + + + + +output x_result_sel_add; +reg x_result_sel_add; +output m_result_sel_compare; +reg m_result_sel_compare; + + +output m_result_sel_shift; +reg m_result_sel_shift; + + +output w_result_sel_load; +reg w_result_sel_load; + + +output w_result_sel_mul; +reg w_result_sel_mul; + + +output x_bypass_enable; +wire x_bypass_enable; +output m_bypass_enable; +wire m_bypass_enable; +output read_enable_0; +wire read_enable_0; +output [ (5-1):0] read_idx_0; +wire [ (5-1):0] read_idx_0; +output read_enable_1; +wire read_enable_1; +output [ (5-1):0] read_idx_1; +wire [ (5-1):0] read_idx_1; +output write_enable; +wire write_enable; +output [ (5-1):0] write_idx; +wire [ (5-1):0] write_idx; +output [ (32-1):0] immediate; +wire [ (32-1):0] immediate; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; +output load; +wire load; +output store; +wire store; +output [ 1:0] size; +wire [ 1:0] size; +output sign_extend; +wire sign_extend; +output adder_op; +wire adder_op; +output [ 3:0] logic_op; +wire [ 3:0] logic_op; + + +output direction; +wire direction; + + + + + + + + + + + + + + + + + + + + + +output branch; +wire branch; +output branch_reg; +wire branch_reg; +output [ (3-1):0] condition; +wire [ (3-1):0] condition; +output bi_conditional; +wire bi_conditional; +output bi_unconditional; +wire bi_unconditional; + + +output break_opcode; +wire break_opcode; + + +output scall; +wire scall; +output eret; +wire eret; + + +output bret; +wire bret; + + + + + + + +output csr_write_enable; +wire csr_write_enable; + + + + + +wire [ (32-1):0] extended_immediate; +wire [ (32-1):0] high_immediate; +wire [ (32-1):0] call_immediate; +wire [ (32-1):0] branch_immediate; +wire sign_extend_immediate; +wire select_high_immediate; +wire select_call_immediate; + +wire op_add; +wire op_and; +wire op_andhi; +wire op_b; +wire op_bi; +wire op_be; +wire op_bg; +wire op_bge; +wire op_bgeu; +wire op_bgu; +wire op_bne; +wire op_call; +wire op_calli; +wire op_cmpe; +wire op_cmpg; +wire op_cmpge; +wire op_cmpgeu; +wire op_cmpgu; +wire op_cmpne; + + + + +wire op_lb; +wire op_lbu; +wire op_lh; +wire op_lhu; +wire op_lw; + + + + + + +wire op_mul; + + +wire op_nor; +wire op_or; +wire op_orhi; +wire op_raise; +wire op_rcsr; +wire op_sb; + + +wire op_sextb; +wire op_sexth; + + +wire op_sh; + + +wire op_sl; + + +wire op_sr; +wire op_sru; +wire op_sub; +wire op_sw; + + + + +wire op_wcsr; +wire op_xnor; +wire op_xor; + +wire arith; +wire logical; +wire cmp; +wire bra; +wire call; + + +wire shift; + + + + + + + + +wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - if (rst_i == 1'b1) - begin - operand_0_x <= { 32{1'b0}}; - operand_1_x <= { 32{1'b0}}; - store_operand_x <= { 32{1'b0}}; - branch_target_x <= { (32-2){1'b0}}; - x_result_sel_csr_x <= 1'b0; - x_result_sel_sext_x <= 1'b0; - x_result_sel_add_x <= 1'b0; - m_result_sel_compare_x <= 1'b0; - m_result_sel_shift_x <= 1'b0; - w_result_sel_load_x <= 1'b0; - w_result_sel_mul_x <= 1'b0; - x_bypass_enable_x <= 1'b0; - m_bypass_enable_x <= 1'b0; - write_enable_x <= 1'b0; - write_idx_x <= { 5{1'b0}}; - csr_x <= { 4 {1'b0}}; - load_x <= 1'b0; - store_x <= 1'b0; - size_x <= { 2{1'b0}}; - sign_extend_x <= 1'b0; - adder_op_x <= 1'b0; - adder_op_x_n <= 1'b0; - logic_op_x <= 4'h0; - direction_x <= 1'b0; - branch_x <= 1'b0; - branch_predict_x <= 1'b0; - branch_predict_taken_x <= 1'b0; - condition_x <= 3'b000; - scall_x <= 1'b0; - eret_x <= 1'b0; - csr_write_enable_x <= 1'b0; - operand_m <= { 32{1'b0}}; - branch_target_m <= { (32-2){1'b0}}; - m_result_sel_compare_m <= 1'b0; - m_result_sel_shift_m <= 1'b0; - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; - m_bypass_enable_m <= 1'b0; - branch_m <= 1'b0; - branch_predict_m <= 1'b0; - branch_predict_taken_m <= 1'b0; - exception_m <= 1'b0; - load_m <= 1'b0; - store_m <= 1'b0; - write_enable_m <= 1'b0; - write_idx_m <= { 5{1'b0}}; - condition_met_m <= 1'b0; - operand_w <= { 32{1'b0}}; - w_result_sel_load_w <= 1'b0; - w_result_sel_mul_w <= 1'b0; - write_idx_w <= { 5{1'b0}}; - write_enable_w <= 1'b0; - exception_w <= 1'b0; - end - else - begin - if (stall_x == 1'b0) - begin - operand_0_x <= d_result_0; - operand_1_x <= d_result_1; - store_operand_x <= bypass_data_1; - branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; - x_result_sel_csr_x <= x_result_sel_csr_d; - x_result_sel_sext_x <= x_result_sel_sext_d; - x_result_sel_add_x <= x_result_sel_add_d; - m_result_sel_compare_x <= m_result_sel_compare_d; - m_result_sel_shift_x <= m_result_sel_shift_d; - w_result_sel_load_x <= w_result_sel_load_d; - w_result_sel_mul_x <= w_result_sel_mul_d; - x_bypass_enable_x <= x_bypass_enable_d; - m_bypass_enable_x <= m_bypass_enable_d; - load_x <= load_d; - store_x <= store_d; - branch_x <= branch_d; - branch_predict_x <= branch_predict_d; - branch_predict_taken_x <= branch_predict_taken_d; - write_idx_x <= write_idx_d; - csr_x <= csr_d; - size_x <= size_d; - sign_extend_x <= sign_extend_d; - adder_op_x <= adder_op_d; - adder_op_x_n <= ~adder_op_d; - logic_op_x <= logic_op_d; - direction_x <= direction_d; - condition_x <= condition_d; - csr_write_enable_x <= csr_write_enable_d; - scall_x <= scall_d; - eret_x <= eret_d; - write_enable_x <= write_enable_d; - end - if (stall_m == 1'b0) - begin - operand_m <= x_result; - m_result_sel_compare_m <= m_result_sel_compare_x; - m_result_sel_shift_m <= m_result_sel_shift_x; - if (exception_x == 1'b1) - begin - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; - end - else - begin - w_result_sel_load_m <= w_result_sel_load_x; - w_result_sel_mul_m <= w_result_sel_mul_x; - end - m_bypass_enable_m <= m_bypass_enable_x; - load_m <= load_x; - store_m <= store_x; - branch_m <= branch_x; - branch_predict_m <= branch_predict_x; - branch_predict_taken_m <= branch_predict_taken_x; - if (exception_x == 1'b1) - write_idx_m <= 5'd30; - else - write_idx_m <= write_idx_x; - condition_met_m <= condition_met_x; - branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; - write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; - end - if (stall_m == 1'b0) - begin - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - exception_m <= 1'b1; - else - exception_m <= 1'b0; - end - operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; - w_result_sel_load_w <= w_result_sel_load_m; - w_result_sel_mul_w <= w_result_sel_mul_m; - write_idx_w <= write_idx_m; - write_enable_w <= write_enable_m; - exception_w <= exception_m; - end + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -always @(posedge clk_i ) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - if (rst_i == 1'b1) - begin - use_buf <= 1'b0; - reg_data_buf_0 <= { 32{1'b0}}; - reg_data_buf_1 <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) - use_buf <= 1'b0; - else if (use_buf == 1'b0) - begin - reg_data_buf_0 <= reg_data_live_0; - reg_data_buf_1 <= reg_data_live_1; - use_buf <= 1'b1; - end - if (reg_write_enable_q_w == 1'b1) - begin - if (write_idx_w == read_idx_0_d) - reg_data_buf_0 <= w_result; - if (write_idx_w == read_idx_1_d) - reg_data_buf_1 <= w_result; - end - end + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end -initial +endfunction + + + + + + + + + +assign op_add = instruction[ 30:26] == 5'b01101; +assign op_and = instruction[ 30:26] == 5'b01000; +assign op_andhi = instruction[ 31:26] == 6'b011000; +assign op_b = instruction[ 31:26] == 6'b110000; +assign op_bi = instruction[ 31:26] == 6'b111000; +assign op_be = instruction[ 31:26] == 6'b010001; +assign op_bg = instruction[ 31:26] == 6'b010010; +assign op_bge = instruction[ 31:26] == 6'b010011; +assign op_bgeu = instruction[ 31:26] == 6'b010100; +assign op_bgu = instruction[ 31:26] == 6'b010101; +assign op_bne = instruction[ 31:26] == 6'b010111; +assign op_call = instruction[ 31:26] == 6'b110110; +assign op_calli = instruction[ 31:26] == 6'b111110; +assign op_cmpe = instruction[ 30:26] == 5'b11001; +assign op_cmpg = instruction[ 30:26] == 5'b11010; +assign op_cmpge = instruction[ 30:26] == 5'b11011; +assign op_cmpgeu = instruction[ 30:26] == 5'b11100; +assign op_cmpgu = instruction[ 30:26] == 5'b11101; +assign op_cmpne = instruction[ 30:26] == 5'b11111; + + + + +assign op_lb = instruction[ 31:26] == 6'b000100; +assign op_lbu = instruction[ 31:26] == 6'b010000; +assign op_lh = instruction[ 31:26] == 6'b000111; +assign op_lhu = instruction[ 31:26] == 6'b001011; +assign op_lw = instruction[ 31:26] == 6'b001010; + + + + + + +assign op_mul = instruction[ 30:26] == 5'b00010; + + +assign op_nor = instruction[ 30:26] == 5'b00001; +assign op_or = instruction[ 30:26] == 5'b01110; +assign op_orhi = instruction[ 31:26] == 6'b011110; +assign op_raise = instruction[ 31:26] == 6'b101011; +assign op_rcsr = instruction[ 31:26] == 6'b100100; +assign op_sb = instruction[ 31:26] == 6'b001100; + + +assign op_sextb = instruction[ 31:26] == 6'b101100; +assign op_sexth = instruction[ 31:26] == 6'b110111; + + +assign op_sh = instruction[ 31:26] == 6'b000011; + + +assign op_sl = instruction[ 30:26] == 5'b01111; + + +assign op_sr = instruction[ 30:26] == 5'b00101; +assign op_sru = instruction[ 30:26] == 5'b00000; +assign op_sub = instruction[ 31:26] == 6'b110010; +assign op_sw = instruction[ 31:26] == 6'b010110; + + + + +assign op_wcsr = instruction[ 31:26] == 6'b110100; +assign op_xnor = instruction[ 30:26] == 5'b01001; +assign op_xor = instruction[ 30:26] == 5'b00110; + + +assign arith = op_add | op_sub; +assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; +assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; +assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; +assign bi_unconditional = op_bi; +assign bra = op_b | bi_unconditional | bi_conditional; +assign call = op_call | op_calli; + + +assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + +assign sext = op_sextb | op_sexth; + + + + + + + + + + + +assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; +assign store = op_sb | op_sh | op_sw; + + +always @(*) begin + + if (call) + d_result_sel_0 = 1'b1; + else + d_result_sel_0 = 1'b0; + if (call) + d_result_sel_1 = 2'b00; + else if ((instruction[31] == 1'b0) && !bra) + d_result_sel_1 = 2'b10; + else + d_result_sel_1 = 2'b01; + + x_result_sel_csr = 1'b0; + + + + + + + + + + + x_result_sel_sext = 1'b0; + + + x_result_sel_logic = 1'b0; + + + + + x_result_sel_add = 1'b0; + if (op_rcsr) + x_result_sel_csr = 1'b1; + + + + + + + + + + + + + + + + + + + + + + + else if (sext) + x_result_sel_sext = 1'b1; + + + else if (logical) + x_result_sel_logic = 1'b1; + + + + + + else + x_result_sel_add = 1'b1; + + + + m_result_sel_compare = cmp; + + + m_result_sel_shift = shift; + + + + + w_result_sel_load = load; + + + w_result_sel_mul = op_mul; + + end + + +assign x_bypass_enable = arith + | logical + + + + + + + + + + + + + + + + + + + + + | sext + + + + + + + | op_rcsr + ; + +assign m_bypass_enable = x_bypass_enable + + + | shift + + + | cmp + ; + +assign read_enable_0 = ~(op_bi | op_calli); +assign read_idx_0 = instruction[25:21]; + +assign read_enable_1 = ~(op_bi | op_calli | load); +assign read_idx_1 = instruction[20:16]; + +assign write_enable = ~(bra | op_raise | store | op_wcsr); +assign write_idx = call + ? 5'd29 + : instruction[31] == 1'b0 + ? instruction[20:16] + : instruction[15:11]; + + +assign size = instruction[27:26]; + +assign sign_extend = instruction[28]; + +assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + +assign logic_op = instruction[29:26]; + + + +assign direction = instruction[29]; + + + +assign branch = bra | call; +assign branch_reg = op_call | op_b; +assign condition = instruction[28:26]; + + +assign break_opcode = op_raise & ~instruction[2]; + + +assign scall = op_raise & instruction[2]; +assign eret = op_b & (instruction[25:21] == 5'd30); + + +assign bret = op_b & (instruction[25:21] == 5'd31); + + + + + + + + +assign csr_write_enable = op_wcsr; + + + +assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); +assign select_high_immediate = op_andhi | op_orhi; +assign select_call_immediate = instruction[31]; + +assign high_immediate = {instruction[15:0], 16'h0000}; +assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; +assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; +assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + +assign immediate = select_high_immediate == 1'b1 + ? high_immediate + : extended_immediate; + +assign branch_offset = select_call_immediate == 1'b1 + ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) + : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); + endmodule -module lm32_load_store_unit_medium ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_icache_medium_debug ( + clk_i, - rst_i, + rst_i, stall_a, - stall_x, - stall_m, - kill_x, - kill_m, - exception_m, - store_operand_x, - load_store_address_x, - load_store_address_m, - load_store_address_w, - load_x, - store_x, - load_q_x, - store_q_x, - load_q_m, - store_q_m, - sign_extend_x, - size_x, - d_dat_i, - d_ack_i, - d_err_i, - d_rty_i, - load_data_w, - stall_wb_load, - d_dat_o, - d_adr_o, - d_cyc_o, - d_sel_o, - d_stb_o, - d_we_o, - d_cti_o, - d_lock_o, - d_bte_o + stall_f, + address_a, + address_f, + read_enable_f, + refill_ready, + refill_data, + iflush, + + + + + valid_d, + branch_predict_taken_d, + + stall_request, + restart_request, + refill_request, + refill_address, + refilling, + inst ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; + +localparam addr_offset_width = clogb2(bytes_per_line)-1-2; +localparam addr_set_width = clogb2(sets)-1; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_x; -input stall_m; -input kill_x; -input kill_m; -input exception_m; -input [ (32-1):0] store_operand_x; -input [ (32-1):0] load_store_address_x; -input [ (32-1):0] load_store_address_m; -input [1:0] load_store_address_w; -input load_x; -input store_x; -input load_q_x; -input store_q_x; -input load_q_m; -input store_q_m; -input sign_extend_x; -input [ 1:0] size_x; -input [ (32-1):0] d_dat_i; -input d_ack_i; -input d_err_i; -input d_rty_i; -output [ (32-1):0] load_data_w; -reg [ (32-1):0] load_data_w; -output stall_wb_load; -reg stall_wb_load; -output [ (32-1):0] d_dat_o; -reg [ (32-1):0] d_dat_o; -output [ (32-1):0] d_adr_o; -reg [ (32-1):0] d_adr_o; -output d_cyc_o; -reg d_cyc_o; -output [ (4-1):0] d_sel_o; -reg [ (4-1):0] d_sel_o; -output d_stb_o; -reg d_stb_o; -output d_we_o; -reg d_we_o; -output [ (3-1):0] d_cti_o; -reg [ (3-1):0] d_cti_o; -output d_lock_o; -reg d_lock_o; -output [ (2-1):0] d_bte_o; -wire [ (2-1):0] d_bte_o; -reg [ 1:0] size_m; -reg [ 1:0] size_w; -reg sign_extend_m; -reg sign_extend_w; -reg [ (32-1):0] store_data_x; -reg [ (32-1):0] store_data_m; -reg [ (4-1):0] byte_enable_x; -reg [ (4-1):0] byte_enable_m; -wire [ (32-1):0] data_m; -reg [ (32-1):0] data_w; -wire wb_select_x; -reg wb_select_m; -reg [ (32-1):0] wb_data_m; -reg wb_load_complete; +localparam addr_set_lsb = (addr_offset_msb+1); +localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); +localparam addr_tag_lsb = (addr_set_msb+1); +localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; +localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + +input clk_i; +input rst_i; + +input stall_a; +input stall_f; + +input valid_d; +input branch_predict_taken_d; + +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; +input read_enable_f; + +input refill_ready; +input [ (32-1):0] refill_data; + +input iflush; + + + + + + + + + +output stall_request; +wire stall_request; +output restart_request; +reg restart_request; +output refill_request; +wire refill_request; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; +output refilling; +reg refilling; +output [ (32-1):0] inst; +wire [ (32-1):0] inst; + + + + + +wire enable; +wire [0:associativity-1] way_mem_we; +wire [ (32-1):0] way_data[0:associativity-1]; +wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; +wire [0:associativity-1] way_valid; +wire [0:associativity-1] way_match; +wire miss; + +wire [ (addr_set_width-1):0] tmem_read_address; +wire [ (addr_set_width-1):0] tmem_write_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; +wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; +wire [ ((addr_tag_width+1)-1):0] tmem_write_data; + +reg [ 3:0] state; +wire flushing; +wire check; +wire refill; + +reg [associativity-1:0] refill_way_select; +reg [ addr_offset_msb:addr_offset_lsb] refill_offset; +wire last_refill; +reg [ (addr_set_width-1):0] flush_set; + +genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -8643,6 +33793,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -8652,330 +33803,1659 @@ begin i = 0; for (i = 0; temp < value; i = i + 1) temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction - assign wb_select_x = 1'b1 - ; -always @(*) -begin - case (size_x) - 2'b00: store_data_x = {4{store_operand_x[7:0]}}; - 2'b11: store_data_x = {2{store_operand_x[15:0]}}; - 2'b10: store_data_x = store_operand_x; - default: store_data_x = { 32{1'bx}}; - endcase + clogb2_v1 = i-1; end -always @(*) +endfunction + + + + + + + + + generate + for (i = 0; i < associativity; i = i + 1) + begin : memories + + lm32_ram + #( + + .data_width (32), + .address_width ( (addr_offset_width+addr_set_width)) + +) + way_0_data_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (dmem_read_address), + .enable_read (enable), + .write_address (dmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i]), + .write_data (refill_data), + + .read_data (way_data[i]) + ); + + lm32_ram + #( + + .data_width ( (addr_tag_width+1)), + .address_width ( addr_set_width) + + ) + way_0_tag_ram + ( + + .read_clk (clk_i), + .write_clk (clk_i), + .reset (rst_i), + .read_address (tmem_read_address), + .enable_read (enable), + .write_address (tmem_write_address), + .enable_write ( 1'b1), + .write_enable (way_mem_we[i] | flushing), + .write_data (tmem_write_data), + + .read_data ({way_tag[i], way_valid[i]}) + ); + + end +endgenerate + + + + + + +generate + for (i = 0; i < associativity; i = i + 1) + begin : match +assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); + end +endgenerate + + +generate + if (associativity == 1) + begin : inst_1 +assign inst = way_match[0] ? way_data[0] : 32'b0; + end + else if (associativity == 2) + begin : inst_2 +assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); + end +endgenerate + + +generate + if (bytes_per_line > 4) +assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; + else +assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; +endgenerate + +assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + +assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; +assign tmem_write_address = flushing + ? flush_set + : refill_address[ addr_set_msb:addr_set_lsb]; + + +generate + if (bytes_per_line > 4) +assign last_refill = refill_offset == {addr_offset_width{1'b1}}; + else +assign last_refill = 1'b1; +endgenerate + + +assign enable = (stall_a == 1'b0); + + +generate + if (associativity == 1) + begin : we_1 +assign way_mem_we[0] = (refill_ready == 1'b1); + end + else + begin : we_2 +assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); +assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); + end +endgenerate + + +assign tmem_write_data[ 0] = last_refill & !flushing; +assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + +assign flushing = |state[1:0]; +assign check = state[2]; +assign refill = state[3]; + +assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); +assign stall_request = (check == 1'b0); +assign refill_request = (refill == 1'b1); + + + + + + +generate + if (associativity >= 2) + begin : way_select +always @(posedge clk_i ) begin - casez ({size_x, load_store_address_x[1:0]}) - { 2'b00, 2'b11}: byte_enable_x = 4'b0001; - { 2'b00, 2'b10}: byte_enable_x = 4'b0010; - { 2'b00, 2'b01}: byte_enable_x = 4'b0100; - { 2'b00, 2'b00}: byte_enable_x = 4'b1000; - { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; - { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; - { 2'b10, 2'b??}: byte_enable_x = 4'b1111; - default: byte_enable_x = 4'bxxxx; - endcase + if (rst_i == 1'b1) + refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + else + begin + if (miss == 1'b1) + refill_way_select <= {refill_way_select[0], refill_way_select[1]}; + end end - assign data_m = wb_data_m; -always @(*) + end +endgenerate + + +always @(posedge clk_i ) begin - casez ({size_w, load_store_address_w[1:0]}) - { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; - { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; - { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; - { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; - { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; - { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; - { 2'b10, 2'b??}: load_data_w = data_w; - default: load_data_w = { 32{1'bx}}; - endcase + if (rst_i == 1'b1) + refilling <= 1'b0; + else + refilling <= refill; end -assign d_bte_o = 2'b00; + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_dat_o <= { 32{1'b0}}; - d_adr_o <= { 32{1'b0}}; - d_sel_o <= { 4{ 1'b0}}; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; - d_lock_o <= 1'b0; - wb_data_m <= { 32{1'b0}}; - wb_load_complete <= 1'b0; - stall_wb_load <= 1'b0; + state <= 4'b0001; + flush_set <= { addr_set_width{1'b1}}; + refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + restart_request <= 1'b0; end - else + else begin - if (d_cyc_o == 1'b1) - begin - if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) - begin - begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_lock_o <= 1'b0; - end - wb_data_m <= d_dat_i; - wb_load_complete <= !d_we_o; - end - if (d_err_i == 1'b1) - $display ("Data bus error. Address: %x", d_adr_o); + case (state) + + + 4'b0001: + begin + if (flush_set == { addr_set_width{1'b0}}) + state <= 4'b0100; + flush_set <= flush_set - 1'b1; end - else - begin - if ( (store_q_m == 1'b1) - && (stall_m == 1'b0) - ) + + + 4'b0010: + begin + if (flush_set == { addr_set_width{1'b0}}) + + + + + + + state <= 4'b0100; + + flush_set <= flush_set - 1'b1; + end + + + 4'b0100: + begin + if (stall_a == 1'b0) + restart_request <= 1'b0; + if (iflush == 1'b1) begin - d_dat_o <= store_data_m; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b1; - d_cti_o <= 3'b111; - end - else if ( (load_q_m == 1'b1) - && (wb_select_m == 1'b1) - && (wb_load_complete == 1'b0) - ) + refill_address <= address_f; + state <= 4'b0010; + end + else if (miss == 1'b1) begin - stall_wb_load <= 1'b0; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; + refill_address <= address_f; + state <= 4'b1000; end end - if (stall_m == 1'b0) - wb_load_complete <= 1'b0; - if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) - stall_wb_load <= 1'b1; - if ((kill_m == 1'b1) || (exception_m == 1'b1)) - stall_wb_load <= 1'b0; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - sign_extend_m <= 1'b0; - size_m <= 2'b00; - byte_enable_m <= 1'b0; - store_data_m <= { 32{1'b0}}; - wb_select_m <= 1'b0; - end - else - begin - if (stall_m == 1'b0) - begin - sign_extend_m <= sign_extend_x; - size_m <= size_x; - byte_enable_m <= byte_enable_x; - store_data_m <= store_data_x; - wb_select_m <= wb_select_x; + + + 4'b1000: + begin + if (refill_ready == 1'b1) + begin + if (last_refill == 1'b1) + begin + restart_request <= 1'b1; + state <= 4'b0100; + end + end end + + endcase end end + +generate + if (bytes_per_line > 4) + begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else begin - size_w <= 2'b00; - data_w <= { 32{1'b0}}; - sign_extend_w <= 1'b0; - end - else - begin - size_w <= size_m; - data_w <= data_m; - sign_extend_w <= sign_extend_m; + case (state) + + + 4'b0100: + begin + if (iflush == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + else if (miss == 1'b1) + refill_offset <= {addr_offset_width{1'b0}}; + end + + + 4'b1000: + begin + if (refill_ready == 1'b1) + refill_offset <= refill_offset + 1'b1; + end + + endcase end end -always @(posedge clk_i) -begin - if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) - begin - if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) - $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); - if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) - $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end -end +endgenerate + endmodule -module lm32_decoder_medium ( - instruction, - d_result_sel_0, - d_result_sel_1, - x_result_sel_csr, - x_result_sel_sext, - x_result_sel_logic, - x_result_sel_add, - m_result_sel_compare, - m_result_sel_shift, - w_result_sel_load, - w_result_sel_mul, - x_bypass_enable, - m_bypass_enable, - read_enable_0, - read_idx_0, - read_enable_1, - read_idx_1, - write_enable, - write_idx, - immediate, - branch_offset, - load, - store, - size, - sign_extend, - adder_op, - logic_op, - direction, - branch, - branch_reg, - condition, - bi_conditional, - bi_unconditional, - scall, - eret, - csr_write_enable + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_debug_medium_debug ( + + clk_i, + rst_i, + pc_x, + load_x, + store_x, + load_store_address_x, + csr_write_enable_x, + csr_write_data, + csr_x, + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + + + + + eret_q_x, + bret_q_x, + stall_x, + exception_x, + q_x, + + + + + + + + + + dc_ss, + + + dc_re, + bp_match, + wp_match ); -input [ (32-1):0] instruction; -output [ 0:0] d_result_sel_0; -reg [ 0:0] d_result_sel_0; -output [ 1:0] d_result_sel_1; -reg [ 1:0] d_result_sel_1; -output x_result_sel_csr; -reg x_result_sel_csr; -output x_result_sel_sext; -reg x_result_sel_sext; -output x_result_sel_logic; -reg x_result_sel_logic; -output x_result_sel_add; -reg x_result_sel_add; -output m_result_sel_compare; -reg m_result_sel_compare; -output m_result_sel_shift; -reg m_result_sel_shift; -output w_result_sel_load; -reg w_result_sel_load; -output w_result_sel_mul; -reg w_result_sel_mul; -output x_bypass_enable; -wire x_bypass_enable; -output m_bypass_enable; -wire m_bypass_enable; -output read_enable_0; -wire read_enable_0; -output [ (5-1):0] read_idx_0; -wire [ (5-1):0] read_idx_0; -output read_enable_1; -wire read_enable_1; -output [ (5-1):0] read_idx_1; -wire [ (5-1):0] read_idx_1; -output write_enable; -wire write_enable; -output [ (5-1):0] write_idx; -wire [ (5-1):0] write_idx; -output [ (32-1):0] immediate; -wire [ (32-1):0] immediate; -output [ ((32-2)+2-1):2] branch_offset; -wire [ ((32-2)+2-1):2] branch_offset; -output load; -wire load; -output store; -wire store; -output [ 1:0] size; -wire [ 1:0] size; -output sign_extend; -wire sign_extend; -output adder_op; -wire adder_op; -output [ 3:0] logic_op; -wire [ 3:0] logic_op; -output direction; -wire direction; -output branch; -wire branch; -output branch_reg; -wire branch_reg; -output [ (3-1):0] condition; -wire [ (3-1):0] condition; -output bi_conditional; -wire bi_conditional; -output bi_unconditional; -wire bi_unconditional; -output scall; -wire scall; -output eret; -wire eret; -output csr_write_enable; -wire csr_write_enable; -wire [ (32-1):0] extended_immediate; -wire [ (32-1):0] high_immediate; -wire [ (32-1):0] call_immediate; -wire [ (32-1):0] branch_immediate; -wire sign_extend_immediate; -wire select_high_immediate; -wire select_call_immediate; -wire op_add; -wire op_and; -wire op_andhi; -wire op_b; -wire op_bi; -wire op_be; -wire op_bg; -wire op_bge; -wire op_bgeu; -wire op_bgu; -wire op_bne; -wire op_call; -wire op_calli; -wire op_cmpe; -wire op_cmpg; -wire op_cmpge; -wire op_cmpgeu; -wire op_cmpgu; -wire op_cmpne; -wire op_lb; -wire op_lbu; -wire op_lh; -wire op_lhu; -wire op_lw; -wire op_mul; -wire op_nor; -wire op_or; -wire op_orhi; -wire op_raise; -wire op_rcsr; -wire op_sb; -wire op_sextb; -wire op_sexth; -wire op_sh; -wire op_sl; -wire op_sr; -wire op_sru; -wire op_sub; -wire op_sw; -wire op_wcsr; -wire op_xnor; -wire op_xor; -wire arith; -wire logical; -wire cmp; -wire bra; -wire call; -wire shift; -wire sext; + + + + + +parameter breakpoints = 0; +parameter watchpoints = 0; + + + + + +input clk_i; +input rst_i; + +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +input load_x; +input store_x; +input [ (32-1):0] load_store_address_x; +input csr_write_enable_x; +input [ (32-1):0] csr_write_data; +input [ (5-1):0] csr_x; + + +input jtag_csr_write_enable; +input [ (32-1):0] jtag_csr_write_data; +input [ (5-1):0] jtag_csr; + + + + +input eret_q_x; +input bret_q_x; +input stall_x; +input exception_x; +input q_x; + + + + + + + + + + + + + +output dc_ss; +reg dc_ss; + + +output dc_re; +reg dc_re; +output bp_match; +wire bp_match; +output wp_match; +wire wp_match; + + + + + +genvar i; + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; +reg bp_e[0:breakpoints-1]; +wire [0:breakpoints-1]bp_match_n; + +reg [ 1:0] wpc_c[0:watchpoints-1]; +reg [ (32-1):0] wp[0:watchpoints-1]; +wire [0:watchpoints-1]wp_match_n; + +wire debug_csr_write_enable; +wire [ (32-1):0] debug_csr_write_data; +wire [ (5-1):0] debug_csr; + + + + +reg [ 2:0] state; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -8983,6 +35463,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -8995,135 +35476,582 @@ begin clogb2_v1 = i-1; end endfunction -assign op_add = instruction[ 30:26] == 5'b01101; -assign op_and = instruction[ 30:26] == 5'b01000; -assign op_andhi = instruction[ 31:26] == 6'b011000; -assign op_b = instruction[ 31:26] == 6'b110000; -assign op_bi = instruction[ 31:26] == 6'b111000; -assign op_be = instruction[ 31:26] == 6'b010001; -assign op_bg = instruction[ 31:26] == 6'b010010; -assign op_bge = instruction[ 31:26] == 6'b010011; -assign op_bgeu = instruction[ 31:26] == 6'b010100; -assign op_bgu = instruction[ 31:26] == 6'b010101; -assign op_bne = instruction[ 31:26] == 6'b010111; -assign op_call = instruction[ 31:26] == 6'b110110; -assign op_calli = instruction[ 31:26] == 6'b111110; -assign op_cmpe = instruction[ 30:26] == 5'b11001; -assign op_cmpg = instruction[ 30:26] == 5'b11010; -assign op_cmpge = instruction[ 30:26] == 5'b11011; -assign op_cmpgeu = instruction[ 30:26] == 5'b11100; -assign op_cmpgu = instruction[ 30:26] == 5'b11101; -assign op_cmpne = instruction[ 30:26] == 5'b11111; -assign op_lb = instruction[ 31:26] == 6'b000100; -assign op_lbu = instruction[ 31:26] == 6'b010000; -assign op_lh = instruction[ 31:26] == 6'b000111; -assign op_lhu = instruction[ 31:26] == 6'b001011; -assign op_lw = instruction[ 31:26] == 6'b001010; -assign op_mul = instruction[ 30:26] == 5'b00010; -assign op_nor = instruction[ 30:26] == 5'b00001; -assign op_or = instruction[ 30:26] == 5'b01110; -assign op_orhi = instruction[ 31:26] == 6'b011110; -assign op_raise = instruction[ 31:26] == 6'b101011; -assign op_rcsr = instruction[ 31:26] == 6'b100100; -assign op_sb = instruction[ 31:26] == 6'b001100; -assign op_sextb = instruction[ 31:26] == 6'b101100; -assign op_sexth = instruction[ 31:26] == 6'b110111; -assign op_sh = instruction[ 31:26] == 6'b000011; -assign op_sl = instruction[ 30:26] == 5'b01111; -assign op_sr = instruction[ 30:26] == 5'b00101; -assign op_sru = instruction[ 30:26] == 5'b00000; -assign op_sub = instruction[ 31:26] == 6'b110010; -assign op_sw = instruction[ 31:26] == 6'b010110; -assign op_wcsr = instruction[ 31:26] == 6'b110100; -assign op_xnor = instruction[ 30:26] == 5'b01001; -assign op_xor = instruction[ 30:26] == 5'b00110; -assign arith = op_add | op_sub; -assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; -assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; -assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; -assign bi_unconditional = op_bi; -assign bra = op_b | bi_unconditional | bi_conditional; -assign call = op_call | op_calli; -assign shift = op_sl | op_sr | op_sru; -assign sext = op_sextb | op_sexth; -assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; -assign store = op_sb | op_sh | op_sw; -always @(*) + + + + + + + + + +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_comb +assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); + end +endgenerate +generate + + + if (breakpoints > 0) +assign bp_match = (|bp_match_n) || (state == 3'b011); + else +assign bp_match = state == 3'b011; + + + + + + + +endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_comb +assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); + end +endgenerate +generate + if (watchpoints > 0) +assign wp_match = |wp_match_n; + else +assign wp_match = 1'b0; +endgenerate + + + + +assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); +assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; +assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; + + + + + + + + + + + + +generate + for (i = 0; i < breakpoints; i = i + 1) + begin : bp_seq +always @(posedge clk_i ) begin - if (call) - d_result_sel_0 = 1'b1; - else - d_result_sel_0 = 1'b0; - if (call) - d_result_sel_1 = 2'b00; - else if ((instruction[31] == 1'b0) && !bra) - d_result_sel_1 = 2'b10; + if (rst_i == 1'b1) + begin + bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; + bp_e[i] <= 1'b0; + end else - d_result_sel_1 = 2'b01; - x_result_sel_csr = 1'b0; - x_result_sel_sext = 1'b0; - x_result_sel_logic = 1'b0; - x_result_sel_add = 1'b0; - if (op_rcsr) - x_result_sel_csr = 1'b1; - else if (sext) - x_result_sel_sext = 1'b1; - else if (logical) - x_result_sel_logic = 1'b1; - else - x_result_sel_add = 1'b1; - m_result_sel_compare = cmp; - m_result_sel_shift = shift; - w_result_sel_load = load; - w_result_sel_mul = op_mul; + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) + begin + bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + bp_e[i] <= debug_csr_write_data[0]; + end + end +end + end +endgenerate + + +generate + for (i = 0; i < watchpoints; i = i + 1) + begin : wp_seq +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + wp[i] <= { 32{1'bx}}; + wpc_c[i] <= 2'b00; + end + else + begin + if (debug_csr_write_enable == 1'b1) + begin + if (debug_csr == 5'h8) + wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; + if (debug_csr == 5'h18 + i) + wp[i] <= debug_csr_write_data; + end + end end -assign x_bypass_enable = arith - | logical - | sext - | op_rcsr - ; -assign m_bypass_enable = x_bypass_enable - | shift - | cmp - ; -assign read_enable_0 = ~(op_bi | op_calli); -assign read_idx_0 = instruction[25:21]; -assign read_enable_1 = ~(op_bi | op_calli | load); -assign read_idx_1 = instruction[20:16]; -assign write_enable = ~(bra | op_raise | store | op_wcsr); -assign write_idx = call - ? 5'd29 - : instruction[31] == 1'b0 - ? instruction[20:16] - : instruction[15:11]; -assign size = instruction[27:26]; -assign sign_extend = instruction[28]; -assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; -assign logic_op = instruction[29:26]; -assign direction = instruction[29]; -assign branch = bra | call; -assign branch_reg = op_call | op_b; -assign condition = instruction[28:26]; -assign scall = op_raise & instruction[2]; -assign eret = op_b & (instruction[25:21] == 5'd30); -assign csr_write_enable = op_wcsr; -assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); -assign select_high_immediate = op_andhi | op_orhi; -assign select_call_immediate = instruction[31]; -assign high_immediate = {instruction[15:0], 16'h0000}; -assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; -assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; -assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; -assign immediate = select_high_immediate == 1'b1 - ? high_immediate - : extended_immediate; -assign branch_offset = select_call_immediate == 1'b1 - ? (call_immediate[ (32-2)-1:0]) - : (branch_immediate[ (32-2)-1:0]); -endmodule -module lm32_instruction_unit_medium ( + end +endgenerate + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + dc_re <= 1'b0; + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + dc_re <= debug_csr_write_data[1]; + end +end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + state <= 3'b000; + dc_ss <= 1'b0; + end + else + begin + if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) + begin + dc_ss <= debug_csr_write_data[0]; + if (debug_csr_write_data[0] == 1'b0) + state <= 3'b000; + else + state <= 3'b001; + end + case (state) + 3'b001: + begin + + if ( ( (eret_q_x == 1'b1) + || (bret_q_x == 1'b1) + ) + && (stall_x == 1'b0) + ) + state <= 3'b010; + end + 3'b010: + begin + + if ((q_x == 1'b1) && (stall_x == 1'b0)) + state <= 3'b011; + end + 3'b011: + begin + + + + + + + + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + begin + dc_ss <= 1'b0; + state <= 3'b100; + end + end + 3'b100: + begin + + + + + + + + state <= 3'b000; + end + endcase + end +end + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_medium_debug ( + clk_i, rst_i, + stall_a, stall_f, stall_d, @@ -9134,19 +36062,61 @@ module lm32_instruction_unit_medium ( kill_f, branch_predict_taken_d, branch_predict_address_d, + + + + + exception_m, branch_taken_m, branch_mispredict_taken_m, branch_target_m, + + + iflush, + + + + + + + + + + + i_dat_i, i_ack_i, i_err_i, i_rty_i, + + + + + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + + + + pc_f, pc_d, pc_x, pc_m, pc_w, + + + icache_stall_request, + icache_restart_request, + icache_refill_request, + icache_refilling, + + + + + i_dat_o, i_adr_o, i_cyc_o, @@ -9156,21 +36126,63 @@ module lm32_instruction_unit_medium ( i_cti_o, i_lock_o, i_bte_o, + + + + + + + + + + + jtag_read_data, + jtag_access_complete, + + + + + + + + instruction_f, + + instruction_d ); + + + + + parameter eba_reset = 32'h00000000; parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam eba_reset_minus_4 = eba_reset - 4; localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; input stall_d; @@ -9179,50 +36191,229 @@ input stall_m; input valid_f; input valid_d; input kill_f; + input branch_predict_taken_d; -input [ ((32-2)+2-1):2] branch_predict_address_d; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; + + + + + + input exception_m; input branch_taken_m; input branch_mispredict_taken_m; -input [ ((32-2)+2-1):2] branch_target_m; +input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; + + + +input iflush; + + + + + + + + + + + + input [ (32-1):0] i_dat_i; input i_ack_i; input i_err_i; input i_rty_i; -output [ ((32-2)+2-1):2] pc_f; -reg [ ((32-2)+2-1):2] pc_f; -output [ ((32-2)+2-1):2] pc_d; -reg [ ((32-2)+2-1):2] pc_d; -output [ ((32-2)+2-1):2] pc_x; -reg [ ((32-2)+2-1):2] pc_x; -output [ ((32-2)+2-1):2] pc_m; -reg [ ((32-2)+2-1):2] pc_m; -output [ ((32-2)+2-1):2] pc_w; -reg [ ((32-2)+2-1):2] pc_w; + + + + + +input jtag_read_enable; +input jtag_write_enable; +input [ 7:0] jtag_write_data; +input [ (32-1):0] jtag_address; + + + + + + + +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; +output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + +output icache_stall_request; +wire icache_stall_request; +output icache_restart_request; +wire icache_restart_request; +output icache_refill_request; +wire icache_refill_request; +output icache_refilling; +wire icache_refilling; + + + + + output [ (32-1):0] i_dat_o; -wire [ (32-1):0] i_dat_o; + + +reg [ (32-1):0] i_dat_o; + + + + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; -wire [ (4-1):0] i_sel_o; + + +reg [ (4-1):0] i_sel_o; + + + + output i_stb_o; reg i_stb_o; output i_we_o; -wire i_we_o; + + +reg i_we_o; + + + + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; output i_lock_o; reg i_lock_o; output [ (2-1):0] i_bte_o; wire [ (2-1):0] i_bte_o; + + + + + +output [ 7:0] jtag_read_data; +reg [ 7:0] jtag_read_data; +output jtag_access_complete; +wire jtag_access_complete; + + + + + + + + + + output [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_f; + + output [ (32-1):0] instruction_d; reg [ (32-1):0] instruction_d; -reg [ ((32-2)+2-1):2] pc_a; -reg [ (32-1):0] wb_data_f; + + + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; + + + +reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + + + + + +wire icache_read_enable_f; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; +reg icache_refill_ready; +reg [ (32-1):0] icache_refill_data; +wire [ (32-1):0] icache_data_f; +wire [ (3-1):0] first_cycle_type; +wire [ (3-1):0] next_cycle_type; +wire last_word; +wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + + + + + + + + + + + + + + + + + + + + + + + + + +reg jtag_access; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -9230,6 +36421,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -9242,213 +36434,2008 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + +lm32_icache_medium_debug #( + .associativity (associativity), + .sets (sets), + .bytes_per_line (bytes_per_line), + .base_address (base_address), + .limit (limit) + ) icache ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_a (stall_a), + .stall_f (stall_f), + .branch_predict_taken_d (branch_predict_taken_d), + .valid_d (valid_d), + .address_a (pc_a), + .address_f (pc_f), + .read_enable_f (icache_read_enable_f), + .refill_ready (icache_refill_ready), + .refill_data (icache_refill_data), + .iflush (iflush), + + .stall_request (icache_stall_request), + .restart_request (icache_restart_request), + .refill_request (icache_refill_request), + .refill_address (icache_refill_address), + .refilling (icache_refilling), + .inst (icache_data_f) + ); + + + + + + + + + + + assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + + + + + + + + ; + + + + always @(*) begin + + + + + + + if (branch_taken_m == 1'b1) if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) pc_a = pc_x; else pc_a = branch_target_m; + + + + + else if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) pc_a = branch_predict_address_d; else + + + if (icache_restart_request == 1'b1) + pc_a = restart_address; + else + + pc_a = pc_f + 1'b1; end -assign instruction_f = wb_data_f; -assign i_dat_o = 32'd0; -assign i_we_o = 1'b0; -assign i_sel_o = 4'b1111; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_f = icache_data_f; + + + + + + + + + + + + + + + + + + + assign i_bte_o = 2'b00; + + + + + + +generate + case (bytes_per_line) + 4: + begin +assign first_cycle_type = 3'b111; +assign next_cycle_type = 3'b111; +assign last_word = 1'b1; +assign first_address = icache_refill_address; + end + 8: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = 3'b111; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + 16: + begin +assign first_cycle_type = 3'b010; +assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; +assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; +assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; + end + endcase +endgenerate + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; + pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + end + else + begin + if (stall_f == 1'b0) + pc_f <= pc_a; + if (stall_d == 1'b0) + pc_d <= pc_f; + if (stall_x == 1'b0) + pc_x <= pc_d; + if (stall_m == 1'b0) + pc_m <= pc_x; + pc_w <= pc_m; + end +end + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; + else + begin + + + + + + + + + + + + + + + + if (icache_refill_request == 1'b1) + restart_address <= icache_refill_address; + + + + + end +end + + + + + + + + + + + + + + + + + + + + +assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); +always @(*) +begin + case (jtag_address[1:0]) + 2'b00: jtag_read_data = i_dat_i[ 31:24]; + 2'b01: jtag_read_data = i_dat_i[ 23:16]; + 2'b10: jtag_read_data = i_dat_i[ 15:8]; + 2'b11: jtag_read_data = i_dat_i[ 7:0]; + endcase +end + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + + + + + i_we_o <= 1'b0; + i_sel_o <= 4'b1111; + jtag_access <= 1'b0; + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + if (jtag_access == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_we_o <= 1'b0; + jtag_access <= 1'b0; + end + else + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + + + + + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + i_sel_o <= 4'b1111; + + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + + + end + + + else + begin + if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + begin + case (jtag_address[1:0]) + 2'b00: i_sel_o <= 4'b1000; + 2'b01: i_sel_o <= 4'b0100; + 2'b10: i_sel_o <= 4'b0010; + 2'b11: i_sel_o <= 4'b0001; + endcase + i_adr_o <= jtag_address; + i_dat_o <= {4{jtag_write_data}}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_we_o <= jtag_write_enable; + i_cti_o <= 3'b111; + jtag_access <= 1'b1; + end + end + + + + + + + + + + + + + + end + end + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_jtag_medium_debug ( + + clk_i, + rst_i, + jtag_clk, + jtag_update, + jtag_reg_q, + jtag_reg_addr_q, + + + csr, + csr_write_enable, + csr_write_data, + stall_x, + + + + + jtag_read_data, + jtag_access_complete, + + + + + exception_q_w, + + + + + + jtx_csr_read_data, + jrx_csr_read_data, + + + + + jtag_csr_write_enable, + jtag_csr_write_data, + jtag_csr, + jtag_read_enable, + jtag_write_enable, + jtag_write_data, + jtag_address, + + + + + jtag_break, + jtag_reset, + + + jtag_reg_d, + jtag_reg_addr_d + ); + + + + + +input clk_i; +input rst_i; + +input jtag_clk; +input jtag_update; +input [ 7:0] jtag_reg_q; +input [2:0] jtag_reg_addr_q; + + + +input [ (5-1):0] csr; +input csr_write_enable; +input [ (32-1):0] csr_write_data; +input stall_x; + + + + +input [ 7:0] jtag_read_data; +input jtag_access_complete; + + + + +input exception_q_w; + + + + + + + + + +output [ (32-1):0] jtx_csr_read_data; +wire [ (32-1):0] jtx_csr_read_data; +output [ (32-1):0] jrx_csr_read_data; +wire [ (32-1):0] jrx_csr_read_data; + + + + +output jtag_csr_write_enable; +reg jtag_csr_write_enable; +output [ (32-1):0] jtag_csr_write_data; +wire [ (32-1):0] jtag_csr_write_data; +output [ (5-1):0] jtag_csr; +wire [ (5-1):0] jtag_csr; +output jtag_read_enable; +reg jtag_read_enable; +output jtag_write_enable; +reg jtag_write_enable; +output [ 7:0] jtag_write_data; +wire [ 7:0] jtag_write_data; +output [ (32-1):0] jtag_address; +wire [ (32-1):0] jtag_address; + + + + +output jtag_break; +reg jtag_break; +output jtag_reset; +reg jtag_reset; + + +output [ 7:0] jtag_reg_d; +reg [ 7:0] jtag_reg_d; +output [2:0] jtag_reg_addr_d; +wire [2:0] jtag_reg_addr_d; + + + + + +reg rx_update; +reg rx_update_r; +reg rx_update_r_r; +reg rx_update_r_r_r; + + + +wire [ 7:0] rx_byte; +wire [2:0] rx_addr; + + + +reg [ 7:0] uart_tx_byte; +reg uart_tx_valid; +reg [ 7:0] uart_rx_byte; +reg uart_rx_valid; + + + +reg [ 3:0] command; + + +reg [ 7:0] jtag_byte_0; +reg [ 7:0] jtag_byte_1; +reg [ 7:0] jtag_byte_2; +reg [ 7:0] jtag_byte_3; +reg [ 7:0] jtag_byte_4; +reg processing; + + + +reg [ 3:0] state; + + + + + + + +assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_csr = jtag_byte_4[ (5-1):0]; +assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; +assign jtag_write_data = jtag_byte_4; + + + + + + +assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; + + + + + + +assign jtag_reg_addr_d[2] = processing; + + + + + + + +assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; +assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; + + + + + + + +assign rx_byte = jtag_reg_q; +assign rx_addr = jtag_reg_addr_q; + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - pc_f <= eba_reset_minus_4[ ((32-2)+2-1):2]; - pc_d <= { (32-2){1'b0}}; - pc_x <= { (32-2){1'b0}}; - pc_m <= { (32-2){1'b0}}; - pc_w <= { (32-2){1'b0}}; + rx_update <= 1'b0; + rx_update_r <= 1'b0; + rx_update_r_r <= 1'b0; + rx_update_r_r_r <= 1'b0; end else begin - if (stall_f == 1'b0) - pc_f <= pc_a; - if (stall_d == 1'b0) - pc_d <= pc_f; - if (stall_x == 1'b0) - pc_x <= pc_d; - if (stall_m == 1'b0) - pc_m <= pc_x; - pc_w <= pc_m; + rx_update <= jtag_update; + rx_update_r <= rx_update; + rx_update_r_r <= rx_update_r; + rx_update_r_r_r <= rx_update_r_r; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - wb_data_f <= { 32{1'b0}}; + state <= 4'h0; + command <= 4'b0000; + jtag_reg_d <= 8'h00; + + + processing <= 1'b0; + jtag_csr_write_enable <= 1'b0; + jtag_read_enable <= 1'b0; + jtag_write_enable <= 1'b0; + + + + + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + + + + + uart_tx_byte <= 8'h00; + uart_tx_valid <= 1'b0; + uart_rx_byte <= 8'h00; + uart_rx_valid <= 1'b0; + + end else - begin - if (i_cyc_o == 1'b1) + begin + + + if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) begin - if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + case (csr) + 5'he: + begin + + uart_tx_byte <= csr_write_data[ 7:0]; + uart_tx_valid <= 1'b1; + end + 5'hf: begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - wb_data_f <= i_dat_i; + + uart_rx_valid <= 1'b0; end + endcase end - else + + + + + + if (exception_q_w == 1'b1) begin - if ( (stall_a == 1'b0) - ) + jtag_break <= 1'b0; + jtag_reset <= 1'b0; + end + + + case (state) + 4'h0: + begin + + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) begin - i_adr_o <= {pc_a, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; + command <= rx_byte[7:4]; + case (rx_addr) + + + 3'b000: + begin + case (rx_byte[7:4]) + + + 4'b0001: + state <= 4'h1; + 4'b0011: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 4'h6; + end + 4'b0010: + state <= 4'h1; + 4'b0100: + begin + {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; + state <= 5; + end + 4'b0101: + state <= 4'h1; + + + 4'b0110: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + + + jtag_break <= 1'b1; + end + 4'b0111: + begin + + + uart_rx_valid <= 1'b0; + uart_tx_valid <= 1'b0; + + + jtag_reset <= 1'b1; + end + endcase + end + + + + + 3'b001: + begin + uart_rx_byte <= rx_byte; + uart_rx_valid <= 1'b1; + end + 3'b010: + begin + jtag_reg_d <= uart_tx_byte; + uart_tx_valid <= 1'b0; + end + + + default: + ; + endcase end - else - begin - if ( (stall_a == 1'b0) - ) - begin - end - end end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) + + + 4'h1: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_0 <= rx_byte; + state <= 4'h2; + end + end + 4'h2: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_1 <= rx_byte; + state <= 4'h3; + end + end + 4'h3: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_2 <= rx_byte; + state <= 4'h4; + end + end + 4'h4: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_3 <= rx_byte; + if (command == 4'b0001) + state <= 4'h6; + else + state <= 4'h5; + end + end + 4'h5: + begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) + begin + jtag_byte_4 <= rx_byte; + state <= 4'h6; + end + end + 4'h6: begin - instruction_d <= instruction_f; + case (command) + 4'b0001, + 4'b0011: + begin + jtag_read_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0010, + 4'b0100: + begin + jtag_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h7; + end + 4'b0101: + begin + jtag_csr_write_enable <= 1'b1; + processing <= 1'b1; + state <= 4'h8; + end + endcase end + 4'h7: + begin + if (jtag_access_complete == 1'b1) + begin + jtag_read_enable <= 1'b0; + jtag_reg_d <= jtag_read_data; + jtag_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + end + 4'h8: + begin + jtag_csr_write_enable <= 1'b0; + processing <= 1'b0; + state <= 4'h0; + end + + + endcase end -end +end + endmodule -module lm32_interrupt_medium ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_medium_debug ( + clk_i, rst_i, + interrupt, + stall_x, - exception, + + + non_debug_exception, + debug_exception, + + + + eret_q_x, + + + bret_q_x, + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; -input exception; + + + +input non_debug_exception; +input debug_exception; + + + + input eret_q_x; -input [ (4 -1):0] csr; + + +input bret_q_x; + + + +input [ (5-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; + + +reg bie; + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) - 4 'h0: csr_read_data = {{ 32-3{1'b0}}, - 1'b0, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + + bie, + + + + eie, ie }; - 4 'h2: csr_read_data = ip; - 4 'h1: csr_read_data = im; + 5'h2: csr_read_data = ip; + 5'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end end else begin + always @(*) begin case (csr) - 4 'h0: csr_read_data = {{ 32-3{1'b0}}, - 1'b0, + 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + + bie, + + + + eie, ie }; - 4 'h2: csr_read_data = ip; + 5'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + bie <= 1'b0; + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; - if (exception == 1'b1) + + + if (non_debug_exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + else if (debug_exception == 1'b1) + begin + + bie <= ie; + ie <= 1'b0; + end + + + + + + + + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + + else if (bret_q_x == 1'b1) + + ie <= bie; + + else if (csr_write_enable == 1'b1) begin - if (csr == 4 'h0) + + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + bie <= csr_write_data[2]; + + end - if (csr == 4 'h1) + if (csr == 5'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 4 'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -9457,40 +38444,83 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + bie <= 1'b0; + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; - if (exception == 1'b1) + + + if (non_debug_exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + else if (debug_exception == 1'b1) + begin + + bie <= ie; + ie <= 1'b0; + end + + + + + + + + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + else if (bret_q_x == 1'b1) + + ie <= bie; + + else if (csr_write_enable == 1'b1) begin - if (csr == 4 'h0) + + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + bie <= csr_write_data[2]; + + end - if (csr == 4 'h2) + if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -9498,19 +38528,635 @@ always @(posedge clk_i ) end end endgenerate + endmodule -module lm32_top_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_medium_icache_debug ( + clk_i, rst_i, + + interrupt, + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -9520,6 +39166,9 @@ module lm32_top_medium_debug ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -9530,19 +39179,58 @@ module lm32_top_medium_debug ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -9561,6 +39249,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -9579,6 +39270,14 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + wire [ 7:0] jtag_reg_d; wire [ 7:0] jtag_reg_q; wire jtag_update; @@ -9586,6 +39285,57 @@ wire [2:0] jtag_reg_addr_d; wire [2:0] jtag_reg_addr_q; wire jtck; wire jrstn; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -9593,6 +39343,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -9605,28 +39356,89 @@ begin clogb2_v1 = i-1; end endfunction -lm32_cpu_medium_debug + + + + + + + + +lm32_cpu_medium_icache_debug #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), + + + + + + + + + + + .jtag_clk (jtck), .jtag_update (jtag_update), .jtag_reg_q (jtag_reg_q), .jtag_reg_addr_q (jtag_reg_addr_q), + + + + + .I_DAT_I (I_DAT_I), .I_ACK_I (I_ACK_I), .I_ERR_I (I_ERR_I), .I_RTY_I (I_RTY_I), + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + .jtag_reg_d (jtag_reg_d), .jtag_reg_addr_d (jtag_reg_addr_d), + + + + + + + + + + + + .I_DAT_O (I_DAT_O), .I_ADR_O (I_ADR_O), .I_CYC_O (I_CYC_O), @@ -9636,6 +39448,9 @@ lm32_cpu_medium_debug .I_CTI_O (I_CTI_O), .I_LOCK_O (I_LOCK_O), .I_BTE_O (I_BTE_O), + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -9646,42 +39461,515 @@ lm32_cpu_medium_debug .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); + + + + jtag_cores jtag_cores ( + .reg_d (jtag_reg_d), .reg_addr_d (jtag_reg_addr_d), + .reg_update (jtag_update), .reg_q (jtag_reg_q), .reg_addr_q (jtag_reg_addr_q), .jtck (jtck), .jrstn (jrstn) ); + + + endmodule -module lm32_mc_arithmetic_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_medium_icache_debug ( + clk_i, rst_i, stall_d, kill_x, + + + + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + + + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + + + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -9690,11 +39978,23 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + + + case (state) 3'b000: begin @@ -9704,30 +40004,587 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule -module lm32_cpu_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_medium_icache_debug ( + clk_i, + + + + rst_i, + + + interrupt, + + + + + + + + + + + jtag_clk, jtag_update, jtag_reg_q, jtag_reg_addr_q, + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + + + + jtag_reg_d, jtag_reg_addr_d, + + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -9737,6 +40594,23 @@ module lm32_cpu_medium_debug ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -9746,42 +40620,168 @@ module lm32_cpu_medium_debug ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; + + parameter deba_reset = 32'h10000000; + + parameter sdb_address = 32'h00000000; + + + parameter icache_associativity = 1; parameter icache_sets = 256; parameter icache_bytes_per_line = 16; parameter icache_base_address = 32'h0; parameter icache_limit = 32'h7fffffff; + + + + + + + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 512; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 0; parameter dcache_limit = 0; + + + + + parameter watchpoints = 32'h4; + + + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; + + + + + + + + + + + input jtag_clk; input jtag_update; input [ 7:0] jtag_reg_q; input [2:0] jtag_reg_addr_q; + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + output [ 7:0] jtag_reg_d; wire [ 7:0] jtag_reg_d; output [2:0] jtag_reg_addr_d; wire [2:0] jtag_reg_addr_d; + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -9800,6 +40800,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -9818,12 +40821,33 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + reg valid_a; + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -9860,27 +40884,56 @@ reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; + + + + + + + + + + + + + wire x_result_sel_sext_d; reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + wire m_result_sel_shift_d; reg m_result_sel_shift_x; reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + wire w_result_sel_mul_d; reg w_result_sel_mul_x; reg w_result_sel_mul_m; reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -9907,81 +40960,234 @@ wire [ (5-1):0] csr_d; reg [ (5-1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + wire break_d; reg break_x; + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; + + + + + + + wire bret_d; reg bret_x; wire bret_q_x; + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + + + + + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; + + + + wire [ (32-1):0] sextb_result_x; wire [ (32-1):0] sexth_result_x; wire [ (32-1):0] sext_result_x; + + + + + + + + + + + wire direction_d; reg direction_x; wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; + + wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; + + wire iflush; wire icache_stall_request; wire icache_restart_request; wire icache_refill_request; wire icache_refilling; + + + + + + + + + + + + + wire [ (32-1):0] load_data_w; wire stall_wb_load; + + + + + + wire [ (32-1):0] jtx_csr_read_data; wire [ (32-1):0] jrx_csr_read_data; + + + + wire jtag_csr_write_enable; wire [ (32-1):0] jtag_csr_write_data; wire [ (5-1):0] jtag_csr; @@ -9991,29 +41197,63 @@ wire jtag_write_enable; wire [ 7:0] jtag_write_data; wire [ (32-1):0] jtag_address; wire jtag_access_complete; + + + + wire jtag_break; + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; + reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + + reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; + + reg [ (3-1):0] eid_x; + + + + + + + + + + wire dc_ss; + + wire dc_re; wire bp_match; wire wp_match; @@ -10027,11 +41267,90 @@ wire non_debug_exception_x; reg non_debug_exception_m; reg non_debug_exception_w; wire non_debug_exception_q_w; + + + + + + + + + + + + wire reset_exception; + + + + + + wire interrupt_exception; + + + + wire breakpoint_exception; wire watchpoint_exception; + + + + + + + + + + + wire system_call_exception; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -10039,6 +41358,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -10051,7 +41371,16 @@ begin clogb2_v1 = i-1; end endfunction -lm32_instruction_unit_medium_debug #( + + + + + + + + + +lm32_instruction_unit_medium_icache_debug #( .eba_reset (eba_reset), .associativity (icache_associativity), .sets (icache_sets), @@ -10059,8 +41388,10 @@ lm32_instruction_unit_medium_debug #( .base_address (icache_base_address), .limit (icache_limit) ) instruction_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_f (stall_f), .stall_d (stall_d), @@ -10071,28 +41402,61 @@ lm32_instruction_unit_medium_debug #( .kill_f (kill_f), .branch_predict_taken_d (branch_predict_taken_d), .branch_predict_address_d (branch_predict_address_d), + + + + + .exception_m (exception_m), .branch_taken_m (branch_taken_m), .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), + + .iflush (iflush), + + + + + + + + + + + .i_dat_i (I_DAT_I), .i_ack_i (I_ACK_I), .i_err_i (I_ERR_I), .i_rty_i (I_RTY_I), + + + + .jtag_read_enable (jtag_read_enable), .jtag_write_enable (jtag_write_enable), .jtag_write_data (jtag_write_data), .jtag_address (jtag_address), + + + + .pc_f (pc_f), .pc_d (pc_d), .pc_x (pc_x), .pc_m (pc_m), .pc_w (pc_w), + + .icache_stall_request (icache_stall_request), .icache_restart_request (icache_restart_request), .icache_refill_request (icache_refill_request), .icache_refilling (icache_refilling), + + + + + .i_dat_o (I_DAT_O), .i_adr_o (I_ADR_O), .i_cyc_o (I_CYC_O), @@ -10102,23 +41466,78 @@ lm32_instruction_unit_medium_debug #( .i_cti_o (I_CTI_O), .i_lock_o (I_LOCK_O), .i_bte_o (I_BTE_O), + + + + + + + + + + + + .jtag_read_data (jtag_read_data), .jtag_access_complete (jtag_access_complete), + + + + + + + + .instruction_f (instruction_f), + + + + .instruction_d (instruction_d) + + + ); -lm32_decoder_medium_debug decoder ( + + +lm32_decoder_medium_icache_debug decoder ( + .instruction (instruction_d), + .d_result_sel_0 (d_result_sel_0_d), .d_result_sel_1 (d_result_sel_1_d), .x_result_sel_csr (x_result_sel_csr_d), + + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + .x_result_sel_logic (x_result_sel_logic_d), + + + + .x_result_sel_add (x_result_sel_add_d), .m_result_sel_compare (m_result_sel_compare_d), + + .m_result_sel_shift (m_result_sel_shift_d), + + .w_result_sel_load (w_result_sel_load_d), + + .w_result_sel_mul (w_result_sel_mul_d), + + .x_bypass_enable (x_bypass_enable_d), .m_bypass_enable (m_bypass_enable_d), .read_enable_0 (read_enable_0_d), @@ -10135,27 +41554,61 @@ lm32_decoder_medium_debug decoder ( .sign_extend (sign_extend_d), .adder_op (adder_op_d), .logic_op (logic_op_d), + + .direction (direction_d), + + + + + + + + + + + + + + + + .branch (branch_d), .bi_unconditional (bi_unconditional), .bi_conditional (bi_conditional), .branch_reg (branch_reg_d), .condition (condition_d), + + .break_opcode (break_d), + + .scall (scall_d), .eret (eret_d), + + .bret (bret_d), + + + + + + .csr_write_enable (csr_write_enable_d) ); -lm32_load_store_unit_medium_debug #( + + +lm32_load_store_unit_medium_icache_debug #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), .base_address (dcache_base_address), .limit (dcache_limit) ) load_store_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_x (stall_x), .stall_m (stall_m), @@ -10174,12 +41627,39 @@ lm32_load_store_unit_medium_debug #( .store_q_m (store_q_m), .sign_extend_x (sign_extend_x), .size_x (size_x), + + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), .d_ack_i (D_ACK_I), .d_err_i (D_ERR_I), .d_rty_i (D_RTY_I), + + + + + + + + + .load_data_w (load_data_w), .stall_wb_load (stall_wb_load), + .d_dat_o (D_DAT_O), .d_adr_o (D_ADR_O), .d_cyc_o (D_CYC_O), @@ -10190,22 +41670,36 @@ lm32_load_store_unit_medium_debug #( .d_lock_o (D_LOCK_O), .d_bte_o (D_BTE_O) ); + + lm32_adder adder ( + .adder_op_x (adder_op_x), .adder_op_x_n (adder_op_x_n), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .adder_result_x (adder_result_x), .adder_carry_n_x (adder_carry_n_x), .adder_overflow_x (adder_overflow_x) ); + + lm32_logic_op logic_op ( + .logic_op_x (logic_op_x), .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + .logic_result_x (logic_result_x) ); + + + + lm32_shifter shifter ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), @@ -10213,48 +41707,139 @@ lm32_shifter shifter ( .sign_extend_x (sign_extend_x), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .shifter_result_m (shifter_result_m) ); + + + + + + lm32_multiplier multiplier ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), .stall_m (stall_m), .operand_0 (d_result_0), .operand_1 (d_result_1), + .result (multiplier_result_w) ); -lm32_interrupt_medium_debug interrupt_unit ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +lm32_interrupt_medium_icache_debug interrupt_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .interrupt (interrupt), + .stall_x (stall_x), + + .non_debug_exception (non_debug_exception_q_w), .debug_exception (debug_exception_q_w), + + + + .eret_q_x (eret_q_x), + + .bret_q_x (bret_q_x), + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), + .interrupt_exception (interrupt_exception), + .csr_read_data (interrupt_csr_read_data_x) ); -lm32_jtag_medium_debug jtag ( + + + + + + +lm32_jtag_medium_icache_debug jtag ( + .clk_i (clk_i), .rst_i (rst_i), + .jtag_clk (jtag_clk), .jtag_update (jtag_update), .jtag_reg_q (jtag_reg_q), .jtag_reg_addr_q (jtag_reg_addr_q), + + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), .stall_x (stall_x), + + + + .jtag_read_data (jtag_read_data), .jtag_access_complete (jtag_access_complete), + + + + .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), + + + + + + .jtx_csr_read_data (jtx_csr_read_data), .jrx_csr_read_data (jrx_csr_read_data), + + + + .jtag_csr_write_enable (jtag_csr_write_enable), .jtag_csr_write_data (jtag_csr_write_data), .jtag_csr (jtag_csr), @@ -10262,15 +41847,29 @@ lm32_jtag_medium_debug jtag ( .jtag_write_enable (jtag_write_enable), .jtag_write_data (jtag_write_data), .jtag_address (jtag_address), + + + + .jtag_break (jtag_break), .jtag_reset (reset_exception), + + + .jtag_reg_d (jtag_reg_d), .jtag_reg_addr_d (jtag_reg_addr_d) ); -lm32_debug_medium_debug #( + + + + + + +lm32_debug_medium_icache_debug #( .breakpoints (breakpoints), .watchpoints (watchpoints) ) hw_debug ( + .clk_i (clk_i), .rst_i (rst_i), .pc_x (pc_x), @@ -10280,23 +41879,63 @@ lm32_debug_medium_debug #( .csr_write_enable_x (csr_write_enable_q_x), .csr_write_data (operand_1_x), .csr_x (csr_x), + + .jtag_csr_write_enable (jtag_csr_write_enable), .jtag_csr_write_data (jtag_csr_write_data), .jtag_csr (jtag_csr), + + + + .eret_q_x (eret_q_x), .bret_q_x (bret_q_x), .stall_x (stall_x), .exception_x (exception_x), .q_x (q_x), + + + + + + + + + .dc_ss (dc_ss), + + .dc_re (dc_re), .bp_match (bp_match), .wp_match (wp_match) ); + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; reg [31:0] w_result_d; reg regfile_raw_0, regfile_raw_0_nxt; reg regfile_raw_1, regfile_raw_1_nxt; + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) begin if (reg_write_enable_q_w @@ -10304,22 +41943,39 @@ lm32_debug_medium_debug #( regfile_raw_0_nxt = 1'b1; else regfile_raw_0_nxt = 1'b0; + if (reg_write_enable_q_w && (write_idx_w == instruction_f[20:16])) regfile_raw_1_nxt = 1'b1; else regfile_raw_1_nxt = 1'b0; end + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) if (regfile_raw_0) reg_data_live_0 = w_result_d; else reg_data_live_0 = regfile_data_0; + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) if (regfile_raw_1) reg_data_live_1 = w_result_d; else reg_data_live_1 = regfile_data_1; + + + + always @(posedge clk_i ) if (rst_i == 1'b1) begin @@ -10333,22 +41989,31 @@ lm32_debug_medium_debug #( regfile_raw_1 <= regfile_raw_1_nxt; w_result_d <= w_result; end + + + + + lm32_dp_ram #( + .addr_depth(1<<5), .addr_width(5), .data_width(32) ) reg_0 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[25:21]), + .rdata_o (regfile_data_0) ); + lm32_dp_ram #( .addr_depth(1<<5), @@ -10357,22 +42022,118 @@ lm32_debug_medium_debug #( ) reg_1 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[20:16]), + .rdata_o (regfile_data_1) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + always @(*) begin if ( ( (x_bypass_enable_x == 1'b0) @@ -10390,6 +42151,8 @@ begin else interlock = 1'b0; end + + always @(*) begin if (raw_x_0 == 1'b1) @@ -10401,6 +42164,8 @@ begin else bypass_data_0 = reg_data_0; end + + always @(*) begin if (raw_x_1 == 1'b1) @@ -10412,10 +42177,25 @@ begin else bypass_data_1 = reg_data_1; end + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + assign branch_target_d = pc_d + branch_offset_d; + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + always @(*) begin d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; @@ -10426,9 +42206,30 @@ begin default: d_result_1 = { 32{1'bx}}; endcase end + + + + + + + + + + + assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + assign cmp_zero = operand_0_x == operand_1_x; assign cmp_negative = adder_result_x[ 32-1]; assign cmp_overflow = adder_overflow_x; @@ -10447,25 +42248,68 @@ begin default: condition_met_x = 1'bx; endcase end + + always @(*) begin x_result = x_result_sel_add_x ? adder_result_x : x_result_sel_csr_x ? csr_read_data_x + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + + : logic_result_x; end + + always @(*) begin m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + : m_result_sel_shift_m ? shifter_result_m + + : operand_m; end + + always @(*) begin w_result = w_result_sel_load_w ? load_data_w + + : w_result_sel_mul_w ? multiplier_result_w + + : operand_w; end + + + + + + + + + + + + + assign branch_taken_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -10480,9 +42324,13 @@ assign branch_taken_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign branch_mispredict_taken_m = (condition_met_m == 1'b0) && (branch_predict_m == 1'b1) && (branch_predict_taken_m == 1'b1); + + assign branch_flushX_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -10495,67 +42343,245 @@ assign branch_flushX_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign kill_f = ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) || (branch_taken_m == 1'b1) + + + + + + || (icache_refill_request == 1'b1) + + + + + + ; assign kill_d = (branch_taken_m == 1'b1) + + + + + + || (icache_refill_request == 1'b1) + + + + + + ; assign kill_x = (branch_flushX_m == 1'b1) + + + + ; assign kill_m = 1'b0 + + + + ; assign kill_w = 1'b0 + + + + ; + + + + + assign breakpoint_exception = ( ( (break_x == 1'b1) || (bp_match == 1'b1) ) && (valid_x == 1'b1) ) + + || (jtag_break == 1'b1) + + ; + + + + + assign watchpoint_exception = wp_match == 1'b1; + + + + + + + + + + + + + + + + assign system_call_exception = ( (scall_x == 1'b1) + + + + ); + + + assign debug_exception_x = (breakpoint_exception == 1'b1) || (watchpoint_exception == 1'b1) ; + assign non_debug_exception_x = (system_call_exception == 1'b1) + + || (reset_exception == 1'b1) + + + + + + + + + + + + + || ( (interrupt_exception == 1'b1) + + && (dc_ss == 1'b0) + + + + + + + ) + + ; + assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin + + + + if (reset_exception == 1'b1) eid_x = 3'h0; else + + + + + + + + if (breakpoint_exception == 1'b1) eid_x = 3'd1; else + + + + + + + + + + + + + if (watchpoint_exception == 1'b1) eid_x = 3'd3; else + + + + + + + + + + if ( (interrupt_exception == 1'b1) + + && (dc_ss == 1'b0) + + ) eid_x = 3'h6; else + + eid_x = 3'h7; end + + + assign stall_a = (stall_f == 1'b1); + assign stall_f = (stall_d == 1'b1); + assign stall_d = (stall_x == 1'b1) || ( (interlock == 1'b1) && (kill_d == 1'b0) ) || ( ( (eret_d == 1'b1) || (scall_d == 1'b1) + + + + ) && ( (load_q_x == 1'b1) || (load_q_m == 1'b1) @@ -10565,6 +42591,8 @@ assign stall_d = (stall_x == 1'b1) ) && (kill_d == 1'b0) ) + + || ( ( (break_d == 1'b1) || (bret_d == 1'b1) ) @@ -10576,93 +42604,337 @@ assign stall_d = (stall_x == 1'b1) ) && (kill_d == 1'b0) ) + + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) ) + + + + + + + + + + ; + assign stall_x = (stall_m == 1'b1) + + + + + + + + ; + assign stall_m = (stall_wb_load == 1'b1) + + + + || ( (D_CYC_O == 1'b1) && ( (store_m == 1'b1) + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + || (load_m == 1'b1) || (load_x == 1'b1) ) ) + + + + + + + + || (icache_stall_request == 1'b1) || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) + + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); + + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + + && (bp_match == 1'b0) + + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + + && (bp_match == 1'b0) + + ; + + + + assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); + + + + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + assign cfg = { 6'h02, watchpoints[3:0], breakpoints[3:0], interrupts[5:0], + + 1'b1, + + + + + + + + 1'b0, + + + + 1'b1, + + + + + + 1'b1, + + + + + + 1'b1, + + + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + 1'b1, + + + + + + 1'b1, + + + + + + + + 1'b0, + + + + 1'b1 + + + + }; + assign cfg2 = { 30'b0, + + + + 1'b0, + + + + + + 1'b0 + + }; + + + + assign iflush = ( (csr_write_enable_d == 1'b1) && (csr_d == 5'h3) && (stall_d == 1'b0) && (kill_d == 1'b0) && (valid_d == 1'b1)) + + + || ( (jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h3)) + + ; + + + + + + + + + + + + + + + + assign csr_d = read_idx_0_d[ (5-1):0]; + + always @(*) begin case (csr_x) + + 5'h0, 5'h1, 5'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + 5'h6: csr_read_data_x = cfg; 5'h7: csr_read_data_x = {eba, 8'h00}; + + 5'h9: csr_read_data_x = {deba, 8'h00}; + + + + 5'he: csr_read_data_x = jtx_csr_read_data; 5'hf: csr_read_data_x = jrx_csr_read_data; + + 5'ha: csr_read_data_x = cfg2; 5'hb: csr_read_data_x = sdb_address; + default: csr_read_data_x = { 32{1'bx}}; endcase end + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -10671,10 +42943,18 @@ begin begin if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -10683,10 +42963,68 @@ begin begin if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin if (icache_refill_request == 1'b1) @@ -10696,6 +43034,23 @@ begin else valid_a = !icache_refilling; end + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -10709,48 +43064,88 @@ begin else begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + valid_f <= valid_a; + + + + else if (stall_f == 1'b0) valid_f <= 1'b0; + if (kill_d == 1'b1) valid_d <= 1'b0; else if (stall_f == 1'b0) valid_d <= valid_f & !kill_f; else if (stall_d == 1'b0) valid_d <= 1'b0; + if (stall_d == 1'b0) valid_x <= valid_d & !kill_d; else if (kill_x == 1'b1) valid_x <= 1'b0; else if (stall_x == 1'b0) valid_x <= 1'b0; + if (kill_m == 1'b1) valid_m <= 1'b0; else if (stall_x == 1'b0) valid_m <= valid_x & !kill_x; else if (stall_m == 1'b0) valid_m <= 1'b0; + if (stall_m == 1'b0) valid_w <= valid_m & !kill_m; else valid_w <= 1'b0; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin + + + + operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; x_result_sel_csr_x <= 1'b0; + + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + x_result_sel_add_x <= 1'b0; m_result_sel_compare_x <= 1'b0; + + m_result_sel_shift_x <= 1'b0; + + w_result_sel_load_x <= 1'b0; + + w_result_sel_mul_x <= 1'b0; + + x_bypass_enable_x <= 1'b0; m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; @@ -10763,22 +43158,52 @@ begin adder_op_x <= 1'b0; adder_op_x_n <= 1'b0; logic_op_x <= 4'h0; + + direction_x <= 1'b0; + + + + + + + branch_x <= 1'b0; branch_predict_x <= 1'b0; branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + + break_x <= 1'b0; + + scall_x <= 1'b0; eret_x <= 1'b0; + + bret_x <= 1'b0; + + + + + + + csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; m_result_sel_compare_m <= 1'b0; + + m_result_sel_shift_m <= 1'b0; + + w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + m_bypass_enable_m <= 1'b0; branch_m <= 1'b0; branch_predict_m <= 1'b0; @@ -10789,31 +43214,83 @@ begin write_enable_m <= 1'b0; write_idx_m <= { 5{1'b0}}; condition_met_m <= 1'b0; + + + + + + debug_exception_m <= 1'b0; non_debug_exception_m <= 1'b0; + + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; + + w_result_sel_mul_w <= 1'b0; + + write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; + + debug_exception_w <= 1'b0; non_debug_exception_w <= 1'b0; + + + + + + + + end else begin + + if (stall_x == 1'b0) begin + + + + operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; + + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + x_result_sel_add_x <= x_result_sel_add_d; m_result_sel_compare_x <= m_result_sel_compare_d; + + m_result_sel_shift_x <= m_result_sel_shift_d; + + w_result_sel_load_x <= w_result_sel_load_d; + + w_result_sel_mul_x <= w_result_sel_mul_d; + + x_bypass_enable_x <= x_bypass_enable_d; m_bypass_enable_x <= m_bypass_enable_d; load_x <= load_d; @@ -10828,43 +43305,100 @@ begin adder_op_x <= adder_op_d; adder_op_x_n <= ~adder_op_d; logic_op_x <= logic_op_d; + + direction_x <= direction_d; + + + + + + condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + + break_x <= break_d; + + scall_x <= scall_d; + + + + eret_x <= eret_d; + + bret_x <= bret_d; + + write_enable_x <= write_enable_d; end + + + if (stall_m == 1'b0) begin operand_m <= x_result; m_result_sel_compare_m <= m_result_sel_compare_x; + + m_result_sel_shift_m <= m_result_sel_shift_x; + + if (exception_x == 1'b1) begin w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + end else begin w_result_sel_load_m <= w_result_sel_load_x; + + w_result_sel_mul_m <= w_result_sel_mul_x; + + end m_bypass_enable_m <= m_bypass_enable_x; load_m <= load_x; store_m <= store_x; + + + + branch_m <= branch_x; branch_predict_m <= branch_predict_x; branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + if (non_debug_exception_x == 1'b1) write_idx_m <= 5'd30; else if (debug_exception_x == 1'b1) write_idx_m <= 5'd31; else write_idx_m <= write_idx_x; + + + + + + + condition_met_m <= condition_met_x; + + if (exception_x == 1'b1) if ((dc_re == 1'b1) || ((debug_exception_x == 1'b1) @@ -10874,26 +43408,99 @@ begin branch_target_m <= {eba, eid_x, {3{1'b0}}}; else branch_target_m <= branch_target_x; + + + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + debug_exception_m <= debug_exception_x; non_debug_exception_m <= non_debug_exception_x; + + end + + if (stall_m == 1'b0) begin if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) exception_m <= 1'b1; else exception_m <= 1'b0; + + + + + + + + end + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + w_result_sel_load_w <= w_result_sel_load_m; + + w_result_sel_mul_w <= w_result_sel_mul_m; + + write_idx_w <= write_idx_m; + + + + + + + + write_enable_w <= write_enable_m; + + debug_exception_w <= debug_exception_m; non_debug_exception_w <= non_debug_exception_m; + + + + + + + + + + + + + end end + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -10921,13 +43528,521 @@ begin end end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + initial begin + + + + + + end + + + endmodule -module lm32_load_store_unit_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_medium_icache_debug +( + clk_i, + + + + rst_i, + stall_a, stall_x, stall_m, @@ -10946,12 +44061,37 @@ module lm32_load_store_unit_medium_debug ( store_q_m, sign_extend_x, size_x, + + + + + d_dat_i, d_ack_i, d_err_i, d_rty_i, + + + + + + + + + + + + + + + + + + + load_data_w, stall_wb_load, + d_dat_o, d_adr_o, d_cyc_o, @@ -10962,22 +44102,37 @@ module lm32_load_store_unit_medium_debug ( d_lock_o, d_bte_o ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; + + + + + + input clk_i; + input rst_i; + input stall_a; input stall_x; input stall_m; input kill_x; input kill_m; input exception_m; + input [ (32-1):0] store_operand_x; input [ (32-1):0] load_store_address_x; input [ (32-1):0] load_store_address_m; @@ -10990,14 +44145,57 @@ input load_q_m; input store_q_m; input sign_extend_x; input [ 1:0] size_x; + + + + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + input [ (32-1):0] d_dat_i; input d_ack_i; input d_err_i; input d_rty_i; + + + + + + + + + + + + + + + + + + output [ (32-1):0] load_data_w; reg [ (32-1):0] load_data_w; output stall_wb_load; reg stall_wb_load; + output [ (32-1):0] d_dat_o; reg [ (32-1):0] d_dat_o; output [ (32-1):0] d_adr_o; @@ -11016,6 +44214,12 @@ output d_lock_o; reg d_lock_o; output [ (2-1):0] d_bte_o; wire [ (2-1):0] d_bte_o; + + + + + + reg [ 1:0] size_m; reg [ 1:0] size_w; reg sign_extend_m; @@ -11026,10 +44230,113 @@ reg [ (4-1):0] byte_enable_x; reg [ (4-1):0] byte_enable_m; wire [ (32-1):0] data_m; reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + wire wb_select_x; + + + + + + + + + + reg wb_select_m; reg [ (32-1):0] wb_data_m; reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -11037,6 +44344,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -11049,8 +44357,116 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + + ; + + always @(*) begin case (size_x) @@ -11060,6 +44476,8 @@ begin default: store_data_x = { 32{1'bx}}; endcase end + + always @(*) begin casez ({size_x, load_store_address_x[1:0]}) @@ -11073,7 +44491,90 @@ begin default: byte_enable_x = 4'bxxxx; endcase end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_data_m; + + + + + + + + always @(*) begin casez ({size_w, load_store_address_w[1:0]}) @@ -11087,7 +44588,45 @@ begin default: load_data_w = { 32{1'bx}}; endcase end + + assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11103,30 +44642,85 @@ begin wb_data_m <= { 32{1'b0}}; wb_load_complete <= 1'b0; stall_wb_load <= 1'b0; + + + + end else begin + + + + + + if (d_cyc_o == 1'b1) begin + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) begin + + + + + + + + + begin + d_cyc_o <= 1'b0; d_stb_o <= 1'b0; d_lock_o <= 1'b0; end + + + + + + + wb_data_m <= d_dat_i; + wb_load_complete <= !d_we_o; end + if (d_err_i == 1'b1) $display ("Data bus error. Address: %x", d_adr_o); + end else begin + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) && (stall_m == 1'b0) + + + + + + + + ) begin + d_dat_o <= store_data_m; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -11138,8 +44732,10 @@ begin else if ( (load_q_m == 1'b1) && (wb_select_m == 1'b1) && (wb_load_complete == 1'b0) + ) begin + stall_wb_load <= 1'b0; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -11149,14 +44745,21 @@ begin d_cti_o <= 3'b111; end end + if (stall_m == 1'b0) wb_load_complete <= 1'b0; + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) stall_wb_load <= 1'b1; + if ((kill_m == 1'b1) || (exception_m == 1'b1)) stall_wb_load <= 1'b0; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11165,6 +44768,19 @@ begin size_m <= 2'b00; byte_enable_m <= 1'b0; store_data_m <= { 32{1'b0}}; + + + + + + + + + + + + + wb_select_m <= 1'b0; end else @@ -11175,10 +44791,25 @@ begin size_m <= size_x; byte_enable_m <= byte_enable_x; store_data_m <= store_data_x; + + + + + + + + + + + + + wb_select_m <= wb_select_x; end end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11190,10 +44821,24 @@ begin else begin size_w <= size_m; + + + + + data_w <= data_m; + sign_extend_w <= sign_extend_m; end end + + + + + + + + always @(posedge clk_i) begin if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) @@ -11204,19 +44849,510 @@ begin $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end end + + + endmodule -module lm32_decoder_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_medium_icache_debug ( + instruction, + d_result_sel_0, d_result_sel_1, x_result_sel_csr, + + + + + + + + + + x_result_sel_sext, + + x_result_sel_logic, + + + + x_result_sel_add, m_result_sel_compare, + + m_result_sel_shift, + + w_result_sel_load, + + w_result_sel_mul, + + x_bypass_enable, m_bypass_enable, read_enable_0, @@ -11233,39 +45369,106 @@ module lm32_decoder_medium_debug ( sign_extend, adder_op, logic_op, + + direction, + + + + + + + + + + + + + + + + branch, branch_reg, condition, bi_conditional, bi_unconditional, + + break_opcode, + + scall, eret, + + bret, + + + + + + csr_write_enable ); + + + + + input [ (32-1):0] instruction; + + + + + output [ 0:0] d_result_sel_0; reg [ 0:0] d_result_sel_0; output [ 1:0] d_result_sel_1; reg [ 1:0] d_result_sel_1; output x_result_sel_csr; reg x_result_sel_csr; + + + + + + + + + + + + output x_result_sel_sext; reg x_result_sel_sext; + + output x_result_sel_logic; reg x_result_sel_logic; + + + + + output x_result_sel_add; reg x_result_sel_add; output m_result_sel_compare; reg m_result_sel_compare; + + output m_result_sel_shift; reg m_result_sel_shift; + + output w_result_sel_load; reg w_result_sel_load; + + output w_result_sel_mul; reg w_result_sel_mul; + + output x_bypass_enable; wire x_bypass_enable; output m_bypass_enable; @@ -11298,8 +45501,31 @@ output adder_op; wire adder_op; output [ 3:0] logic_op; wire [ 3:0] logic_op; + + output direction; wire direction; + + + + + + + + + + + + + + + + + + + + + output branch; wire branch; output branch_reg; @@ -11310,16 +45536,34 @@ output bi_conditional; wire bi_conditional; output bi_unconditional; wire bi_unconditional; + + output break_opcode; wire break_opcode; + + output scall; wire scall; output eret; wire eret; + + output bret; wire bret; + + + + + + + output csr_write_enable; wire csr_write_enable; + + + + + wire [ (32-1):0] extended_immediate; wire [ (32-1):0] high_immediate; wire [ (32-1):0] call_immediate; @@ -11327,6 +45571,7 @@ wire [ (32-1):0] branch_immediate; wire sign_extend_immediate; wire select_high_immediate; wire select_call_immediate; + wire op_add; wire op_and; wire op_andhi; @@ -11346,36 +45591,108 @@ wire op_cmpge; wire op_cmpgeu; wire op_cmpgu; wire op_cmpne; + + + + wire op_lb; wire op_lbu; wire op_lh; wire op_lhu; wire op_lw; + + + + + + wire op_mul; + + wire op_nor; wire op_or; wire op_orhi; wire op_raise; wire op_rcsr; wire op_sb; + + wire op_sextb; wire op_sexth; + + wire op_sh; + + wire op_sl; + + wire op_sr; wire op_sru; wire op_sub; wire op_sw; + + + + wire op_wcsr; wire op_xnor; wire op_xor; + wire arith; wire logical; wire cmp; wire bra; wire call; + + wire shift; + + + + + + + + wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -11383,6 +45700,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -11395,6 +45713,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + assign op_add = instruction[ 30:26] == 5'b01101; assign op_and = instruction[ 30:26] == 5'b01000; assign op_andhi = instruction[ 31:26] == 6'b011000; @@ -11414,29 +45741,55 @@ assign op_cmpge = instruction[ 30:26] == 5'b11011; assign op_cmpgeu = instruction[ 30:26] == 5'b11100; assign op_cmpgu = instruction[ 30:26] == 5'b11101; assign op_cmpne = instruction[ 30:26] == 5'b11111; + + + + assign op_lb = instruction[ 31:26] == 6'b000100; assign op_lbu = instruction[ 31:26] == 6'b010000; assign op_lh = instruction[ 31:26] == 6'b000111; assign op_lhu = instruction[ 31:26] == 6'b001011; assign op_lw = instruction[ 31:26] == 6'b001010; + + + + + + assign op_mul = instruction[ 30:26] == 5'b00010; + + assign op_nor = instruction[ 30:26] == 5'b00001; assign op_or = instruction[ 30:26] == 5'b01110; assign op_orhi = instruction[ 31:26] == 6'b011110; assign op_raise = instruction[ 31:26] == 6'b101011; assign op_rcsr = instruction[ 31:26] == 6'b100100; assign op_sb = instruction[ 31:26] == 6'b001100; + + assign op_sextb = instruction[ 31:26] == 6'b101100; assign op_sexth = instruction[ 31:26] == 6'b110111; + + assign op_sh = instruction[ 31:26] == 6'b000011; + + assign op_sl = instruction[ 30:26] == 5'b01111; + + assign op_sr = instruction[ 30:26] == 5'b00101; assign op_sru = instruction[ 30:26] == 5'b00000; assign op_sub = instruction[ 31:26] == 6'b110010; assign op_sw = instruction[ 31:26] == 6'b010110; + + + + assign op_wcsr = instruction[ 31:26] == 6'b110100; assign op_xnor = instruction[ 30:26] == 5'b01001; assign op_xor = instruction[ 30:26] == 5'b00110; + + assign arith = op_add | op_sub; assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; @@ -11444,12 +45797,41 @@ assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; assign bi_unconditional = op_bi; assign bra = op_b | bi_unconditional | bi_conditional; assign call = op_call | op_calli; + + assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + assign sext = op_sextb | op_sexth; + + + + + + + + + + + assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; assign store = op_sb | op_sh | op_sw; + + always @(*) begin + if (call) d_result_sel_0 = 1'b1; else @@ -11460,70 +45842,605 @@ begin d_result_sel_1 = 2'b10; else d_result_sel_1 = 2'b01; + x_result_sel_csr = 1'b0; + + + + + + + + + + x_result_sel_sext = 1'b0; + + x_result_sel_logic = 1'b0; + + + + x_result_sel_add = 1'b0; if (op_rcsr) x_result_sel_csr = 1'b1; + + + + + + + + + + + + + + + + + + + + + + else if (sext) x_result_sel_sext = 1'b1; + + else if (logical) x_result_sel_logic = 1'b1; + + + + + else x_result_sel_add = 1'b1; + + + m_result_sel_compare = cmp; + + m_result_sel_shift = shift; + + + + w_result_sel_load = load; + + w_result_sel_mul = op_mul; + + end + + assign x_bypass_enable = arith | logical + + + + + + + + + + + + + + + + + + + + | sext + + + + + + | op_rcsr ; + assign m_bypass_enable = x_bypass_enable + + | shift + + | cmp ; + assign read_enable_0 = ~(op_bi | op_calli); assign read_idx_0 = instruction[25:21]; + assign read_enable_1 = ~(op_bi | op_calli | load); assign read_idx_1 = instruction[20:16]; + assign write_enable = ~(bra | op_raise | store | op_wcsr); assign write_idx = call ? 5'd29 : instruction[31] == 1'b0 ? instruction[20:16] : instruction[15:11]; + + assign size = instruction[27:26]; + assign sign_extend = instruction[28]; + assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + assign logic_op = instruction[29:26]; + + + assign direction = instruction[29]; + + + assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + + assign break_opcode = op_raise & ~instruction[2]; + + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + + assign bret = op_b & (instruction[25:21] == 5'd31); + + + + + + + + assign csr_write_enable = op_wcsr; + + + assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); assign select_high_immediate = op_andhi | op_orhi; assign select_call_immediate = instruction[31]; + assign high_immediate = {instruction[15:0], 16'h0000}; assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + assign immediate = select_high_immediate == 1'b1 ? high_immediate : extended_immediate; + assign branch_offset = select_call_immediate == 1'b1 ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); + endmodule -module lm32_icache_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_icache_medium_icache_debug ( + clk_i, rst_i, stall_a, @@ -11534,8 +46451,13 @@ module lm32_icache_medium_debug ( refill_ready, refill_data, iflush, + + + + valid_d, branch_predict_taken_d, + stall_request, restart_request, refill_request, @@ -11543,11 +46465,17 @@ module lm32_icache_medium_debug ( refilling, inst ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + localparam addr_offset_width = clogb2(bytes_per_line)-1-2; localparam addr_set_width = clogb2(sets)-1; localparam addr_offset_lsb = 2; @@ -11557,18 +46485,37 @@ localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); localparam addr_tag_lsb = (addr_set_msb+1); localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; + input valid_d; input branch_predict_taken_d; + input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; input read_enable_f; + input refill_ready; input [ (32-1):0] refill_data; + input iflush; + + + + + + + + + output stall_request; wire stall_request; output restart_request; @@ -11581,6 +46528,11 @@ output refilling; reg refilling; output [ (32-1):0] inst; wire [ (32-1):0] inst; + + + + + wire enable; wire [0:associativity-1] way_mem_we; wire [ (32-1):0] way_data[0:associativity-1]; @@ -11588,20 +46540,59 @@ wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; wire [0:associativity-1] way_valid; wire [0:associativity-1] way_match; wire miss; + wire [ (addr_set_width-1):0] tmem_read_address; wire [ (addr_set_width-1):0] tmem_write_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; wire [ ((addr_tag_width+1)-1):0] tmem_write_data; + reg [ 3:0] state; wire flushing; wire check; wire refill; + reg [associativity-1:0] refill_way_select; reg [ addr_offset_msb:addr_offset_lsb] refill_offset; wire last_refill; reg [ (addr_set_width-1):0] flush_set; + genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -11609,6 +46600,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -11621,16 +46613,28 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : memories + lm32_ram #( + .data_width (32), .address_width ( (addr_offset_width+addr_set_width)) + ) way_0_data_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -11640,15 +46644,20 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i]), .write_data (refill_data), + .read_data (way_data[i]) ); + lm32_ram #( + .data_width ( (addr_tag_width+1)), .address_width ( addr_set_width) + ) way_0_tag_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -11658,16 +46667,26 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i] | flushing), .write_data (tmem_write_data), + .read_data ({way_tag[i], way_valid[i]}) ); + end endgenerate + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : match assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); end endgenerate + + generate if (associativity == 1) begin : inst_1 @@ -11678,24 +46697,35 @@ assign inst = way_match[0] ? way_data[0] : 32'b0; assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); end endgenerate + + generate if (bytes_per_line > 4) assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; else assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; endgenerate + assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; assign tmem_write_address = flushing ? flush_set : refill_address[ addr_set_msb:addr_set_lsb]; + + generate if (bytes_per_line > 4) assign last_refill = refill_offset == {addr_offset_width{1'b1}}; else assign last_refill = 1'b1; endgenerate + + assign enable = (stall_a == 1'b0); + + generate if (associativity == 1) begin : we_1 @@ -11707,14 +46737,25 @@ assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1 assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); end endgenerate + + assign tmem_write_data[ 0] = last_refill & !flushing; assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + assign flushing = |state[1:0]; assign check = state[2]; assign refill = state[3]; + assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); assign stall_request = (check == 1'b0); assign refill_request = (refill == 1'b1); + + + + + + generate if (associativity >= 2) begin : way_select @@ -11730,6 +46771,8 @@ begin end end endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11737,6 +46780,8 @@ begin else refilling <= refill; end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11749,18 +46794,31 @@ begin else begin case (state) + + 4'b0001: begin if (flush_set == { addr_set_width{1'b0}}) state <= 4'b0100; flush_set <= flush_set - 1'b1; end + + 4'b0010: begin if (flush_set == { addr_set_width{1'b0}}) + + + + + + state <= 4'b0100; + flush_set <= flush_set - 1'b1; end + + 4'b0100: begin if (stall_a == 1'b0) @@ -11776,6 +46834,8 @@ begin state <= 4'b1000; end end + + 4'b1000: begin if (refill_ready == 1'b1) @@ -11787,12 +46847,15 @@ begin end end end + endcase end end + generate if (bytes_per_line > 4) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11800,6 +46863,8 @@ begin else begin case (state) + + 4'b0100: begin if (iflush == 1'b1) @@ -11807,18 +46872,1236 @@ begin else if (miss == 1'b1) refill_offset <= {addr_offset_width{1'b0}}; end + + 4'b1000: begin if (refill_ready == 1'b1) refill_offset <= refill_offset + 1'b1; end + endcase end end end endgenerate + endmodule -module lm32_debug_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_debug_medium_icache_debug ( + clk_i, rst_i, pc_x, @@ -11828,23 +48111,51 @@ module lm32_debug_medium_debug ( csr_write_enable_x, csr_write_data, csr_x, + + jtag_csr_write_enable, jtag_csr_write_data, jtag_csr, + + + + eret_q_x, bret_q_x, stall_x, exception_x, q_x, + + + + + + + + + dc_ss, + + dc_re, bp_match, wp_match ); + + + + + parameter breakpoints = 0; parameter watchpoints = 0; + + + + + input clk_i; input rst_i; + input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; input load_x; input store_x; @@ -11852,33 +48163,106 @@ input [ (32-1):0] load_store_address_x; input csr_write_enable_x; input [ (32-1):0] csr_write_data; input [ (5-1):0] csr_x; + + input jtag_csr_write_enable; input [ (32-1):0] jtag_csr_write_data; input [ (5-1):0] jtag_csr; + + + + input eret_q_x; input bret_q_x; input stall_x; input exception_x; input q_x; + + + + + + + + + + + + + output dc_ss; reg dc_ss; + + output dc_re; reg dc_re; output bp_match; wire bp_match; output wp_match; wire wp_match; + + + + + genvar i; + + + reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; reg bp_e[0:breakpoints-1]; wire [0:breakpoints-1]bp_match_n; + reg [ 1:0] wpc_c[0:watchpoints-1]; reg [ (32-1):0] wp[0:watchpoints-1]; wire [0:watchpoints-1]wp_match_n; + wire debug_csr_write_enable; wire [ (32-1):0] debug_csr_write_data; wire [ (5-1):0] debug_csr; + + + + reg [ 2:0] state; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -11886,6 +48270,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -11898,6 +48283,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + generate for (i = 0; i < breakpoints; i = i + 1) begin : bp_comb @@ -11905,11 +48299,22 @@ assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); end endgenerate generate + + if (breakpoints > 0) assign bp_match = (|bp_match_n) || (state == 3'b011); else assign bp_match = state == 3'b011; + + + + + + + endgenerate + + generate for (i = 0; i < watchpoints; i = i + 1) begin : wp_comb @@ -11922,9 +48327,25 @@ assign wp_match = |wp_match_n; else assign wp_match = 1'b0; endgenerate + + + + assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; + + + + + + + + + + + + generate for (i = 0; i < breakpoints; i = i + 1) begin : bp_seq @@ -11946,6 +48367,8 @@ begin end end endgenerate + + generate for (i = 0; i < watchpoints; i = i + 1) begin : wp_seq @@ -11969,6 +48392,8 @@ begin end end endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11979,6 +48404,10 @@ begin dc_re <= debug_csr_write_data[1]; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -11999,6 +48428,7 @@ begin case (state) 3'b001: begin + if ( ( (eret_q_x == 1'b1) || (bret_q_x == 1'b1) ) @@ -12008,11 +48438,19 @@ begin end 3'b010: begin + if ((q_x == 1'b1) && (stall_x == 1'b0)) state <= 3'b011; end 3'b011: begin + + + + + + + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) begin dc_ss <= 1'b0; @@ -12021,15 +48459,406 @@ begin end 3'b100: begin + + + + + + + state <= 3'b000; end endcase end end + + + endmodule -module lm32_instruction_unit_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_medium_icache_debug ( + clk_i, rst_i, + stall_a, stall_f, stall_d, @@ -12040,28 +48869,61 @@ module lm32_instruction_unit_medium_debug ( kill_f, branch_predict_taken_d, branch_predict_address_d, + + + + + exception_m, branch_taken_m, branch_mispredict_taken_m, branch_target_m, + + iflush, + + + + + + + + + + + i_dat_i, i_ack_i, i_err_i, i_rty_i, + + + + jtag_read_enable, jtag_write_enable, jtag_write_data, jtag_address, + + + + pc_f, pc_d, pc_x, pc_m, pc_w, + + icache_stall_request, icache_restart_request, icache_refill_request, icache_refilling, + + + + + i_dat_o, i_adr_o, i_cyc_o, @@ -12071,23 +48933,63 @@ module lm32_instruction_unit_medium_debug ( i_cti_o, i_lock_o, i_bte_o, + + + + + + + + + + jtag_read_data, jtag_access_complete, + + + + + + + + instruction_f, + + instruction_d ); + + + + + parameter eba_reset = 32'h00000000; parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam eba_reset_minus_4 = eba_reset - 4; localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; input stall_d; @@ -12096,21 +48998,55 @@ input stall_m; input valid_f; input valid_d; input kill_f; + input branch_predict_taken_d; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; + + + + + + input exception_m; input branch_taken_m; input branch_mispredict_taken_m; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; + + + input iflush; + + + + + + + + + + + + input [ (32-1):0] i_dat_i; input i_ack_i; input i_err_i; input i_rty_i; + + + + + input jtag_read_enable; input jtag_write_enable; input [ 7:0] jtag_write_data; input [ (32-1):0] jtag_address; + + + + + + + output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; @@ -12121,6 +49057,9 @@ output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + output icache_stall_request; wire icache_stall_request; output icache_restart_request; @@ -12129,34 +49068,87 @@ output icache_refill_request; wire icache_refill_request; output icache_refilling; wire icache_refilling; + + + + + output [ (32-1):0] i_dat_o; + + reg [ (32-1):0] i_dat_o; + + + + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; + + reg [ (4-1):0] i_sel_o; + + + + output i_stb_o; reg i_stb_o; output i_we_o; + + reg i_we_o; + + + + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; output i_lock_o; reg i_lock_o; output [ (2-1):0] i_bte_o; wire [ (2-1):0] i_bte_o; + + + + + output [ 7:0] jtag_read_data; reg [ 7:0] jtag_read_data; output jtag_access_complete; wire jtag_access_complete; + + + + + + + + + + output [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_f; + + output [ (32-1):0] instruction_d; reg [ (32-1):0] instruction_d; + + + + + reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; + + + reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + + + + + wire icache_read_enable_f; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; reg icache_refill_ready; @@ -12166,7 +49158,69 @@ wire [ (3-1):0] first_cycle_type; wire [ (3-1):0] next_cycle_type; wire last_word; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + + + + + + + + + + + + + + + + + + + + + + + + + reg jtag_access; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -12174,6 +49228,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -12186,13 +49241,26 @@ begin clogb2_v1 = i-1; end endfunction -lm32_icache_medium_debug #( + + + + + + + + + + + + +lm32_icache_medium_icache_debug #( .associativity (associativity), .sets (sets), .bytes_per_line (bytes_per_line), .base_address (base_address), .limit (limit) ) icache ( + .clk_i (clk_i), .rst_i (rst_i), .stall_a (stall_a), @@ -12205,6 +49273,7 @@ lm32_icache_medium_debug #( .refill_ready (icache_refill_ready), .refill_data (icache_refill_data), .iflush (iflush), + .stall_request (icache_stall_request), .restart_request (icache_restart_request), .refill_request (icache_refill_request), @@ -12212,27 +49281,125 @@ lm32_icache_medium_debug #( .refilling (icache_refilling), .inst (icache_data_f) ); -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - ; + + + + + + + + + + + assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + + + + + + + + ; + + + + always @(*) begin + + + + + + + if (branch_taken_m == 1'b1) if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) pc_a = pc_x; else pc_a = branch_target_m; + + + + + else if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) pc_a = branch_predict_address_d; else + + if (icache_restart_request == 1'b1) pc_a = restart_address; else + + pc_a = pc_f + 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign instruction_f = icache_data_f; + + + + + + + + + + + + + + + + + + + assign i_bte_o = 2'b00; + + + + + + generate case (bytes_per_line) 4: @@ -12258,6 +49425,14 @@ assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2- end endcase endgenerate + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -12281,16 +49456,59 @@ begin pc_w <= pc_m; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; else begin + + + + + + + + + + + + + + + if (icache_refill_request == 1'b1) restart_address <= icache_refill_address; + + + + end end + + + + + + + + + + + + + + + + + + + + assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); always @(*) begin @@ -12301,113 +49519,687 @@ begin 2'b11: jtag_read_data = i_dat_i[ 7:0]; endcase end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - i_we_o <= 1'b0; - i_sel_o <= 4'b1111; - jtag_access <= 1'b0; - end - else - begin - icache_refill_ready <= 1'b0; - if (i_cyc_o == 1'b1) - begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - if (jtag_access == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_we_o <= 1'b0; - jtag_access <= 1'b0; - end - else - begin - if (last_word == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end - end - end - else - begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) - begin - i_sel_o <= 4'b1111; - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; - end - else - begin - if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) - begin - case (jtag_address[1:0]) - 2'b00: i_sel_o <= 4'b1000; - 2'b01: i_sel_o <= 4'b0100; - 2'b10: i_sel_o <= 4'b0010; - 2'b11: i_sel_o <= 4'b0001; - endcase - i_adr_o <= jtag_address; - i_dat_o <= {4{jtag_write_data}}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_we_o <= jtag_write_enable; - i_cti_o <= 3'b111; - jtag_access <= 1'b1; - end - end - end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) - begin - instruction_d <= instruction_f; - end - end -end + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + + + + + i_we_o <= 1'b0; + i_sel_o <= 4'b1111; + jtag_access <= 1'b0; + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + if (jtag_access == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_we_o <= 1'b0; + jtag_access <= 1'b0; + end + else + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + + + + + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + i_sel_o <= 4'b1111; + + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + + + end + + + else + begin + if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) + begin + case (jtag_address[1:0]) + 2'b00: i_sel_o <= 4'b1000; + 2'b01: i_sel_o <= 4'b0100; + 2'b10: i_sel_o <= 4'b0010; + 2'b11: i_sel_o <= 4'b0001; + endcase + i_adr_o <= jtag_address; + i_dat_o <= {4{jtag_write_data}}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_we_o <= jtag_write_enable; + i_cti_o <= 3'b111; + jtag_access <= 1'b1; + end + end + + + + + + + + + + + + + + end + end + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + endmodule -module lm32_jtag_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_jtag_medium_icache_debug ( + clk_i, rst_i, jtag_clk, jtag_update, jtag_reg_q, jtag_reg_addr_q, + + csr, csr_write_enable, csr_write_data, stall_x, + + + + jtag_read_data, jtag_access_complete, + + + + exception_q_w, + + + + + jtx_csr_read_data, jrx_csr_read_data, + + + + jtag_csr_write_enable, jtag_csr_write_data, jtag_csr, @@ -12415,28 +50207,64 @@ module lm32_jtag_medium_debug ( jtag_write_enable, jtag_write_data, jtag_address, + + + + jtag_break, jtag_reset, + + jtag_reg_d, jtag_reg_addr_d ); + + + + + input clk_i; input rst_i; + input jtag_clk; input jtag_update; input [ 7:0] jtag_reg_q; input [2:0] jtag_reg_addr_q; + + + input [ (5-1):0] csr; input csr_write_enable; input [ (32-1):0] csr_write_data; input stall_x; + + + + input [ 7:0] jtag_read_data; input jtag_access_complete; + + + + input exception_q_w; + + + + + + + + + output [ (32-1):0] jtx_csr_read_data; wire [ (32-1):0] jtx_csr_read_data; output [ (32-1):0] jrx_csr_read_data; wire [ (32-1):0] jrx_csr_read_data; + + + + output jtag_csr_write_enable; reg jtag_csr_write_enable; output [ (32-1):0] jtag_csr_write_data; @@ -12451,42 +50279,103 @@ output [ 7:0] jtag_write_data; wire [ 7:0] jtag_write_data; output [ (32-1):0] jtag_address; wire [ (32-1):0] jtag_address; + + + + output jtag_break; reg jtag_break; output jtag_reset; reg jtag_reset; + + output [ 7:0] jtag_reg_d; reg [ 7:0] jtag_reg_d; output [2:0] jtag_reg_addr_d; wire [2:0] jtag_reg_addr_d; + + + + + reg rx_update; reg rx_update_r; reg rx_update_r_r; reg rx_update_r_r_r; + + + wire [ 7:0] rx_byte; wire [2:0] rx_addr; + + + reg [ 7:0] uart_tx_byte; reg uart_tx_valid; reg [ 7:0] uart_rx_byte; reg uart_rx_valid; + + + reg [ 3:0] command; + + reg [ 7:0] jtag_byte_0; reg [ 7:0] jtag_byte_1; reg [ 7:0] jtag_byte_2; reg [ 7:0] jtag_byte_3; reg [ 7:0] jtag_byte_4; reg processing; + + + reg [ 3:0] state; + + + + + + + assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; assign jtag_csr = jtag_byte_4[ (5-1):0]; assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; assign jtag_write_data = jtag_byte_4; + + + + + + assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; + + + + + + assign jtag_reg_addr_d[2] = processing; + + + + + + + assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; + + + + + + + assign rx_byte = jtag_reg_q; assign rx_addr = jtag_reg_addr_q; + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -12504,6 +50393,8 @@ begin rx_update_r_r_r <= rx_update_r_r; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -12511,48 +50402,76 @@ begin state <= 4'h0; command <= 4'b0000; jtag_reg_d <= 8'h00; + + processing <= 1'b0; jtag_csr_write_enable <= 1'b0; jtag_read_enable <= 1'b0; jtag_write_enable <= 1'b0; + + + + jtag_break <= 1'b0; jtag_reset <= 1'b0; + + + + uart_tx_byte <= 8'h00; uart_tx_valid <= 1'b0; uart_rx_byte <= 8'h00; uart_rx_valid <= 1'b0; + + end else begin + + if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) begin case (csr) 5'he: begin + uart_tx_byte <= csr_write_data[ 7:0]; uart_tx_valid <= 1'b1; end 5'hf: begin + uart_rx_valid <= 1'b0; end endcase end + + + + + if (exception_q_w == 1'b1) begin jtag_break <= 1'b0; jtag_reset <= 1'b0; end + + case (state) 4'h0: begin + if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) begin command <= rx_byte[7:4]; case (rx_addr) + + 3'b000: begin case (rx_byte[7:4]) + + 4'b0001: state <= 4'h1; 4'b0011: @@ -12569,20 +50488,34 @@ begin end 4'b0101: state <= 4'h1; + + 4'b0110: begin + + uart_rx_valid <= 1'b0; uart_tx_valid <= 1'b0; + + jtag_break <= 1'b1; end 4'b0111: begin + + uart_rx_valid <= 1'b0; uart_tx_valid <= 1'b0; + + jtag_reset <= 1'b1; end endcase end + + + + 3'b001: begin uart_rx_byte <= rx_byte; @@ -12593,11 +50526,15 @@ begin jtag_reg_d <= uart_tx_byte; uart_tx_valid <= 1'b0; end + + default: ; endcase end end + + 4'h1: begin if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) @@ -12683,59 +50620,499 @@ begin processing <= 1'b0; state <= 4'h0; end + + endcase end end + endmodule -module lm32_interrupt_medium_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_medium_icache_debug ( + clk_i, rst_i, + interrupt, + stall_x, + + non_debug_exception, debug_exception, + + + + eret_q_x, + + bret_q_x, + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; + + + input non_debug_exception; input debug_exception; + + + + input eret_q_x; + + input bret_q_x; + + + input [ (5-1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; + + reg bie; + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + bie, + + + + eie, ie }; @@ -12747,11 +51124,18 @@ end end else begin + always @(*) begin case (csr) 5'h0: csr_read_data = {{ 32-3{1'b0}}, + + bie, + + + + eie, ie }; @@ -12761,52 +51145,100 @@ begin end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + bie <= 1'b0; + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; + + if (non_debug_exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end else if (debug_exception == 1'b1) begin + bie <= ie; ie <= 1'b0; end + + + + + + + + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + else if (bret_q_x == 1'b1) + ie <= bie; + + else if (csr_write_enable == 1'b1) begin + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + bie <= csr_write_data[2]; + + end if (csr == 5'h1) im <= csr_write_data[interrupts-1:0]; @@ -12819,47 +51251,81 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + bie <= 1'b0; + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; + + if (non_debug_exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end else if (debug_exception == 1'b1) begin + bie <= ie; ie <= 1'b0; end + + + + + + + + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + else if (bret_q_x == 1'b1) + ie <= bie; + + else if (csr_write_enable == 1'b1) begin + if (csr == 5'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + bie <= csr_write_data[2]; + + end if (csr == 5'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; @@ -12869,19 +51335,612 @@ always @(posedge clk_i ) end end endgenerate + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_top_medium_icache ( + clk_i, rst_i, + + interrupt, + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -12891,6 +51950,9 @@ module lm32_top_medium_icache ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -12901,19 +51963,58 @@ module lm32_top_medium_icache ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -12932,6 +52033,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -12950,6 +52054,71 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -12957,6 +52126,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -12969,22 +52139,87 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + lm32_cpu_medium_icache #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), + + + + + + + + + + + + + + + + + + + .I_DAT_I (I_DAT_I), .I_ACK_I (I_ACK_I), .I_ERR_I (I_ERR_I), .I_RTY_I (I_RTY_I), + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + + + + + + + + + + + + + + .I_DAT_O (I_DAT_O), .I_ADR_O (I_ADR_O), .I_CYC_O (I_CYC_O), @@ -12994,6 +52229,9 @@ lm32_cpu_medium_icache .I_CTI_O (I_CTI_O), .I_LOCK_O (I_LOCK_O), .I_BTE_O (I_BTE_O), + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -13004,33 +52242,514 @@ lm32_cpu_medium_icache .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); + + + + + + + + + + + + + + + + + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_mc_arithmetic_medium_icache ( + clk_i, rst_i, stall_d, kill_x, + + + + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + + + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + + + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -13039,11 +52758,23 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + + + case (state) 3'b000: begin @@ -13053,24 +52784,585 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_cpu_medium_icache ( + clk_i, + + + + rst_i, + + + interrupt, + + + + + + + + + + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + + + + + + + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -13080,6 +53372,23 @@ module lm32_cpu_medium_icache ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -13089,33 +53398,165 @@ module lm32_cpu_medium_icache ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; + + + + parameter sdb_address = 32'h00000000; + + + parameter icache_associativity = 1; parameter icache_sets = 256; parameter icache_bytes_per_line = 16; parameter icache_base_address = 32'h0; parameter icache_limit = 32'h7fffffff; + + + + + + + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 512; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 0; parameter dcache_limit = 0; + + + + + + + parameter watchpoints = 0; + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; + + + + + + + + + + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -13134,6 +53575,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -13152,12 +53596,33 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + reg valid_a; + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -13194,27 +53659,56 @@ reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; + + + + + + + + + + + + + wire x_result_sel_sext_d; reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + wire m_result_sel_shift_d; reg m_result_sel_shift_x; reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + wire w_result_sel_mul_d; reg w_result_sel_mul_x; reg w_result_sel_mul_m; reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -13241,100 +53735,380 @@ wire [ (4 -1):0] csr_d; reg [ (4 -1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + + + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; + + + + + + + + + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + + + + + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; + + + + wire [ (32-1):0] sextb_result_x; wire [ (32-1):0] sexth_result_x; wire [ (32-1):0] sext_result_x; + + + + + + + + + + + wire direction_d; reg direction_x; wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; + + wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; + + wire iflush; wire icache_stall_request; wire icache_restart_request; wire icache_refill_request; wire icache_refilling; + + + + + + + + + + + + + wire [ (32-1):0] load_data_w; wire stall_wb_load; + + + + + + + + + + + + + + + + + + + + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; + reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; + + + + reg [ (3-1):0] eid_x; + + + + + + + + + + + + + + + + + + + + + + + + + wire exception_x; reg exception_m; reg exception_w; wire exception_q_w; + + + + + + + + + + + wire interrupt_exception; + + + + + + + + + + + + + + + + wire system_call_exception; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -13342,6 +54116,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -13354,6 +54129,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + lm32_instruction_unit_medium_icache #( .eba_reset (eba_reset), .associativity (icache_associativity), @@ -13362,8 +54146,10 @@ lm32_instruction_unit_medium_icache #( .base_address (icache_base_address), .limit (icache_limit) ) instruction_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_f (stall_f), .stall_d (stall_d), @@ -13374,24 +54160,60 @@ lm32_instruction_unit_medium_icache #( .kill_f (kill_f), .branch_predict_taken_d (branch_predict_taken_d), .branch_predict_address_d (branch_predict_address_d), + + + + + .exception_m (exception_m), .branch_taken_m (branch_taken_m), .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), + + .iflush (iflush), + + + + + + + + + + + .i_dat_i (I_DAT_I), .i_ack_i (I_ACK_I), .i_err_i (I_ERR_I), .i_rty_i (I_RTY_I), + + + + + + + + + + + .pc_f (pc_f), .pc_d (pc_d), .pc_x (pc_x), .pc_m (pc_m), .pc_w (pc_w), + + .icache_stall_request (icache_stall_request), .icache_restart_request (icache_restart_request), .icache_refill_request (icache_refill_request), .icache_refilling (icache_refilling), + + + + + .i_dat_o (I_DAT_O), .i_adr_o (I_ADR_O), .i_cyc_o (I_CYC_O), @@ -13401,21 +54223,77 @@ lm32_instruction_unit_medium_icache #( .i_cti_o (I_CTI_O), .i_lock_o (I_LOCK_O), .i_bte_o (I_BTE_O), + + + + + + + + + + + + + + + + + + + + + .instruction_f (instruction_f), + + + + .instruction_d (instruction_d) + + + ); + + lm32_decoder_medium_icache decoder ( + .instruction (instruction_d), + .d_result_sel_0 (d_result_sel_0_d), .d_result_sel_1 (d_result_sel_1_d), .x_result_sel_csr (x_result_sel_csr_d), + + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + .x_result_sel_logic (x_result_sel_logic_d), + + + + .x_result_sel_add (x_result_sel_add_d), .m_result_sel_compare (m_result_sel_compare_d), + + .m_result_sel_shift (m_result_sel_shift_d), + + .w_result_sel_load (w_result_sel_load_d), + + .w_result_sel_mul (w_result_sel_mul_d), + + .x_bypass_enable (x_bypass_enable_d), .m_bypass_enable (m_bypass_enable_d), .read_enable_0 (read_enable_0_d), @@ -13432,16 +54310,48 @@ lm32_decoder_medium_icache decoder ( .sign_extend (sign_extend_d), .adder_op (adder_op_d), .logic_op (logic_op_d), + + .direction (direction_d), + + + + + + + + + + + + + + + + .branch (branch_d), .bi_unconditional (bi_unconditional), .bi_conditional (bi_conditional), .branch_reg (branch_reg_d), .condition (condition_d), + + + + .scall (scall_d), .eret (eret_d), + + + + + + + + .csr_write_enable (csr_write_enable_d) ); + + lm32_load_store_unit_medium_icache #( .associativity (dcache_associativity), .sets (dcache_sets), @@ -13449,8 +54359,10 @@ lm32_load_store_unit_medium_icache #( .base_address (dcache_base_address), .limit (dcache_limit) ) load_store_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_x (stall_x), .stall_m (stall_m), @@ -13469,12 +54381,39 @@ lm32_load_store_unit_medium_icache #( .store_q_m (store_q_m), .sign_extend_x (sign_extend_x), .size_x (size_x), + + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), .d_ack_i (D_ACK_I), .d_err_i (D_ERR_I), .d_rty_i (D_RTY_I), + + + + + + + + + .load_data_w (load_data_w), .stall_wb_load (stall_wb_load), + .d_dat_o (D_DAT_O), .d_adr_o (D_ADR_O), .d_cyc_o (D_CYC_O), @@ -13485,22 +54424,36 @@ lm32_load_store_unit_medium_icache #( .d_lock_o (D_LOCK_O), .d_bte_o (D_BTE_O) ); + + lm32_adder adder ( + .adder_op_x (adder_op_x), .adder_op_x_n (adder_op_x_n), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .adder_result_x (adder_result_x), .adder_carry_n_x (adder_carry_n_x), .adder_overflow_x (adder_overflow_x) ); + + lm32_logic_op logic_op ( + .logic_op_x (logic_op_x), .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + .logic_result_x (logic_result_x) ); + + + + lm32_shifter shifter ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), @@ -13508,34 +54461,213 @@ lm32_shifter shifter ( .sign_extend_x (sign_extend_x), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .shifter_result_m (shifter_result_m) ); + + + + + + lm32_multiplier multiplier ( + .clk_i (clk_i), .rst_i (rst_i), .stall_x (stall_x), .stall_m (stall_m), .operand_0 (d_result_0), .operand_1 (d_result_1), + .result (multiplier_result_w) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lm32_interrupt_medium_icache interrupt_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .interrupt (interrupt), + .stall_x (stall_x), + + + + + .exception (exception_q_w), + + .eret_q_x (eret_q_x), + + + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), + .interrupt_exception (interrupt_exception), + .csr_read_data (interrupt_csr_read_data_x) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; reg [31:0] w_result_d; reg regfile_raw_0, regfile_raw_0_nxt; reg regfile_raw_1, regfile_raw_1_nxt; + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) begin if (reg_write_enable_q_w @@ -13543,22 +54675,39 @@ lm32_interrupt_medium_icache interrupt_unit ( regfile_raw_0_nxt = 1'b1; else regfile_raw_0_nxt = 1'b0; + if (reg_write_enable_q_w && (write_idx_w == instruction_f[20:16])) regfile_raw_1_nxt = 1'b1; else regfile_raw_1_nxt = 1'b0; end + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) if (regfile_raw_0) reg_data_live_0 = w_result_d; else reg_data_live_0 = regfile_data_0; + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) if (regfile_raw_1) reg_data_live_1 = w_result_d; else reg_data_live_1 = regfile_data_1; + + + + always @(posedge clk_i ) if (rst_i == 1'b1) begin @@ -13572,22 +54721,31 @@ lm32_interrupt_medium_icache interrupt_unit ( regfile_raw_1 <= regfile_raw_1_nxt; w_result_d <= w_result; end + + + + + lm32_dp_ram #( + .addr_depth(1<<5), .addr_width(5), .data_width(32) ) reg_0 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[25:21]), + .rdata_o (regfile_data_0) ); + lm32_dp_ram #( .addr_depth(1<<5), @@ -13596,22 +54754,118 @@ lm32_interrupt_medium_icache interrupt_unit ( ) reg_1 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[20:16]), + .rdata_o (regfile_data_1) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + always @(*) begin if ( ( (x_bypass_enable_x == 1'b0) @@ -13629,6 +54883,8 @@ begin else interlock = 1'b0; end + + always @(*) begin if (raw_x_0 == 1'b1) @@ -13640,6 +54896,8 @@ begin else bypass_data_0 = reg_data_0; end + + always @(*) begin if (raw_x_1 == 1'b1) @@ -13651,10 +54909,25 @@ begin else bypass_data_1 = reg_data_1; end + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + assign branch_target_d = pc_d + branch_offset_d; + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + always @(*) begin d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; @@ -13665,9 +54938,30 @@ begin default: d_result_1 = { 32{1'bx}}; endcase end + + + + + + + + + + + assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + assign cmp_zero = operand_0_x == operand_1_x; assign cmp_negative = adder_result_x[ 32-1]; assign cmp_overflow = adder_overflow_x; @@ -13686,25 +54980,68 @@ begin default: condition_met_x = 1'bx; endcase end + + always @(*) begin x_result = x_result_sel_add_x ? adder_result_x : x_result_sel_csr_x ? csr_read_data_x + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + + : logic_result_x; end + + always @(*) begin m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + : m_result_sel_shift_m ? shifter_result_m + + : operand_m; end + + always @(*) begin w_result = w_result_sel_load_w ? load_data_w + + : w_result_sel_mul_w ? multiplier_result_w + + : operand_w; end + + + + + + + + + + + + + assign branch_taken_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -13719,9 +55056,13 @@ assign branch_taken_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign branch_mispredict_taken_m = (condition_met_m == 1'b0) && (branch_predict_m == 1'b1) && (branch_predict_taken_m == 1'b1); + + assign branch_flushX_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -13734,43 +55075,232 @@ assign branch_flushX_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign kill_f = ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) || (branch_taken_m == 1'b1) + + + + + + || (icache_refill_request == 1'b1) + + + + + + ; assign kill_d = (branch_taken_m == 1'b1) + + + + + + || (icache_refill_request == 1'b1) + + + + + + ; assign kill_x = (branch_flushX_m == 1'b1) + + + + ; assign kill_m = 1'b0 + + + + ; assign kill_w = 1'b0 + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign system_call_exception = ( (scall_x == 1'b1) + + + + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign exception_x = (system_call_exception == 1'b1) + + + + + + + + + + + || ( (interrupt_exception == 1'b1) + + + + + + + + + ) + + ; + + + + always @(*) begin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if ( (interrupt_exception == 1'b1) + + + + ) eid_x = 3'h6; else + + eid_x = 3'h7; end + + + assign stall_a = (stall_f == 1'b1); + assign stall_f = (stall_d == 1'b1); + assign stall_d = (stall_x == 1'b1) || ( (interlock == 1'b1) && (kill_d == 1'b0) ) || ( ( (eret_d == 1'b1) || (scall_d == 1'b1) + + + + ) && ( (load_q_x == 1'b1) || (load_q_m == 1'b1) @@ -13780,83 +55310,343 @@ assign stall_d = (stall_x == 1'b1) ) && (kill_d == 1'b0) ) + + + + + + + + + + + + + + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) ) + + + + + + + + + + ; + assign stall_x = (stall_m == 1'b1) + + + + + + + + ; + assign stall_m = (stall_wb_load == 1'b1) + + + + || ( (D_CYC_O == 1'b1) && ( (store_m == 1'b1) + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + || (load_m == 1'b1) || (load_x == 1'b1) ) ) + + + + + + + + || (icache_stall_request == 1'b1) || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) + + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + + + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + + + + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + + + + ; + + + + assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + + + + assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + assign cfg = { 6'h02, watchpoints[3:0], breakpoints[3:0], interrupts[5:0], + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + 1'b1, + + + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + 1'b1, + + + + + + 1'b1, + + + + + + + + 1'b0, + + + + 1'b1 + + + + }; + assign cfg2 = { 30'b0, + + + + 1'b0, + + + + + + 1'b0 + + }; + + + + assign iflush = ( (csr_write_enable_d == 1'b1) && (csr_d == 4 'h3) && (stall_d == 1'b0) && (kill_d == 1'b0) && (valid_d == 1'b1)) + + + + + + + ; + + + + + + + + + + + + + + + + assign csr_d = read_idx_0_d[ (4 -1):0]; + + always @(*) begin case (csr_x) + + 4 'h0, 4 'h1, 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + 4 'h6: csr_read_data_x = cfg; 4 'h7: csr_read_data_x = {eba, 8'h00}; + + + + + + + + + 4 'ha: csr_read_data_x = cfg2; 4 'hb: csr_read_data_x = sdb_address; + default: csr_read_data_x = { 32{1'bx}}; endcase end + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -13865,8 +55655,84 @@ begin begin if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin if (icache_refill_request == 1'b1) @@ -13876,6 +55742,23 @@ begin else valid_a = !icache_refilling; end + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -13889,48 +55772,88 @@ begin else begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + valid_f <= valid_a; + + + + else if (stall_f == 1'b0) valid_f <= 1'b0; + if (kill_d == 1'b1) valid_d <= 1'b0; else if (stall_f == 1'b0) valid_d <= valid_f & !kill_f; else if (stall_d == 1'b0) valid_d <= 1'b0; + if (stall_d == 1'b0) valid_x <= valid_d & !kill_d; else if (kill_x == 1'b1) valid_x <= 1'b0; else if (stall_x == 1'b0) valid_x <= 1'b0; + if (kill_m == 1'b1) valid_m <= 1'b0; else if (stall_x == 1'b0) valid_m <= valid_x & !kill_x; else if (stall_m == 1'b0) valid_m <= 1'b0; + if (stall_m == 1'b0) valid_w <= valid_m & !kill_m; else valid_w <= 1'b0; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin + + + + operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; x_result_sel_csr_x <= 1'b0; + + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + x_result_sel_add_x <= 1'b0; m_result_sel_compare_x <= 1'b0; + + m_result_sel_shift_x <= 1'b0; + + w_result_sel_load_x <= 1'b0; + + w_result_sel_mul_x <= 1'b0; + + x_bypass_enable_x <= 1'b0; m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; @@ -13943,20 +55866,50 @@ begin adder_op_x <= 1'b0; adder_op_x_n <= 1'b0; logic_op_x <= 4'h0; + + direction_x <= 1'b0; + + + + + + + branch_x <= 1'b0; branch_predict_x <= 1'b0; branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + + + + scall_x <= 1'b0; eret_x <= 1'b0; + + + + + + + + + csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; m_result_sel_compare_m <= 1'b0; + + m_result_sel_shift_m <= 1'b0; + + w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + m_bypass_enable_m <= 1'b0; branch_m <= 1'b0; branch_predict_m <= 1'b0; @@ -13967,28 +55920,82 @@ begin write_enable_m <= 1'b0; write_idx_m <= { 5{1'b0}}; condition_met_m <= 1'b0; + + + + + + + + + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; + + w_result_sel_mul_w <= 1'b0; + + write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; + + + + + exception_w <= 1'b0; + + + + + + end else begin + + if (stall_x == 1'b0) begin + + + + operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; + + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + x_result_sel_add_x <= x_result_sel_add_d; m_result_sel_compare_x <= m_result_sel_compare_d; + + m_result_sel_shift_x <= m_result_sel_shift_d; + + w_result_sel_load_x <= w_result_sel_load_d; + + w_result_sel_mul_x <= w_result_sel_mul_d; + + x_bypass_enable_x <= x_bypass_enable_d; m_bypass_enable_x <= m_bypass_enable_d; load_x <= load_d; @@ -14003,57 +56010,199 @@ begin adder_op_x <= adder_op_d; adder_op_x_n <= ~adder_op_d; logic_op_x <= logic_op_d; + + direction_x <= direction_d; + + + + + + condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + + + + scall_x <= scall_d; + + + + eret_x <= eret_d; + + + + write_enable_x <= write_enable_d; end + + + if (stall_m == 1'b0) begin operand_m <= x_result; m_result_sel_compare_m <= m_result_sel_compare_x; + + m_result_sel_shift_m <= m_result_sel_shift_x; + + if (exception_x == 1'b1) begin w_result_sel_load_m <= 1'b0; + + w_result_sel_mul_m <= 1'b0; + + end else begin w_result_sel_load_m <= w_result_sel_load_x; + + w_result_sel_mul_m <= w_result_sel_mul_x; + + end m_bypass_enable_m <= m_bypass_enable_x; load_m <= load_x; store_m <= store_x; + + + + branch_m <= branch_x; branch_predict_m <= branch_predict_x; branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + + + + + + + + if (exception_x == 1'b1) write_idx_m <= 5'd30; else write_idx_m <= write_idx_x; + + condition_met_m <= condition_met_x; + + + + + + + + + + + + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + + + end + + if (stall_m == 1'b0) begin if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) exception_m <= 1'b1; else exception_m <= 1'b0; + + + + + + + + end + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + w_result_sel_load_w <= w_result_sel_load_m; + + w_result_sel_mul_w <= w_result_sel_mul_m; + + write_idx_w <= write_idx_m; + + + + + + + + write_enable_w <= write_enable_m; + + + + + exception_w <= exception_m; + + + + + + + + + + + end end + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14081,13 +56230,521 @@ begin end end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + initial begin + + + + + + end + + + endmodule -module lm32_load_store_unit_medium_icache ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_medium_icache +( + clk_i, + + + + rst_i, + stall_a, stall_x, stall_m, @@ -14106,12 +56763,37 @@ module lm32_load_store_unit_medium_icache ( store_q_m, sign_extend_x, size_x, + + + + + d_dat_i, d_ack_i, d_err_i, d_rty_i, + + + + + + + + + + + + + + + + + + + load_data_w, stall_wb_load, + d_dat_o, d_adr_o, d_cyc_o, @@ -14122,22 +56804,37 @@ module lm32_load_store_unit_medium_icache ( d_lock_o, d_bte_o ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; + + + + + + input clk_i; + input rst_i; + input stall_a; input stall_x; input stall_m; input kill_x; input kill_m; input exception_m; + input [ (32-1):0] store_operand_x; input [ (32-1):0] load_store_address_x; input [ (32-1):0] load_store_address_m; @@ -14150,14 +56847,57 @@ input load_q_m; input store_q_m; input sign_extend_x; input [ 1:0] size_x; + + + + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + input [ (32-1):0] d_dat_i; input d_ack_i; input d_err_i; input d_rty_i; + + + + + + + + + + + + + + + + + + output [ (32-1):0] load_data_w; reg [ (32-1):0] load_data_w; output stall_wb_load; reg stall_wb_load; + output [ (32-1):0] d_dat_o; reg [ (32-1):0] d_dat_o; output [ (32-1):0] d_adr_o; @@ -14176,6 +56916,12 @@ output d_lock_o; reg d_lock_o; output [ (2-1):0] d_bte_o; wire [ (2-1):0] d_bte_o; + + + + + + reg [ 1:0] size_m; reg [ 1:0] size_w; reg sign_extend_m; @@ -14186,10 +56932,113 @@ reg [ (4-1):0] byte_enable_x; reg [ (4-1):0] byte_enable_m; wire [ (32-1):0] data_m; reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + wire wb_select_x; + + + + + + + + + + reg wb_select_m; reg [ (32-1):0] wb_data_m; reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -14197,6 +57046,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -14209,8 +57059,116 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + + ; + + always @(*) begin case (size_x) @@ -14220,6 +57178,8 @@ begin default: store_data_x = { 32{1'bx}}; endcase end + + always @(*) begin casez ({size_x, load_store_address_x[1:0]}) @@ -14233,7 +57193,90 @@ begin default: byte_enable_x = 4'bxxxx; endcase end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_data_m; + + + + + + + + always @(*) begin casez ({size_w, load_store_address_w[1:0]}) @@ -14247,7 +57290,45 @@ begin default: load_data_w = { 32{1'bx}}; endcase end + + assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14263,30 +57344,85 @@ begin wb_data_m <= { 32{1'b0}}; wb_load_complete <= 1'b0; stall_wb_load <= 1'b0; + + + + end else begin + + + + + + if (d_cyc_o == 1'b1) begin + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) begin + + + + + + + + + begin + d_cyc_o <= 1'b0; d_stb_o <= 1'b0; d_lock_o <= 1'b0; end + + + + + + + wb_data_m <= d_dat_i; + wb_load_complete <= !d_we_o; end + if (d_err_i == 1'b1) $display ("Data bus error. Address: %x", d_adr_o); + end else begin + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) && (stall_m == 1'b0) + + + + + + + + ) begin + d_dat_o <= store_data_m; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -14298,8 +57434,10 @@ begin else if ( (load_q_m == 1'b1) && (wb_select_m == 1'b1) && (wb_load_complete == 1'b0) + ) begin + stall_wb_load <= 1'b0; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -14309,14 +57447,21 @@ begin d_cti_o <= 3'b111; end end + if (stall_m == 1'b0) wb_load_complete <= 1'b0; + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) stall_wb_load <= 1'b1; + if ((kill_m == 1'b1) || (exception_m == 1'b1)) stall_wb_load <= 1'b0; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14325,6 +57470,19 @@ begin size_m <= 2'b00; byte_enable_m <= 1'b0; store_data_m <= { 32{1'b0}}; + + + + + + + + + + + + + wb_select_m <= 1'b0; end else @@ -14335,10 +57493,25 @@ begin size_m <= size_x; byte_enable_m <= byte_enable_x; store_data_m <= store_data_x; + + + + + + + + + + + + + wb_select_m <= wb_select_x; end end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14350,10 +57523,24 @@ begin else begin size_w <= size_m; + + + + + data_w <= data_m; + sign_extend_w <= sign_extend_m; end end + + + + + + + + always @(posedge clk_i) begin if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) @@ -14364,19 +57551,510 @@ begin $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end end + + + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_decoder_medium_icache ( + instruction, + d_result_sel_0, d_result_sel_1, x_result_sel_csr, + + + + + + + + + + x_result_sel_sext, + + x_result_sel_logic, + + + + x_result_sel_add, m_result_sel_compare, + + m_result_sel_shift, + + w_result_sel_load, + + w_result_sel_mul, + + x_bypass_enable, m_bypass_enable, read_enable_0, @@ -14393,37 +58071,104 @@ module lm32_decoder_medium_icache ( sign_extend, adder_op, logic_op, + + direction, + + + + + + + + + + + + + + + + branch, branch_reg, condition, bi_conditional, bi_unconditional, + + + + scall, eret, + + + + + + + + csr_write_enable ); + + + + + input [ (32-1):0] instruction; + + + + + output [ 0:0] d_result_sel_0; reg [ 0:0] d_result_sel_0; output [ 1:0] d_result_sel_1; reg [ 1:0] d_result_sel_1; output x_result_sel_csr; reg x_result_sel_csr; + + + + + + + + + + + + output x_result_sel_sext; reg x_result_sel_sext; + + output x_result_sel_logic; reg x_result_sel_logic; + + + + + output x_result_sel_add; reg x_result_sel_add; output m_result_sel_compare; reg m_result_sel_compare; + + output m_result_sel_shift; reg m_result_sel_shift; + + output w_result_sel_load; reg w_result_sel_load; + + output w_result_sel_mul; reg w_result_sel_mul; + + output x_bypass_enable; wire x_bypass_enable; output m_bypass_enable; @@ -14456,8 +58201,31 @@ output adder_op; wire adder_op; output [ 3:0] logic_op; wire [ 3:0] logic_op; + + output direction; wire direction; + + + + + + + + + + + + + + + + + + + + + output branch; wire branch; output branch_reg; @@ -14468,12 +58236,32 @@ output bi_conditional; wire bi_conditional; output bi_unconditional; wire bi_unconditional; + + + + + output scall; wire scall; output eret; wire eret; + + + + + + + + + + output csr_write_enable; wire csr_write_enable; + + + + + wire [ (32-1):0] extended_immediate; wire [ (32-1):0] high_immediate; wire [ (32-1):0] call_immediate; @@ -14481,6 +58269,7 @@ wire [ (32-1):0] branch_immediate; wire sign_extend_immediate; wire select_high_immediate; wire select_call_immediate; + wire op_add; wire op_and; wire op_andhi; @@ -14500,36 +58289,108 @@ wire op_cmpge; wire op_cmpgeu; wire op_cmpgu; wire op_cmpne; + + + + wire op_lb; wire op_lbu; wire op_lh; wire op_lhu; wire op_lw; + + + + + + wire op_mul; + + wire op_nor; wire op_or; wire op_orhi; wire op_raise; wire op_rcsr; wire op_sb; + + wire op_sextb; wire op_sexth; + + wire op_sh; + + wire op_sl; + + wire op_sr; wire op_sru; wire op_sub; wire op_sw; + + + + wire op_wcsr; wire op_xnor; wire op_xor; + wire arith; wire logical; wire cmp; wire bra; wire call; + + wire shift; + + + + + + + + wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -14537,6 +58398,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -14549,6 +58411,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + assign op_add = instruction[ 30:26] == 5'b01101; assign op_and = instruction[ 30:26] == 5'b01000; assign op_andhi = instruction[ 31:26] == 6'b011000; @@ -14568,29 +58439,55 @@ assign op_cmpge = instruction[ 30:26] == 5'b11011; assign op_cmpgeu = instruction[ 30:26] == 5'b11100; assign op_cmpgu = instruction[ 30:26] == 5'b11101; assign op_cmpne = instruction[ 30:26] == 5'b11111; + + + + assign op_lb = instruction[ 31:26] == 6'b000100; assign op_lbu = instruction[ 31:26] == 6'b010000; assign op_lh = instruction[ 31:26] == 6'b000111; assign op_lhu = instruction[ 31:26] == 6'b001011; assign op_lw = instruction[ 31:26] == 6'b001010; + + + + + + assign op_mul = instruction[ 30:26] == 5'b00010; + + assign op_nor = instruction[ 30:26] == 5'b00001; assign op_or = instruction[ 30:26] == 5'b01110; assign op_orhi = instruction[ 31:26] == 6'b011110; assign op_raise = instruction[ 31:26] == 6'b101011; assign op_rcsr = instruction[ 31:26] == 6'b100100; assign op_sb = instruction[ 31:26] == 6'b001100; + + assign op_sextb = instruction[ 31:26] == 6'b101100; assign op_sexth = instruction[ 31:26] == 6'b110111; + + assign op_sh = instruction[ 31:26] == 6'b000011; + + assign op_sl = instruction[ 30:26] == 5'b01111; + + assign op_sr = instruction[ 30:26] == 5'b00101; assign op_sru = instruction[ 30:26] == 5'b00000; assign op_sub = instruction[ 31:26] == 6'b110010; assign op_sw = instruction[ 31:26] == 6'b010110; + + + + assign op_wcsr = instruction[ 31:26] == 6'b110100; assign op_xnor = instruction[ 30:26] == 5'b01001; assign op_xor = instruction[ 30:26] == 5'b00110; + + assign arith = op_add | op_sub; assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; @@ -14598,12 +58495,41 @@ assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; assign bi_unconditional = op_bi; assign bra = op_b | bi_unconditional | bi_conditional; assign call = op_call | op_calli; + + assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + assign sext = op_sextb | op_sexth; + + + + + + + + + + + assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; assign store = op_sb | op_sh | op_sw; + + always @(*) begin + if (call) d_result_sel_0 = 1'b1; else @@ -14614,68 +58540,603 @@ begin d_result_sel_1 = 2'b10; else d_result_sel_1 = 2'b01; + x_result_sel_csr = 1'b0; + + + + + + + + + + x_result_sel_sext = 1'b0; + + x_result_sel_logic = 1'b0; + + + + x_result_sel_add = 1'b0; if (op_rcsr) x_result_sel_csr = 1'b1; + + + + + + + + + + + + + + + + + + + + + + else if (sext) x_result_sel_sext = 1'b1; + + else if (logical) x_result_sel_logic = 1'b1; + + + + + else x_result_sel_add = 1'b1; + + + m_result_sel_compare = cmp; + + m_result_sel_shift = shift; + + + + w_result_sel_load = load; + + w_result_sel_mul = op_mul; + + end + + assign x_bypass_enable = arith | logical + + + + + + + + + + + + + + + + + + + + | sext + + + + + + | op_rcsr ; + assign m_bypass_enable = x_bypass_enable + + | shift + + | cmp ; + assign read_enable_0 = ~(op_bi | op_calli); assign read_idx_0 = instruction[25:21]; + assign read_enable_1 = ~(op_bi | op_calli | load); assign read_idx_1 = instruction[20:16]; + assign write_enable = ~(bra | op_raise | store | op_wcsr); assign write_idx = call ? 5'd29 : instruction[31] == 1'b0 ? instruction[20:16] : instruction[15:11]; + + assign size = instruction[27:26]; + assign sign_extend = instruction[28]; + assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + assign logic_op = instruction[29:26]; + + + assign direction = instruction[29]; + + + assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + + + + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + + + + + + + + + + assign csr_write_enable = op_wcsr; + + + assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); assign select_high_immediate = op_andhi | op_orhi; assign select_call_immediate = instruction[31]; + assign high_immediate = {instruction[15:0], 16'h0000}; assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + assign immediate = select_high_immediate == 1'b1 ? high_immediate : extended_immediate; + assign branch_offset = select_call_immediate == 1'b1 ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_icache_medium_icache ( + clk_i, rst_i, stall_a, @@ -14686,8 +59147,13 @@ module lm32_icache_medium_icache ( refill_ready, refill_data, iflush, + + + + valid_d, branch_predict_taken_d, + stall_request, restart_request, refill_request, @@ -14695,11 +59161,17 @@ module lm32_icache_medium_icache ( refilling, inst ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + localparam addr_offset_width = clogb2(bytes_per_line)-1-2; localparam addr_set_width = clogb2(sets)-1; localparam addr_offset_lsb = 2; @@ -14709,18 +59181,37 @@ localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); localparam addr_tag_lsb = (addr_set_msb+1); localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; + input valid_d; input branch_predict_taken_d; + input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; input read_enable_f; + input refill_ready; input [ (32-1):0] refill_data; + input iflush; + + + + + + + + + output stall_request; wire stall_request; output restart_request; @@ -14733,6 +59224,11 @@ output refilling; reg refilling; output [ (32-1):0] inst; wire [ (32-1):0] inst; + + + + + wire enable; wire [0:associativity-1] way_mem_we; wire [ (32-1):0] way_data[0:associativity-1]; @@ -14740,20 +59236,59 @@ wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; wire [0:associativity-1] way_valid; wire [0:associativity-1] way_match; wire miss; + wire [ (addr_set_width-1):0] tmem_read_address; wire [ (addr_set_width-1):0] tmem_write_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; wire [ ((addr_tag_width+1)-1):0] tmem_write_data; + reg [ 3:0] state; wire flushing; wire check; wire refill; + reg [associativity-1:0] refill_way_select; reg [ addr_offset_msb:addr_offset_lsb] refill_offset; wire last_refill; reg [ (addr_set_width-1):0] flush_set; + genvar i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -14761,6 +59296,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -14773,16 +59309,28 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : memories + lm32_ram #( + .data_width (32), .address_width ( (addr_offset_width+addr_set_width)) + ) way_0_data_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -14792,15 +59340,20 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i]), .write_data (refill_data), + .read_data (way_data[i]) ); + lm32_ram #( + .data_width ( (addr_tag_width+1)), .address_width ( addr_set_width) + ) way_0_tag_ram ( + .read_clk (clk_i), .write_clk (clk_i), .reset (rst_i), @@ -14810,16 +59363,26 @@ endfunction .enable_write ( 1'b1), .write_enable (way_mem_we[i] | flushing), .write_data (tmem_write_data), + .read_data ({way_tag[i], way_valid[i]}) ); + end endgenerate + + + + + + generate for (i = 0; i < associativity; i = i + 1) begin : match assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); end endgenerate + + generate if (associativity == 1) begin : inst_1 @@ -14830,24 +59393,35 @@ assign inst = way_match[0] ? way_data[0] : 32'b0; assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); end endgenerate + + generate if (bytes_per_line > 4) assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; else assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; endgenerate + assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; + + assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; assign tmem_write_address = flushing ? flush_set : refill_address[ addr_set_msb:addr_set_lsb]; + + generate if (bytes_per_line > 4) assign last_refill = refill_offset == {addr_offset_width{1'b1}}; else assign last_refill = 1'b1; endgenerate + + assign enable = (stall_a == 1'b0); + + generate if (associativity == 1) begin : we_1 @@ -14859,14 +59433,25 @@ assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1 assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); end endgenerate + + assign tmem_write_data[ 0] = last_refill & !flushing; assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; + + assign flushing = |state[1:0]; assign check = state[2]; assign refill = state[3]; + assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); assign stall_request = (check == 1'b0); assign refill_request = (refill == 1'b1); + + + + + + generate if (associativity >= 2) begin : way_select @@ -14882,6 +59467,8 @@ begin end end endgenerate + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14889,6 +59476,8 @@ begin else refilling <= refill; end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14901,18 +59490,31 @@ begin else begin case (state) + + 4'b0001: begin if (flush_set == { addr_set_width{1'b0}}) state <= 4'b0100; flush_set <= flush_set - 1'b1; end + + 4'b0010: begin if (flush_set == { addr_set_width{1'b0}}) + + + + + + state <= 4'b0100; + flush_set <= flush_set - 1'b1; end + + 4'b0100: begin if (stall_a == 1'b0) @@ -14928,6 +59530,8 @@ begin state <= 4'b1000; end end + + 4'b1000: begin if (refill_ready == 1'b1) @@ -14939,12 +59543,15 @@ begin end end end + endcase end end + generate if (bytes_per_line > 4) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -14952,6 +59559,8 @@ begin else begin case (state) + + 4'b0100: begin if (iflush == 1'b1) @@ -14959,20 +59568,1910 @@ begin else if (miss == 1'b1) refill_offset <= {addr_offset_width{1'b0}}; end + + 4'b1000: begin if (refill_ready == 1'b1) refill_offset <= refill_offset + 1'b1; end + endcase end end end endgenerate + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_instruction_unit_medium_icache ( + clk_i, rst_i, + stall_a, stall_f, stall_d, @@ -14983,24 +61482,60 @@ module lm32_instruction_unit_medium_icache ( kill_f, branch_predict_taken_d, branch_predict_address_d, + + + + + exception_m, branch_taken_m, branch_mispredict_taken_m, branch_target_m, + + iflush, + + + + + + + + + + + i_dat_i, i_ack_i, i_err_i, i_rty_i, + + + + + + + + + + + pc_f, pc_d, pc_x, pc_m, pc_w, + + icache_stall_request, icache_restart_request, icache_refill_request, icache_refilling, + + + + + i_dat_o, i_adr_o, i_cyc_o, @@ -15010,21 +61545,62 @@ module lm32_instruction_unit_medium_icache ( i_cti_o, i_lock_o, i_bte_o, + + + + + + + + + + + + + + + + + + + instruction_f, + + instruction_d ); + + + + + parameter eba_reset = 32'h00000000; parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam eba_reset_minus_4 = eba_reset - 4; localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + input clk_i; input rst_i; + input stall_a; input stall_f; input stall_d; @@ -15033,17 +61609,54 @@ input stall_m; input valid_f; input valid_d; input kill_f; + input branch_predict_taken_d; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; + + + + + + input exception_m; input branch_taken_m; input branch_mispredict_taken_m; input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; + + + input iflush; + + + + + + + + + + + + input [ (32-1):0] i_dat_i; input i_ack_i; input i_err_i; input i_rty_i; + + + + + + + + + + + + + + + output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; @@ -15054,6 +61667,9 @@ output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + + output icache_stall_request; wire icache_stall_request; output icache_restart_request; @@ -15062,30 +61678,86 @@ output icache_refill_request; wire icache_refill_request; output icache_refilling; wire icache_refilling; + + + + + output [ (32-1):0] i_dat_o; + + + + wire [ (32-1):0] i_dat_o; + + output [ (32-1):0] i_adr_o; reg [ (32-1):0] i_adr_o; output i_cyc_o; reg i_cyc_o; output [ (4-1):0] i_sel_o; + + + + wire [ (4-1):0] i_sel_o; + + output i_stb_o; reg i_stb_o; output i_we_o; + + + + wire i_we_o; + + output [ (3-1):0] i_cti_o; reg [ (3-1):0] i_cti_o; output i_lock_o; reg i_lock_o; output [ (2-1):0] i_bte_o; wire [ (2-1):0] i_bte_o; + + + + + + + + + + + + + + + + + + output [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_f; + + output [ (32-1):0] instruction_d; reg [ (32-1):0] instruction_d; + + + + + reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; + + + reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; + + + + + wire icache_read_enable_f; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; reg icache_refill_ready; @@ -15095,6 +61767,68 @@ wire [ (3-1):0] first_cycle_type; wire [ (3-1):0] next_cycle_type; wire last_word; wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -15102,6 +61836,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -15114,6 +61849,18 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + lm32_icache_medium_icache #( .associativity (associativity), .sets (sets), @@ -15121,6 +61868,7 @@ lm32_icache_medium_icache #( .base_address (base_address), .limit (limit) ) icache ( + .clk_i (clk_i), .rst_i (rst_i), .stall_a (stall_a), @@ -15133,6 +61881,7 @@ lm32_icache_medium_icache #( .refill_ready (icache_refill_ready), .refill_data (icache_refill_data), .iflush (iflush), + .stall_request (icache_stall_request), .restart_request (icache_restart_request), .refill_request (icache_refill_request), @@ -15140,30 +61889,125 @@ lm32_icache_medium_icache #( .refilling (icache_refilling), .inst (icache_data_f) ); -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - ; + + + + + + + + + + + assign icache_read_enable_f = (valid_f == 1'b1) + && (kill_f == 1'b0) + + + + + + + + + ; + + + + always @(*) begin + + + + + + + if (branch_taken_m == 1'b1) if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) pc_a = pc_x; else pc_a = branch_target_m; + + + + + else if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) pc_a = branch_predict_address_d; else + + if (icache_restart_request == 1'b1) pc_a = restart_address; else + + pc_a = pc_f + 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign instruction_f = icache_data_f; + + + + + + + + + + + + + + assign i_dat_o = 32'd0; assign i_we_o = 1'b0; assign i_sel_o = 4'b1111; + + assign i_bte_o = 2'b00; + + + + + + generate case (bytes_per_line) 4: @@ -15189,6 +62033,14 @@ assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2- end endcase endgenerate + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -15212,120 +62064,1575 @@ begin pc_w <= pc_m; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; else begin + + + + + + + + + + + + + + + if (icache_refill_request == 1'b1) restart_address <= icache_refill_address; + + + + end end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - end - else - begin - icache_refill_ready <= 1'b0; - if (i_cyc_o == 1'b1) - begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - begin - if (last_word == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end - end - end - else - begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) - begin - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; - end - end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) - begin - instruction_d <= instruction_f; - end - end -end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + icache_refill_data <= { 32{1'b0}}; + icache_refill_ready <= 1'b0; + + + + + + + + + + + end + else + begin + icache_refill_ready <= 1'b0; + + if (i_cyc_o == 1'b1) + begin + + if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + + + + + + + + + + + begin + if (last_word == 1'b1) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_lock_o <= 1'b0; + end + + i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; + i_cti_o <= next_cycle_type; + + icache_refill_ready <= 1'b1; + icache_refill_data <= i_dat_i; + end + end + + + + + + + + + end + else + begin + if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) + begin + + + + + + i_adr_o <= {first_address, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + i_cti_o <= first_cycle_type; + + + + + + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end + end + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + module lm32_interrupt_medium_icache ( + clk_i, rst_i, + interrupt, + stall_x, + + + + + exception, + + eret_q_x, + + + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; + + + + + + input exception; + + input eret_q_x; + + + + + input [ (4 -1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; + + + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + 1'b0, + + eie, ie }; @@ -15337,11 +63644,18 @@ end end else begin + always @(*) begin case (csr) 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + 1'b0, + + eie, ie }; @@ -15351,43 +63665,97 @@ begin end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + + + + + else if (csr_write_enable == 1'b1) begin + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + + end if (csr == 4 'h1) im <= csr_write_data[interrupts-1:0]; @@ -15400,38 +63768,78 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + + + else if (csr_write_enable == 1'b1) begin + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + + end if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; @@ -15441,19 +63849,612 @@ always @(posedge clk_i ) end end endgenerate + endmodule -module lm32_top_medium_icache_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_medium ( + clk_i, rst_i, + + interrupt, + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -15463,6 +64464,9 @@ module lm32_top_medium_icache_debug ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -15473,19 +64477,58 @@ module lm32_top_medium_icache_debug ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -15504,6 +64547,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -15522,13 +64568,71 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; -wire [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_q; -wire jtag_update; -wire [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_q; -wire jtck; -wire jrstn; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -15536,6 +64640,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -15548,28 +64653,87 @@ begin clogb2_v1 = i-1; end endfunction -lm32_cpu_medium_icache_debug + + + + + + + + +lm32_cpu_medium #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), - .jtag_clk (jtck), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), + + + + + + + + + + + + + + + + + + + .I_DAT_I (I_DAT_I), .I_ACK_I (I_ACK_I), .I_ERR_I (I_ERR_I), .I_RTY_I (I_RTY_I), + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d), + + + + + + + + + + + + + + + + + + + + + + + + + + + .I_DAT_O (I_DAT_O), .I_ADR_O (I_ADR_O), .I_CYC_O (I_CYC_O), @@ -15579,6 +64743,9 @@ lm32_cpu_medium_icache_debug .I_CTI_O (I_CTI_O), .I_LOCK_O (I_LOCK_O), .I_BTE_O (I_BTE_O), + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -15589,42 +64756,514 @@ lm32_cpu_medium_icache_debug .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); -jtag_cores jtag_cores ( - .reg_d (jtag_reg_d), - .reg_addr_d (jtag_reg_addr_d), - .reg_update (jtag_update), - .reg_q (jtag_reg_q), - .reg_addr_q (jtag_reg_addr_q), - .jtck (jtck), - .jrstn (jrstn) - ); + + + + + + + + + + + + + + + + + endmodule -module lm32_mc_arithmetic_medium_icache_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_medium ( + clk_i, rst_i, stall_d, kill_x, + + + + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + + + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + + + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -15633,11 +65272,23 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + + + case (state) 3'b000: begin @@ -15647,30 +65298,585 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule -module lm32_cpu_medium_icache_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_medium ( + clk_i, + + + + rst_i, + + + interrupt, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, + + + + + + + + + + + + + + + + + + + I_DAT_I, I_ACK_I, I_ERR_I, I_RTY_I, + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, - jtag_reg_d, - jtag_reg_addr_d, + + + + + + + + + + + + + + + + + + + + + + + + + + + I_DAT_O, I_ADR_O, I_CYC_O, @@ -15680,6 +65886,23 @@ module lm32_cpu_medium_icache_debug ( I_CTI_O, I_LOCK_O, I_BTE_O, + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -15689,42 +65912,165 @@ module lm32_cpu_medium_icache_debug ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; -parameter deba_reset = 32'h10000000; + + + + parameter sdb_address = 32'h00000000; -parameter icache_associativity = 1; -parameter icache_sets = 256; -parameter icache_bytes_per_line = 16; -parameter icache_base_address = 32'h0; -parameter icache_limit = 32'h7fffffff; + + + + + + + + + +parameter icache_associativity = 1; +parameter icache_sets = 512; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 0; +parameter icache_limit = 0; + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 512; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 0; parameter dcache_limit = 0; -parameter watchpoints = 32'h4; + + + + + + + +parameter watchpoints = 0; + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; + + + + + + + + + + + + + + + + + + + input [ (32-1):0] I_DAT_I; input I_ACK_I; input I_ERR_I; input I_RTY_I; + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; -output [ 7:0] jtag_reg_d; -wire [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ (32-1):0] I_DAT_O; wire [ (32-1):0] I_DAT_O; output [ (32-1):0] I_ADR_O; @@ -15743,6 +66089,9 @@ output I_LOCK_O; wire I_LOCK_O; output [ (2-1):0] I_BTE_O; wire [ (2-1):0] I_BTE_O; + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -15761,12 +66110,32 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; -reg valid_a; + + + + + + + + + + + + + + + + + + + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -15785,8 +66154,8 @@ reg [ 1:0] size_x; wire branch_d; wire branch_predict_d; wire branch_predict_taken_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_d; +wire [ ((32-2)+2-1):2] branch_predict_address_d; +wire [ ((32-2)+2-1):2] branch_target_d; wire bi_unconditional; wire bi_conditional; reg branch_x; @@ -15798,32 +66167,61 @@ reg branch_predict_taken_m; wire branch_mispredict_taken_m; wire branch_flushX_m; wire branch_reg_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; +wire [ ((32-2)+2-1):2] branch_offset_d; +reg [ ((32-2)+2-1):2] branch_target_x; +reg [ ((32-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; + + + + + + + + + + + + + wire x_result_sel_sext_d; reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + wire m_result_sel_shift_d; reg m_result_sel_shift_x; reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + wire w_result_sel_mul_d; reg w_result_sel_mul_x; reg w_result_sel_mul_m; reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -15846,1133 +66244,12793 @@ wire [ (5-1):0] write_idx_d; reg [ (5-1):0] write_idx_x; reg [ (5-1):0] write_idx_m; reg [ (5-1):0] write_idx_w; -wire [ (5-1):0] csr_d; -reg [ (5-1):0] csr_x; +wire [ (4 -1):0] csr_d; +reg [ (4 -1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; -wire break_d; -reg break_x; + + + + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; -wire bret_d; -reg bret_x; -wire bret_q_x; + + + + + + + + + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + + + + + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; + + + + wire [ (32-1):0] sextb_result_x; wire [ (32-1):0] sexth_result_x; wire [ (32-1):0] sext_result_x; + + + + + + + + + + + wire direction_d; reg direction_x; wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; + + +wire [ ((32-2)+2-1):2] pc_f; +wire [ ((32-2)+2-1):2] pc_d; +wire [ ((32-2)+2-1):2] pc_x; +wire [ ((32-2)+2-1):2] pc_m; +wire [ ((32-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; -wire iflush; -wire icache_stall_request; -wire icache_restart_request; -wire icache_refill_request; -wire icache_refilling; + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] load_data_w; wire stall_wb_load; -wire [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; -wire jtag_csr_write_enable; -wire [ (32-1):0] jtag_csr_write_data; -wire [ (5-1):0] jtag_csr; -wire jtag_read_enable; -wire [ 7:0] jtag_read_data; -wire jtag_write_enable; -wire [ 7:0] jtag_write_data; -wire [ (32-1):0] jtag_address; -wire jtag_access_complete; -wire jtag_break; + + + + + + + + + + + + + + + + + + + + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] eba; -reg [ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8] deba; -reg [ (3-1):0] eid_x; -wire dc_ss; -wire dc_re; -wire bp_match; -wire wp_match; + +reg [ (32-2)+2-1:8] eba; + + + + +reg [ (3-1):0] eid_x; + + + + + + + + + + + + + + + + + + + + + + + + + wire exception_x; -reg exception_m; -wire debug_exception_x; -reg debug_exception_m; -reg debug_exception_w; -wire debug_exception_q_w; -wire non_debug_exception_x; -reg non_debug_exception_m; -reg non_debug_exception_w; -wire non_debug_exception_q_w; -wire reset_exception; +reg exception_m; +reg exception_w; +wire exception_q_w; + + + + + + + + + + + wire interrupt_exception; -wire breakpoint_exception; -wire watchpoint_exception; + + + + + + + + + + + + + + + + wire system_call_exception; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + +lm32_instruction_unit_medium #( + .eba_reset (eba_reset), + .associativity (icache_associativity), + .sets (icache_sets), + .bytes_per_line (icache_bytes_per_line), + .base_address (icache_base_address), + .limit (icache_limit) + ) instruction_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_f (stall_f), + .stall_d (stall_d), + .stall_x (stall_x), + .stall_m (stall_m), + .valid_f (valid_f), + .valid_d (valid_d), + .kill_f (kill_f), + .branch_predict_taken_d (branch_predict_taken_d), + .branch_predict_address_d (branch_predict_address_d), + + + + + + .exception_m (exception_m), + .branch_taken_m (branch_taken_m), + .branch_mispredict_taken_m (branch_mispredict_taken_m), + .branch_target_m (branch_target_m), + + + + + + + + + + + + + + .i_dat_i (I_DAT_I), + .i_ack_i (I_ACK_I), + .i_err_i (I_ERR_I), + .i_rty_i (I_RTY_I), + + + + + + + + + + + + .pc_f (pc_f), + .pc_d (pc_d), + .pc_x (pc_x), + .pc_m (pc_m), + .pc_w (pc_w), + + + + + + + + + + + .i_dat_o (I_DAT_O), + .i_adr_o (I_ADR_O), + .i_cyc_o (I_CYC_O), + .i_sel_o (I_SEL_O), + .i_stb_o (I_STB_O), + .i_we_o (I_WE_O), + .i_cti_o (I_CTI_O), + .i_lock_o (I_LOCK_O), + .i_bte_o (I_BTE_O), + + + + + + + + + + + + + + + + + + + + + + .instruction_f (instruction_f), + + + + + .instruction_d (instruction_d) + + + + ); + + +lm32_decoder_medium decoder ( + + .instruction (instruction_d), + + .d_result_sel_0 (d_result_sel_0_d), + .d_result_sel_1 (d_result_sel_1_d), + .x_result_sel_csr (x_result_sel_csr_d), + + + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + + .x_result_sel_logic (x_result_sel_logic_d), + + + + + .x_result_sel_add (x_result_sel_add_d), + .m_result_sel_compare (m_result_sel_compare_d), + + + .m_result_sel_shift (m_result_sel_shift_d), + + + .w_result_sel_load (w_result_sel_load_d), + + + .w_result_sel_mul (w_result_sel_mul_d), + + + .x_bypass_enable (x_bypass_enable_d), + .m_bypass_enable (m_bypass_enable_d), + .read_enable_0 (read_enable_0_d), + .read_idx_0 (read_idx_0_d), + .read_enable_1 (read_enable_1_d), + .read_idx_1 (read_idx_1_d), + .write_enable (write_enable_d), + .write_idx (write_idx_d), + .immediate (immediate_d), + .branch_offset (branch_offset_d), + .load (load_d), + .store (store_d), + .size (size_d), + .sign_extend (sign_extend_d), + .adder_op (adder_op_d), + .logic_op (logic_op_d), + + + .direction (direction_d), + + + + + + + + + + + + + + + + + .branch (branch_d), + .bi_unconditional (bi_unconditional), + .bi_conditional (bi_conditional), + .branch_reg (branch_reg_d), + .condition (condition_d), + + + + + .scall (scall_d), + .eret (eret_d), + + + + + + + + + .csr_write_enable (csr_write_enable_d) + ); + + +lm32_load_store_unit_medium #( + .associativity (dcache_associativity), + .sets (dcache_sets), + .bytes_per_line (dcache_bytes_per_line), + .base_address (dcache_base_address), + .limit (dcache_limit) + ) load_store_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_x (stall_x), + .stall_m (stall_m), + .kill_x (kill_x), + .kill_m (kill_m), + .exception_m (exception_m), + .store_operand_x (store_operand_x), + .load_store_address_x (adder_result_x), + .load_store_address_m (operand_m), + .load_store_address_w (operand_w[1:0]), + .load_x (load_x), + .store_x (store_x), + .load_q_x (load_q_x), + .store_q_x (store_q_x), + .load_q_m (load_q_m), + .store_q_m (store_q_m), + .sign_extend_x (sign_extend_x), + .size_x (size_x), + + + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), + .d_ack_i (D_ACK_I), + .d_err_i (D_ERR_I), + .d_rty_i (D_RTY_I), + + + + + + + + + + .load_data_w (load_data_w), + .stall_wb_load (stall_wb_load), + + .d_dat_o (D_DAT_O), + .d_adr_o (D_ADR_O), + .d_cyc_o (D_CYC_O), + .d_sel_o (D_SEL_O), + .d_stb_o (D_STB_O), + .d_we_o (D_WE_O), + .d_cti_o (D_CTI_O), + .d_lock_o (D_LOCK_O), + .d_bte_o (D_BTE_O) + ); + + +lm32_adder adder ( + + .adder_op_x (adder_op_x), + .adder_op_x_n (adder_op_x_n), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .adder_result_x (adder_result_x), + .adder_carry_n_x (adder_carry_n_x), + .adder_overflow_x (adder_overflow_x) + ); + + +lm32_logic_op logic_op ( + + .logic_op_x (logic_op_x), + .operand_0_x (operand_0_x), + + .operand_1_x (operand_1_x), + + .logic_result_x (logic_result_x) + ); + + + + +lm32_shifter shifter ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .direction_x (direction_x), + .sign_extend_x (sign_extend_x), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .shifter_result_m (shifter_result_m) + ); + + + + + + +lm32_multiplier multiplier ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .stall_m (stall_m), + .operand_0 (d_result_0), + .operand_1 (d_result_1), + + .result (multiplier_result_w) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +lm32_interrupt_medium interrupt_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .interrupt (interrupt), + + .stall_x (stall_x), + + + + + + .exception (exception_q_w), + + + .eret_q_x (eret_q_x), + + + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + + .interrupt_exception (interrupt_exception), + + .csr_read_data (interrupt_csr_read_data_x) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; + reg [31:0] w_result_d; + reg regfile_raw_0, regfile_raw_0_nxt; + reg regfile_raw_1, regfile_raw_1_nxt; + + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) + begin + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[25:21])) + regfile_raw_0_nxt = 1'b1; + else + regfile_raw_0_nxt = 1'b0; + + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[20:16])) + regfile_raw_1_nxt = 1'b1; + else + regfile_raw_1_nxt = 1'b0; + end + + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) + if (regfile_raw_0) + reg_data_live_0 = w_result_d; + else + reg_data_live_0 = regfile_data_0; + + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) + if (regfile_raw_1) + reg_data_live_1 = w_result_d; + else + reg_data_live_1 = regfile_data_1; + + + + + always @(posedge clk_i ) + if (rst_i == 1'b1) + begin + regfile_raw_0 <= 1'b0; + regfile_raw_1 <= 1'b0; + w_result_d <= 32'b0; + end + else + begin + regfile_raw_0 <= regfile_raw_0_nxt; + regfile_raw_1 <= regfile_raw_1_nxt; + w_result_d <= w_result; + end + + + + + + lm32_dp_ram + #( + + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_0 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[25:21]), + + .rdata_o (regfile_data_0) + ); + + lm32_dp_ram + #( + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_1 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[20:16]), + + .rdata_o (regfile_data_1) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; +assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + +assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); +assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); +assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); +assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); +assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); +assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + +always @(*) +begin + if ( ( (x_bypass_enable_x == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) + ) + ) + || ( (m_bypass_enable_m == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) + ) + ) + ) + interlock = 1'b1; + else + interlock = 1'b0; end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + +always @(*) +begin + if (raw_x_0 == 1'b1) + bypass_data_0 = x_result; + else if (raw_m_0 == 1'b1) + bypass_data_0 = m_result; + else if (raw_w_0 == 1'b1) + bypass_data_0 = w_result; + else + bypass_data_0 = reg_data_0; +end + + +always @(*) +begin + if (raw_x_1 == 1'b1) + bypass_data_1 = x_result; + else if (raw_m_1 == 1'b1) + bypass_data_1 = m_result; + else if (raw_w_1 == 1'b1) + bypass_data_1 = w_result; + else + bypass_data_1 = reg_data_1; +end + + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; + assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + + assign branch_target_d = pc_d + branch_offset_d; + + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + +always @(*) +begin + d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; + case (d_result_sel_1_d) + 2'b00: d_result_1 = { 32{1'b0}}; + 2'b01: d_result_1 = bypass_data_1; + 2'b10: d_result_1 = immediate_d; + default: d_result_1 = { 32{1'bx}}; + endcase +end + + + + + + + + + + + +assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; +assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; +assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + +assign cmp_zero = operand_0_x == operand_1_x; +assign cmp_negative = adder_result_x[ 32-1]; +assign cmp_overflow = adder_overflow_x; +assign cmp_carry_n = adder_carry_n_x; +always @(*) +begin + case (condition_x) + 3'b000: condition_met_x = 1'b1; + 3'b110: condition_met_x = 1'b1; + 3'b001: condition_met_x = cmp_zero; + 3'b111: condition_met_x = !cmp_zero; + 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); + 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; + 3'b011: condition_met_x = cmp_negative == cmp_overflow; + 3'b100: condition_met_x = cmp_carry_n; + default: condition_met_x = 1'bx; + endcase +end + + +always @(*) +begin + x_result = x_result_sel_add_x ? adder_result_x + : x_result_sel_csr_x ? csr_read_data_x + + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + + + : logic_result_x; +end + + +always @(*) +begin + m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + + : m_result_sel_shift_m ? shifter_result_m + + + : operand_m; +end + + +always @(*) +begin + w_result = w_result_sel_load_w ? load_data_w + + + : w_result_sel_mul_w ? multiplier_result_w + + + : operand_w; +end + + + + + + + + + + + + + +assign branch_taken_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( ( (condition_met_m == 1'b1) + && (branch_predict_taken_m == 1'b0) + ) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign branch_mispredict_taken_m = (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1); + + +assign branch_flushX_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( (condition_met_m == 1'b1) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign kill_f = ( (valid_d == 1'b1) + && (branch_predict_taken_d == 1'b1) + ) + || (branch_taken_m == 1'b1) + + + + + + + + + + + + + ; +assign kill_d = (branch_taken_m == 1'b1) + + + + + + + + + + + + + ; +assign kill_x = (branch_flushX_m == 1'b1) + + + + + ; +assign kill_m = 1'b0 + + + + + ; +assign kill_w = 1'b0 + + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign system_call_exception = ( (scall_x == 1'b1) + + + + + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign exception_x = (system_call_exception == 1'b1) + + + + + + + + + + + + || ( (interrupt_exception == 1'b1) + + + + + + + + + + ) + + + ; + + + + +always @(*) +begin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if ( (interrupt_exception == 1'b1) + + + + + ) + eid_x = 3'h6; + else + + + eid_x = 3'h7; +end + + + +assign stall_a = (stall_f == 1'b1); + +assign stall_f = (stall_d == 1'b1); + +assign stall_d = (stall_x == 1'b1) + || ( (interlock == 1'b1) + && (kill_d == 1'b0) + ) + || ( ( (eret_d == 1'b1) + || (scall_d == 1'b1) + + + + + ) + && ( (load_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_x == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + + + + + + + + + + + + + + || ( (csr_write_enable_d == 1'b1) + && (load_q_x == 1'b1) + ) + + + + + + + + + + + ; + +assign stall_x = (stall_m == 1'b1) + + + + + + + + + ; + +assign stall_m = (stall_wb_load == 1'b1) + + + + + || ( (D_CYC_O == 1'b1) + && ( (store_m == 1'b1) + + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + + || (load_m == 1'b1) + || (load_x == 1'b1) + ) + ) + + + + + + + + + + + + + + || (I_CYC_O == 1'b1) + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + +assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); +assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); +assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + + + +assign load_q_x = (load_x == 1'b1) + && (q_x == 1'b1) + + + + + ; +assign store_q_x = (store_x == 1'b1) + && (q_x == 1'b1) + + + + + ; + + + + +assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); +assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); +assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + + + + +assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + + +assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); +assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); +assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + +assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + +assign cfg = { + 6'h02, + watchpoints[3:0], + breakpoints[3:0], + interrupts[5:0], + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + + + 1'b0, + + + + + 1'b1 + + + + + }; + +assign cfg2 = { + 30'b0, + + + + + 1'b0, + + + + + + + 1'b0 + + + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign csr_d = read_idx_0_d[ (4 -1):0]; + + +always @(*) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; -end -endfunction -lm32_instruction_unit_medium_icache_debug #( - .eba_reset (eba_reset), - .associativity (icache_associativity), - .sets (icache_sets), - .bytes_per_line (icache_bytes_per_line), - .base_address (icache_base_address), - .limit (icache_limit) - ) instruction_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .stall_d (stall_d), - .stall_x (stall_x), - .stall_m (stall_m), - .valid_f (valid_f), - .valid_d (valid_d), - .kill_f (kill_f), - .branch_predict_taken_d (branch_predict_taken_d), - .branch_predict_address_d (branch_predict_address_d), - .exception_m (exception_m), - .branch_taken_m (branch_taken_m), - .branch_mispredict_taken_m (branch_mispredict_taken_m), - .branch_target_m (branch_target_m), - .iflush (iflush), - .i_dat_i (I_DAT_I), - .i_ack_i (I_ACK_I), - .i_err_i (I_ERR_I), - .i_rty_i (I_RTY_I), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - .pc_f (pc_f), - .pc_d (pc_d), - .pc_x (pc_x), - .pc_m (pc_m), - .pc_w (pc_w), - .icache_stall_request (icache_stall_request), - .icache_restart_request (icache_restart_request), - .icache_refill_request (icache_refill_request), - .icache_refilling (icache_refilling), - .i_dat_o (I_DAT_O), - .i_adr_o (I_ADR_O), - .i_cyc_o (I_CYC_O), - .i_sel_o (I_SEL_O), - .i_stb_o (I_STB_O), - .i_we_o (I_WE_O), - .i_cti_o (I_CTI_O), - .i_lock_o (I_LOCK_O), - .i_bte_o (I_BTE_O), - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - .instruction_f (instruction_f), - .instruction_d (instruction_d) - ); -lm32_decoder_medium_icache_debug decoder ( - .instruction (instruction_d), - .d_result_sel_0 (d_result_sel_0_d), - .d_result_sel_1 (d_result_sel_1_d), - .x_result_sel_csr (x_result_sel_csr_d), - .x_result_sel_sext (x_result_sel_sext_d), - .x_result_sel_logic (x_result_sel_logic_d), - .x_result_sel_add (x_result_sel_add_d), - .m_result_sel_compare (m_result_sel_compare_d), - .m_result_sel_shift (m_result_sel_shift_d), - .w_result_sel_load (w_result_sel_load_d), - .w_result_sel_mul (w_result_sel_mul_d), - .x_bypass_enable (x_bypass_enable_d), - .m_bypass_enable (m_bypass_enable_d), - .read_enable_0 (read_enable_0_d), - .read_idx_0 (read_idx_0_d), - .read_enable_1 (read_enable_1_d), - .read_idx_1 (read_idx_1_d), - .write_enable (write_enable_d), - .write_idx (write_idx_d), - .immediate (immediate_d), - .branch_offset (branch_offset_d), - .load (load_d), - .store (store_d), - .size (size_d), - .sign_extend (sign_extend_d), - .adder_op (adder_op_d), - .logic_op (logic_op_d), - .direction (direction_d), - .branch (branch_d), - .bi_unconditional (bi_unconditional), - .bi_conditional (bi_conditional), - .branch_reg (branch_reg_d), - .condition (condition_d), - .break_opcode (break_d), - .scall (scall_d), - .eret (eret_d), - .bret (bret_d), - .csr_write_enable (csr_write_enable_d) - ); -lm32_load_store_unit_medium_icache_debug #( - .associativity (dcache_associativity), - .sets (dcache_sets), - .bytes_per_line (dcache_bytes_per_line), - .base_address (dcache_base_address), - .limit (dcache_limit) - ) load_store_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_x (stall_x), - .stall_m (stall_m), - .kill_x (kill_x), - .kill_m (kill_m), - .exception_m (exception_m), - .store_operand_x (store_operand_x), - .load_store_address_x (adder_result_x), - .load_store_address_m (operand_m), - .load_store_address_w (operand_w[1:0]), - .load_x (load_x), - .store_x (store_x), - .load_q_x (load_q_x), - .store_q_x (store_q_x), - .load_q_m (load_q_m), - .store_q_m (store_q_m), - .sign_extend_x (sign_extend_x), - .size_x (size_x), - .d_dat_i (D_DAT_I), - .d_ack_i (D_ACK_I), - .d_err_i (D_ERR_I), - .d_rty_i (D_RTY_I), - .load_data_w (load_data_w), - .stall_wb_load (stall_wb_load), - .d_dat_o (D_DAT_O), - .d_adr_o (D_ADR_O), - .d_cyc_o (D_CYC_O), - .d_sel_o (D_SEL_O), - .d_stb_o (D_STB_O), - .d_we_o (D_WE_O), - .d_cti_o (D_CTI_O), - .d_lock_o (D_LOCK_O), - .d_bte_o (D_BTE_O) - ); -lm32_adder adder ( - .adder_op_x (adder_op_x), - .adder_op_x_n (adder_op_x_n), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .adder_result_x (adder_result_x), - .adder_carry_n_x (adder_carry_n_x), - .adder_overflow_x (adder_overflow_x) - ); -lm32_logic_op logic_op ( - .logic_op_x (logic_op_x), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .logic_result_x (logic_result_x) - ); -lm32_shifter shifter ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_x (stall_x), - .direction_x (direction_x), - .sign_extend_x (sign_extend_x), - .operand_0_x (operand_0_x), - .operand_1_x (operand_1_x), - .shifter_result_m (shifter_result_m) - ); -lm32_multiplier multiplier ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_x (stall_x), - .stall_m (stall_m), - .operand_0 (d_result_0), - .operand_1 (d_result_1), - .result (multiplier_result_w) - ); -lm32_interrupt_medium_icache_debug interrupt_unit ( - .clk_i (clk_i), - .rst_i (rst_i), - .interrupt (interrupt), - .stall_x (stall_x), - .non_debug_exception (non_debug_exception_q_w), - .debug_exception (debug_exception_q_w), - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .interrupt_exception (interrupt_exception), - .csr_read_data (interrupt_csr_read_data_x) - ); -lm32_jtag_medium_icache_debug jtag ( - .clk_i (clk_i), - .rst_i (rst_i), - .jtag_clk (jtag_clk), - .jtag_update (jtag_update), - .jtag_reg_q (jtag_reg_q), - .jtag_reg_addr_q (jtag_reg_addr_q), - .csr (csr_x), - .csr_write_data (operand_1_x), - .csr_write_enable (csr_write_enable_q_x), - .stall_x (stall_x), - .jtag_read_data (jtag_read_data), - .jtag_access_complete (jtag_access_complete), - .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), - .jtx_csr_read_data (jtx_csr_read_data), - .jrx_csr_read_data (jrx_csr_read_data), - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .jtag_read_enable (jtag_read_enable), - .jtag_write_enable (jtag_write_enable), - .jtag_write_data (jtag_write_data), - .jtag_address (jtag_address), - .jtag_break (jtag_break), - .jtag_reset (reset_exception), - .jtag_reg_d (jtag_reg_d), - .jtag_reg_addr_d (jtag_reg_addr_d) - ); -lm32_debug_medium_icache_debug #( - .breakpoints (breakpoints), - .watchpoints (watchpoints) - ) hw_debug ( - .clk_i (clk_i), - .rst_i (rst_i), - .pc_x (pc_x), - .load_x (load_x), - .store_x (store_x), - .load_store_address_x (adder_result_x), - .csr_write_enable_x (csr_write_enable_q_x), - .csr_write_data (operand_1_x), - .csr_x (csr_x), - .jtag_csr_write_enable (jtag_csr_write_enable), - .jtag_csr_write_data (jtag_csr_write_data), - .jtag_csr (jtag_csr), - .eret_q_x (eret_q_x), - .bret_q_x (bret_q_x), - .stall_x (stall_x), - .exception_x (exception_x), - .q_x (q_x), - .dc_ss (dc_ss), - .dc_re (dc_re), - .bp_match (bp_match), - .wp_match (wp_match) + case (csr_x) + + + 4 'h0, + 4 'h1, + 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + + 4 'h6: csr_read_data_x = cfg; + 4 'h7: csr_read_data_x = {eba, 8'h00}; + + + + + + + + + + 4 'ha: csr_read_data_x = cfg2; + 4 'hb: csr_read_data_x = sdb_address; + + default: csr_read_data_x = { 32{1'bx}}; + endcase +end + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + eba <= eba_reset[ (32-2)+2-1:8]; + else + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (32-2)+2-1:8]; + + + + + + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + valid_f <= 1'b0; + valid_d <= 1'b0; + valid_x <= 1'b0; + valid_m <= 1'b0; + valid_w <= 1'b0; + end + else + begin + if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + + + + valid_f <= 1'b1; + + + else if (stall_f == 1'b0) + valid_f <= 1'b0; + + if (kill_d == 1'b1) + valid_d <= 1'b0; + else if (stall_f == 1'b0) + valid_d <= valid_f & !kill_f; + else if (stall_d == 1'b0) + valid_d <= 1'b0; + + if (stall_d == 1'b0) + valid_x <= valid_d & !kill_d; + else if (kill_x == 1'b1) + valid_x <= 1'b0; + else if (stall_x == 1'b0) + valid_x <= 1'b0; + + if (kill_m == 1'b1) + valid_m <= 1'b0; + else if (stall_x == 1'b0) + valid_m <= valid_x & !kill_x; + else if (stall_m == 1'b0) + valid_m <= 1'b0; + + if (stall_m == 1'b0) + valid_w <= valid_m & !kill_m; + else + valid_w <= 1'b0; + end +end + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + + + + + operand_0_x <= { 32{1'b0}}; + operand_1_x <= { 32{1'b0}}; + store_operand_x <= { 32{1'b0}}; + branch_target_x <= { (32-2){1'b0}}; + x_result_sel_csr_x <= 1'b0; + + + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + + x_result_sel_add_x <= 1'b0; + m_result_sel_compare_x <= 1'b0; + + + m_result_sel_shift_x <= 1'b0; + + + w_result_sel_load_x <= 1'b0; + + + w_result_sel_mul_x <= 1'b0; + + + x_bypass_enable_x <= 1'b0; + m_bypass_enable_x <= 1'b0; + write_enable_x <= 1'b0; + write_idx_x <= { 5{1'b0}}; + csr_x <= { 4 {1'b0}}; + load_x <= 1'b0; + store_x <= 1'b0; + size_x <= { 2{1'b0}}; + sign_extend_x <= 1'b0; + adder_op_x <= 1'b0; + adder_op_x_n <= 1'b0; + logic_op_x <= 4'h0; + + + direction_x <= 1'b0; + + + + + + + + branch_x <= 1'b0; + branch_predict_x <= 1'b0; + branch_predict_taken_x <= 1'b0; + condition_x <= 3'b000; + + + + + scall_x <= 1'b0; + eret_x <= 1'b0; + + + + + + + + + + csr_write_enable_x <= 1'b0; + operand_m <= { 32{1'b0}}; + branch_target_m <= { (32-2){1'b0}}; + m_result_sel_compare_m <= 1'b0; + + + m_result_sel_shift_m <= 1'b0; + + + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + + m_bypass_enable_m <= 1'b0; + branch_m <= 1'b0; + branch_predict_m <= 1'b0; + branch_predict_taken_m <= 1'b0; + exception_m <= 1'b0; + load_m <= 1'b0; + store_m <= 1'b0; + write_enable_m <= 1'b0; + write_idx_m <= { 5{1'b0}}; + condition_met_m <= 1'b0; + + + + + + + + + + operand_w <= { 32{1'b0}}; + w_result_sel_load_w <= 1'b0; + + + w_result_sel_mul_w <= 1'b0; + + + write_idx_w <= { 5{1'b0}}; + write_enable_w <= 1'b0; + + + + + + exception_w <= 1'b0; + + + + + + + end + else + begin + + + if (stall_x == 1'b0) + begin + + + + + operand_0_x <= d_result_0; + operand_1_x <= d_result_1; + store_operand_x <= bypass_data_1; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; + x_result_sel_csr_x <= x_result_sel_csr_d; + + + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + + x_result_sel_add_x <= x_result_sel_add_d; + m_result_sel_compare_x <= m_result_sel_compare_d; + + + m_result_sel_shift_x <= m_result_sel_shift_d; + + + w_result_sel_load_x <= w_result_sel_load_d; + + + w_result_sel_mul_x <= w_result_sel_mul_d; + + + x_bypass_enable_x <= x_bypass_enable_d; + m_bypass_enable_x <= m_bypass_enable_d; + load_x <= load_d; + store_x <= store_d; + branch_x <= branch_d; + branch_predict_x <= branch_predict_d; + branch_predict_taken_x <= branch_predict_taken_d; + write_idx_x <= write_idx_d; + csr_x <= csr_d; + size_x <= size_d; + sign_extend_x <= sign_extend_d; + adder_op_x <= adder_op_d; + adder_op_x_n <= ~adder_op_d; + logic_op_x <= logic_op_d; + + + direction_x <= direction_d; + + + + + + + condition_x <= condition_d; + csr_write_enable_x <= csr_write_enable_d; + + + + + scall_x <= scall_d; + + + + + eret_x <= eret_d; + + + + + write_enable_x <= write_enable_d; + end + + + + if (stall_m == 1'b0) + begin + operand_m <= x_result; + m_result_sel_compare_m <= m_result_sel_compare_x; + + + m_result_sel_shift_m <= m_result_sel_shift_x; + + + if (exception_x == 1'b1) + begin + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + + end + else + begin + w_result_sel_load_m <= w_result_sel_load_x; + + + w_result_sel_mul_m <= w_result_sel_mul_x; + + + end + m_bypass_enable_m <= m_bypass_enable_x; + load_m <= load_x; + store_m <= store_x; + + + + + branch_m <= branch_x; + branch_predict_m <= branch_predict_x; + branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + + + + + + + + + if (exception_x == 1'b1) + write_idx_m <= 5'd30; + else + write_idx_m <= write_idx_x; + + + condition_met_m <= condition_met_x; + + + + + + + + + + + + + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + + + + end + + + if (stall_m == 1'b0) + begin + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + exception_m <= 1'b1; + else + exception_m <= 1'b0; + + + + + + + + + end + + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + + w_result_sel_load_w <= w_result_sel_load_m; + + + w_result_sel_mul_w <= w_result_sel_mul_m; + + + write_idx_w <= write_idx_m; + + + + + + + + + write_enable_w <= write_enable_m; + + + + + + exception_w <= exception_m; + + + + + + + + + + + + end +end + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + use_buf <= 1'b0; + reg_data_buf_0 <= { 32{1'b0}}; + reg_data_buf_1 <= { 32{1'b0}}; + end + else + begin + if (stall_d == 1'b0) + use_buf <= 1'b0; + else if (use_buf == 1'b0) + begin + reg_data_buf_0 <= reg_data_live_0; + reg_data_buf_1 <= reg_data_live_1; + use_buf <= 1'b1; + end + if (reg_write_enable_q_w == 1'b1) + begin + if (write_idx_w == read_idx_0_d) + reg_data_buf_0 <= w_result; + if (write_idx_w == read_idx_1_d) + reg_data_buf_1 <= w_result; + end + end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +initial +begin + + + + + + +end + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_medium +( + + clk_i, + + + + + rst_i, + + stall_a, + stall_x, + stall_m, + kill_x, + kill_m, + exception_m, + store_operand_x, + load_store_address_x, + load_store_address_m, + load_store_address_w, + load_x, + store_x, + load_q_x, + store_q_x, + load_q_m, + store_q_m, + sign_extend_x, + size_x, + + + + + + d_dat_i, + d_ack_i, + d_err_i, + d_rty_i, + + + + + + + + + + + + + + + + + + + + load_data_w, + stall_wb_load, + + d_dat_o, + d_adr_o, + d_cyc_o, + d_sel_o, + d_stb_o, + d_we_o, + d_cti_o, + d_lock_o, + d_bte_o ); - wire [31:0] regfile_data_0, regfile_data_1; - reg [31:0] w_result_d; - reg regfile_raw_0, regfile_raw_0_nxt; - reg regfile_raw_1, regfile_raw_1_nxt; - always @(reg_write_enable_q_w or write_idx_w or instruction_f) - begin - if (reg_write_enable_q_w - && (write_idx_w == instruction_f[25:21])) - regfile_raw_0_nxt = 1'b1; - else - regfile_raw_0_nxt = 1'b0; - if (reg_write_enable_q_w - && (write_idx_w == instruction_f[20:16])) - regfile_raw_1_nxt = 1'b1; - else - regfile_raw_1_nxt = 1'b0; - end - always @(regfile_raw_0 or w_result_d or regfile_data_0) - if (regfile_raw_0) - reg_data_live_0 = w_result_d; - else - reg_data_live_0 = regfile_data_0; - always @(regfile_raw_1 or w_result_d or regfile_data_1) - if (regfile_raw_1) - reg_data_live_1 = w_result_d; - else - reg_data_live_1 = regfile_data_1; - always @(posedge clk_i ) - if (rst_i == 1'b1) - begin - regfile_raw_0 <= 1'b0; - regfile_raw_1 <= 1'b0; - w_result_d <= 32'b0; - end - else - begin - regfile_raw_0 <= regfile_raw_0_nxt; - regfile_raw_1 <= regfile_raw_1_nxt; - w_result_d <= w_result; - end - lm32_dp_ram - #( - .addr_depth(1<<5), - .addr_width(5), - .data_width(32) - ) - reg_0 - ( - .clk_i (clk_i), - .rst_i (rst_i), - .we_i (reg_write_enable_q_w), - .wdata_i (w_result), - .waddr_i (write_idx_w), - .raddr_i (instruction_f[25:21]), - .rdata_o (regfile_data_0) - ); - lm32_dp_ram - #( - .addr_depth(1<<5), - .addr_width(5), - .data_width(32) - ) - reg_1 - ( - .clk_i (clk_i), - .rst_i (rst_i), - .we_i (reg_write_enable_q_w), - .wdata_i (w_result), - .waddr_i (write_idx_w), - .raddr_i (instruction_f[20:16]), - .rdata_o (regfile_data_1) - ); -assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; -assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; -assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); -assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); -assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); -assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); -assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); -assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + input clk_i; + +input rst_i; + +input stall_a; +input stall_x; +input stall_m; +input kill_x; +input kill_m; +input exception_m; + +input [ (32-1):0] store_operand_x; +input [ (32-1):0] load_store_address_x; +input [ (32-1):0] load_store_address_m; +input [1:0] load_store_address_w; +input load_x; +input store_x; +input load_q_x; +input store_q_x; +input load_q_m; +input store_q_m; +input sign_extend_x; +input [ 1:0] size_x; + + + + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + +input [ (32-1):0] d_dat_i; +input d_ack_i; +input d_err_i; +input d_rty_i; + + + + + + + + + + + + + + + + + + +output [ (32-1):0] load_data_w; +reg [ (32-1):0] load_data_w; +output stall_wb_load; +reg stall_wb_load; + +output [ (32-1):0] d_dat_o; +reg [ (32-1):0] d_dat_o; +output [ (32-1):0] d_adr_o; +reg [ (32-1):0] d_adr_o; +output d_cyc_o; +reg d_cyc_o; +output [ (4-1):0] d_sel_o; +reg [ (4-1):0] d_sel_o; +output d_stb_o; +reg d_stb_o; +output d_we_o; +reg d_we_o; +output [ (3-1):0] d_cti_o; +reg [ (3-1):0] d_cti_o; +output d_lock_o; +reg d_lock_o; +output [ (2-1):0] d_bte_o; +wire [ (2-1):0] d_bte_o; + + + + + + +reg [ 1:0] size_m; +reg [ 1:0] size_w; +reg sign_extend_m; +reg sign_extend_w; +reg [ (32-1):0] store_data_x; +reg [ (32-1):0] store_data_m; +reg [ (4-1):0] byte_enable_x; +reg [ (4-1):0] byte_enable_m; +wire [ (32-1):0] data_m; +reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + +wire wb_select_x; + + + + + + + + + + +reg wb_select_m; +reg [ (32-1):0] wb_data_m; +reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + + + ; + + always @(*) begin - if ( ( (x_bypass_enable_x == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) - ) - ) - || ( (m_bypass_enable_m == 1'b0) - && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) - || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) - ) - ) - ) - interlock = 1'b1; + case (size_x) + 2'b00: store_data_x = {4{store_operand_x[7:0]}}; + 2'b11: store_data_x = {2{store_operand_x[15:0]}}; + 2'b10: store_data_x = store_operand_x; + default: store_data_x = { 32{1'bx}}; + endcase +end + + +always @(*) +begin + casez ({size_x, load_store_address_x[1:0]}) + { 2'b00, 2'b11}: byte_enable_x = 4'b0001; + { 2'b00, 2'b10}: byte_enable_x = 4'b0010; + { 2'b00, 2'b01}: byte_enable_x = 4'b0100; + { 2'b00, 2'b00}: byte_enable_x = 4'b1000; + { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; + { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; + { 2'b10, 2'b??}: byte_enable_x = 4'b1111; + default: byte_enable_x = 4'bxxxx; + endcase +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_data_m; + + + + + + + + +always @(*) +begin + casez ({size_w, load_store_address_w[1:0]}) + { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; + { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; + { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; + { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; + { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; + { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; + { 2'b10, 2'b??}: load_data_w = data_w; + default: load_data_w = { 32{1'bx}}; + endcase +end + + +assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_dat_o <= { 32{1'b0}}; + d_adr_o <= { 32{1'b0}}; + d_sel_o <= { 4{ 1'b0}}; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + d_lock_o <= 1'b0; + wb_data_m <= { 32{1'b0}}; + wb_load_complete <= 1'b0; + stall_wb_load <= 1'b0; + + + + + end else - interlock = 1'b0; + begin + + + + + + + if (d_cyc_o == 1'b1) + begin + + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) + begin + + + + + + + + + + begin + + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_lock_o <= 1'b0; + end + + + + + + + + wb_data_m <= d_dat_i; + + wb_load_complete <= !d_we_o; + end + + if (d_err_i == 1'b1) + $display ("Data bus error. Address: %x", d_adr_o); + + end + else + begin + + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) + && (stall_m == 1'b0) + + + + + + + + + ) + begin + + d_dat_o <= store_data_m; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b1; + d_cti_o <= 3'b111; + end + else if ( (load_q_m == 1'b1) + && (wb_select_m == 1'b1) + && (wb_load_complete == 1'b0) + + ) + begin + + stall_wb_load <= 1'b0; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + end + end + + if (stall_m == 1'b0) + wb_load_complete <= 1'b0; + + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) + stall_wb_load <= 1'b1; + + if ((kill_m == 1'b1) || (exception_m == 1'b1)) + stall_wb_load <= 1'b0; + end end -always @(*) + + + + +always @(posedge clk_i ) begin - if (raw_x_0 == 1'b1) - bypass_data_0 = x_result; - else if (raw_m_0 == 1'b1) - bypass_data_0 = m_result; - else if (raw_w_0 == 1'b1) - bypass_data_0 = w_result; + if (rst_i == 1'b1) + begin + sign_extend_m <= 1'b0; + size_m <= 2'b00; + byte_enable_m <= 1'b0; + store_data_m <= { 32{1'b0}}; + + + + + + + + + + + + + + wb_select_m <= 1'b0; + end else - bypass_data_0 = reg_data_0; + begin + if (stall_m == 1'b0) + begin + sign_extend_m <= sign_extend_x; + size_m <= size_x; + byte_enable_m <= byte_enable_x; + store_data_m <= store_data_x; + + + + + + + + + + + + + + wb_select_m <= wb_select_x; + end + end end -always @(*) + + +always @(posedge clk_i ) begin - if (raw_x_1 == 1'b1) - bypass_data_1 = x_result; - else if (raw_m_1 == 1'b1) - bypass_data_1 = m_result; - else if (raw_w_1 == 1'b1) - bypass_data_1 = w_result; + if (rst_i == 1'b1) + begin + size_w <= 2'b00; + data_w <= { 32{1'b0}}; + sign_extend_w <= 1'b0; + end else - bypass_data_1 = reg_data_1; + begin + size_w <= size_m; + + + + + + data_w <= data_m; + + sign_extend_w <= sign_extend_m; + end end - assign branch_predict_d = bi_unconditional | bi_conditional; - assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); - assign branch_target_d = pc_d + branch_offset_d; - assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; -always @(*) + + + + + + + + +always @(posedge clk_i) begin - d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; - case (d_result_sel_1_d) - 2'b00: d_result_1 = { 32{1'b0}}; - 2'b01: d_result_1 = bypass_data_1; - 2'b10: d_result_1 = immediate_d; - default: d_result_1 = { 32{1'bx}}; - endcase + if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) + begin + if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) + $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) + $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + end end -assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; -assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; -assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; -assign cmp_zero = operand_0_x == operand_1_x; -assign cmp_negative = adder_result_x[ 32-1]; -assign cmp_overflow = adder_overflow_x; -assign cmp_carry_n = adder_carry_n_x; -always @(*) + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_medium ( + + instruction, + + d_result_sel_0, + d_result_sel_1, + x_result_sel_csr, + + + + + + + + + + + x_result_sel_sext, + + + x_result_sel_logic, + + + + + x_result_sel_add, + m_result_sel_compare, + + + m_result_sel_shift, + + + w_result_sel_load, + + + w_result_sel_mul, + + + x_bypass_enable, + m_bypass_enable, + read_enable_0, + read_idx_0, + read_enable_1, + read_idx_1, + write_enable, + write_idx, + immediate, + branch_offset, + load, + store, + size, + sign_extend, + adder_op, + logic_op, + + + direction, + + + + + + + + + + + + + + + + + branch, + branch_reg, + condition, + bi_conditional, + bi_unconditional, + + + + + scall, + eret, + + + + + + + + + csr_write_enable + ); + + + + + +input [ (32-1):0] instruction; + + + + + +output [ 0:0] d_result_sel_0; +reg [ 0:0] d_result_sel_0; +output [ 1:0] d_result_sel_1; +reg [ 1:0] d_result_sel_1; +output x_result_sel_csr; +reg x_result_sel_csr; + + + + + + + + + + + + +output x_result_sel_sext; +reg x_result_sel_sext; + + +output x_result_sel_logic; +reg x_result_sel_logic; + + + + + +output x_result_sel_add; +reg x_result_sel_add; +output m_result_sel_compare; +reg m_result_sel_compare; + + +output m_result_sel_shift; +reg m_result_sel_shift; + + +output w_result_sel_load; +reg w_result_sel_load; + + +output w_result_sel_mul; +reg w_result_sel_mul; + + +output x_bypass_enable; +wire x_bypass_enable; +output m_bypass_enable; +wire m_bypass_enable; +output read_enable_0; +wire read_enable_0; +output [ (5-1):0] read_idx_0; +wire [ (5-1):0] read_idx_0; +output read_enable_1; +wire read_enable_1; +output [ (5-1):0] read_idx_1; +wire [ (5-1):0] read_idx_1; +output write_enable; +wire write_enable; +output [ (5-1):0] write_idx; +wire [ (5-1):0] write_idx; +output [ (32-1):0] immediate; +wire [ (32-1):0] immediate; +output [ ((32-2)+2-1):2] branch_offset; +wire [ ((32-2)+2-1):2] branch_offset; +output load; +wire load; +output store; +wire store; +output [ 1:0] size; +wire [ 1:0] size; +output sign_extend; +wire sign_extend; +output adder_op; +wire adder_op; +output [ 3:0] logic_op; +wire [ 3:0] logic_op; + + +output direction; +wire direction; + + + + + + + + + + + + + + + + + + + + + +output branch; +wire branch; +output branch_reg; +wire branch_reg; +output [ (3-1):0] condition; +wire [ (3-1):0] condition; +output bi_conditional; +wire bi_conditional; +output bi_unconditional; +wire bi_unconditional; + + + + + +output scall; +wire scall; +output eret; +wire eret; + + + + + + + + + + +output csr_write_enable; +wire csr_write_enable; + + + + + +wire [ (32-1):0] extended_immediate; +wire [ (32-1):0] high_immediate; +wire [ (32-1):0] call_immediate; +wire [ (32-1):0] branch_immediate; +wire sign_extend_immediate; +wire select_high_immediate; +wire select_call_immediate; + +wire op_add; +wire op_and; +wire op_andhi; +wire op_b; +wire op_bi; +wire op_be; +wire op_bg; +wire op_bge; +wire op_bgeu; +wire op_bgu; +wire op_bne; +wire op_call; +wire op_calli; +wire op_cmpe; +wire op_cmpg; +wire op_cmpge; +wire op_cmpgeu; +wire op_cmpgu; +wire op_cmpne; + + + + +wire op_lb; +wire op_lbu; +wire op_lh; +wire op_lhu; +wire op_lw; + + + + + + +wire op_mul; + + +wire op_nor; +wire op_or; +wire op_orhi; +wire op_raise; +wire op_rcsr; +wire op_sb; + + +wire op_sextb; +wire op_sexth; + + +wire op_sh; + + +wire op_sl; + + +wire op_sr; +wire op_sru; +wire op_sub; +wire op_sw; + + + + +wire op_wcsr; +wire op_xnor; +wire op_xor; + +wire arith; +wire logical; +wire cmp; +wire bra; +wire call; + + +wire shift; + + + + + + + + +wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - case (condition_x) - 3'b000: condition_met_x = 1'b1; - 3'b110: condition_met_x = 1'b1; - 3'b001: condition_met_x = cmp_zero; - 3'b111: condition_met_x = !cmp_zero; - 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); - 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; - 3'b011: condition_met_x = cmp_negative == cmp_overflow; - 3'b100: condition_met_x = cmp_carry_n; - default: condition_met_x = 1'bx; - endcase + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -always @(*) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - x_result = x_result_sel_add_x ? adder_result_x - : x_result_sel_csr_x ? csr_read_data_x - : x_result_sel_sext_x ? sext_result_x - : logic_result_x; + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end +endfunction + + + + + + + + + +assign op_add = instruction[ 30:26] == 5'b01101; +assign op_and = instruction[ 30:26] == 5'b01000; +assign op_andhi = instruction[ 31:26] == 6'b011000; +assign op_b = instruction[ 31:26] == 6'b110000; +assign op_bi = instruction[ 31:26] == 6'b111000; +assign op_be = instruction[ 31:26] == 6'b010001; +assign op_bg = instruction[ 31:26] == 6'b010010; +assign op_bge = instruction[ 31:26] == 6'b010011; +assign op_bgeu = instruction[ 31:26] == 6'b010100; +assign op_bgu = instruction[ 31:26] == 6'b010101; +assign op_bne = instruction[ 31:26] == 6'b010111; +assign op_call = instruction[ 31:26] == 6'b110110; +assign op_calli = instruction[ 31:26] == 6'b111110; +assign op_cmpe = instruction[ 30:26] == 5'b11001; +assign op_cmpg = instruction[ 30:26] == 5'b11010; +assign op_cmpge = instruction[ 30:26] == 5'b11011; +assign op_cmpgeu = instruction[ 30:26] == 5'b11100; +assign op_cmpgu = instruction[ 30:26] == 5'b11101; +assign op_cmpne = instruction[ 30:26] == 5'b11111; + + + + +assign op_lb = instruction[ 31:26] == 6'b000100; +assign op_lbu = instruction[ 31:26] == 6'b010000; +assign op_lh = instruction[ 31:26] == 6'b000111; +assign op_lhu = instruction[ 31:26] == 6'b001011; +assign op_lw = instruction[ 31:26] == 6'b001010; + + + + + + +assign op_mul = instruction[ 30:26] == 5'b00010; + + +assign op_nor = instruction[ 30:26] == 5'b00001; +assign op_or = instruction[ 30:26] == 5'b01110; +assign op_orhi = instruction[ 31:26] == 6'b011110; +assign op_raise = instruction[ 31:26] == 6'b101011; +assign op_rcsr = instruction[ 31:26] == 6'b100100; +assign op_sb = instruction[ 31:26] == 6'b001100; + + +assign op_sextb = instruction[ 31:26] == 6'b101100; +assign op_sexth = instruction[ 31:26] == 6'b110111; + + +assign op_sh = instruction[ 31:26] == 6'b000011; + + +assign op_sl = instruction[ 30:26] == 5'b01111; + + +assign op_sr = instruction[ 30:26] == 5'b00101; +assign op_sru = instruction[ 30:26] == 5'b00000; +assign op_sub = instruction[ 31:26] == 6'b110010; +assign op_sw = instruction[ 31:26] == 6'b010110; + + + + +assign op_wcsr = instruction[ 31:26] == 6'b110100; +assign op_xnor = instruction[ 30:26] == 5'b01001; +assign op_xor = instruction[ 30:26] == 5'b00110; + + +assign arith = op_add | op_sub; +assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; +assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; +assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; +assign bi_unconditional = op_bi; +assign bra = op_b | bi_unconditional | bi_conditional; +assign call = op_call | op_calli; + + +assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + +assign sext = op_sextb | op_sexth; + + + + + + + + + + + +assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; +assign store = op_sb | op_sh | op_sw; + + always @(*) begin - m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} - : m_result_sel_shift_m ? shifter_result_m - : operand_m; + + if (call) + d_result_sel_0 = 1'b1; + else + d_result_sel_0 = 1'b0; + if (call) + d_result_sel_1 = 2'b00; + else if ((instruction[31] == 1'b0) && !bra) + d_result_sel_1 = 2'b10; + else + d_result_sel_1 = 2'b01; + + x_result_sel_csr = 1'b0; + + + + + + + + + + + x_result_sel_sext = 1'b0; + + + x_result_sel_logic = 1'b0; + + + + + x_result_sel_add = 1'b0; + if (op_rcsr) + x_result_sel_csr = 1'b1; + + + + + + + + + + + + + + + + + + + + + + + else if (sext) + x_result_sel_sext = 1'b1; + + + else if (logical) + x_result_sel_logic = 1'b1; + + + + + + else + x_result_sel_add = 1'b1; + + + + m_result_sel_compare = cmp; + + + m_result_sel_shift = shift; + + + + + w_result_sel_load = load; + + + w_result_sel_mul = op_mul; + + end -always @(*) + + +assign x_bypass_enable = arith + | logical + + + + + + + + + + + + + + + + + + + + + | sext + + + + + + + | op_rcsr + ; + +assign m_bypass_enable = x_bypass_enable + + + | shift + + + | cmp + ; + +assign read_enable_0 = ~(op_bi | op_calli); +assign read_idx_0 = instruction[25:21]; + +assign read_enable_1 = ~(op_bi | op_calli | load); +assign read_idx_1 = instruction[20:16]; + +assign write_enable = ~(bra | op_raise | store | op_wcsr); +assign write_idx = call + ? 5'd29 + : instruction[31] == 1'b0 + ? instruction[20:16] + : instruction[15:11]; + + +assign size = instruction[27:26]; + +assign sign_extend = instruction[28]; + +assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + +assign logic_op = instruction[29:26]; + + + +assign direction = instruction[29]; + + + +assign branch = bra | call; +assign branch_reg = op_call | op_b; +assign condition = instruction[28:26]; + + + + +assign scall = op_raise & instruction[2]; +assign eret = op_b & (instruction[25:21] == 5'd30); + + + + + + + + + + +assign csr_write_enable = op_wcsr; + + + +assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); +assign select_high_immediate = op_andhi | op_orhi; +assign select_call_immediate = instruction[31]; + +assign high_immediate = {instruction[15:0], 16'h0000}; +assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; +assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; +assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + +assign immediate = select_high_immediate == 1'b1 + ? high_immediate + : extended_immediate; + +assign branch_offset = select_call_immediate == 1'b1 + ? (call_immediate[ (32-2)-1:0]) + : (branch_immediate[ (32-2)-1:0]); + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_medium ( + + clk_i, + rst_i, + + stall_a, + stall_f, + stall_d, + stall_x, + stall_m, + valid_f, + valid_d, + kill_f, + branch_predict_taken_d, + branch_predict_address_d, + + + + + + exception_m, + branch_taken_m, + branch_mispredict_taken_m, + branch_target_m, + + + + + + + + + + + + + + i_dat_i, + i_ack_i, + i_err_i, + i_rty_i, + + + + + + + + + + + + pc_f, + pc_d, + pc_x, + pc_m, + pc_w, + + + + + + + + + + + i_dat_o, + i_adr_o, + i_cyc_o, + i_sel_o, + i_stb_o, + i_we_o, + i_cti_o, + i_lock_o, + i_bte_o, + + + + + + + + + + + + + + + + + + + + instruction_f, + + + instruction_d + ); + + + + + +parameter eba_reset = 32'h00000000; +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam eba_reset_minus_4 = eba_reset - 4; +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + +input clk_i; +input rst_i; + +input stall_a; +input stall_f; +input stall_d; +input stall_x; +input stall_m; +input valid_f; +input valid_d; +input kill_f; + +input branch_predict_taken_d; +input [ ((32-2)+2-1):2] branch_predict_address_d; + + + + + + +input exception_m; +input branch_taken_m; +input branch_mispredict_taken_m; +input [ ((32-2)+2-1):2] branch_target_m; + + + + + + + + + + + + + + + +input [ (32-1):0] i_dat_i; +input i_ack_i; +input i_err_i; +input i_rty_i; + + + + + + + + + + + + + + + +output [ ((32-2)+2-1):2] pc_f; +reg [ ((32-2)+2-1):2] pc_f; +output [ ((32-2)+2-1):2] pc_d; +reg [ ((32-2)+2-1):2] pc_d; +output [ ((32-2)+2-1):2] pc_x; +reg [ ((32-2)+2-1):2] pc_x; +output [ ((32-2)+2-1):2] pc_m; +reg [ ((32-2)+2-1):2] pc_m; +output [ ((32-2)+2-1):2] pc_w; +reg [ ((32-2)+2-1):2] pc_w; + + + + + + + + + + + + + + + +output [ (32-1):0] i_dat_o; + + + + +wire [ (32-1):0] i_dat_o; + + +output [ (32-1):0] i_adr_o; +reg [ (32-1):0] i_adr_o; +output i_cyc_o; +reg i_cyc_o; +output [ (4-1):0] i_sel_o; + + + + +wire [ (4-1):0] i_sel_o; + + +output i_stb_o; +reg i_stb_o; +output i_we_o; + + + + +wire i_we_o; + + +output [ (3-1):0] i_cti_o; +reg [ (3-1):0] i_cti_o; +output i_lock_o; +reg i_lock_o; +output [ (2-1):0] i_bte_o; +wire [ (2-1):0] i_bte_o; + + + + + + + + + + + + + + + + + + +output [ (32-1):0] instruction_f; +wire [ (32-1):0] instruction_f; + + +output [ (32-1):0] instruction_d; +reg [ (32-1):0] instruction_d; + + + + + +reg [ ((32-2)+2-1):2] pc_a; + + + + + + + + + + + + + + + + + + + + +reg [ (32-1):0] wb_data_f; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - w_result = w_result_sel_load_w ? load_data_w - : w_result_sel_mul_w ? multiplier_result_w - : operand_w; + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -assign branch_taken_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( ( (condition_met_m == 1'b1) - && (branch_predict_taken_m == 1'b0) - ) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign branch_mispredict_taken_m = (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1); -assign branch_flushX_m = (stall_m == 1'b0) - && ( ( (branch_m == 1'b1) - && (valid_m == 1'b1) - && ( (condition_met_m == 1'b1) - || ( (condition_met_m == 1'b0) - && (branch_predict_m == 1'b1) - && (branch_predict_taken_m == 1'b1) - ) - ) - ) - || (exception_m == 1'b1) - ); -assign kill_f = ( (valid_d == 1'b1) - && (branch_predict_taken_d == 1'b1) - ) - || (branch_taken_m == 1'b1) - || (icache_refill_request == 1'b1) - ; -assign kill_d = (branch_taken_m == 1'b1) - || (icache_refill_request == 1'b1) - ; -assign kill_x = (branch_flushX_m == 1'b1) - ; -assign kill_m = 1'b0 - ; -assign kill_w = 1'b0 - ; -assign breakpoint_exception = ( ( (break_x == 1'b1) - || (bp_match == 1'b1) - ) - && (valid_x == 1'b1) - ) - || (jtag_break == 1'b1) - ; -assign watchpoint_exception = wp_match == 1'b1; -assign system_call_exception = ( (scall_x == 1'b1) - ); -assign debug_exception_x = (breakpoint_exception == 1'b1) - || (watchpoint_exception == 1'b1) - ; -assign non_debug_exception_x = (system_call_exception == 1'b1) - || (reset_exception == 1'b1) - || ( (interrupt_exception == 1'b1) - && (dc_ss == 1'b0) - ) - ; -assign exception_x = (debug_exception_x == 1'b1) || (non_debug_exception_x == 1'b1); -always @(*) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - if (reset_exception == 1'b1) - eid_x = 3'h0; - else - if (breakpoint_exception == 1'b1) - eid_x = 3'd1; - else - if (watchpoint_exception == 1'b1) - eid_x = 3'd3; - else - if ( (interrupt_exception == 1'b1) - && (dc_ss == 1'b0) - ) - eid_x = 3'h6; - else - eid_x = 3'h7; + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end -assign stall_a = (stall_f == 1'b1); -assign stall_f = (stall_d == 1'b1); -assign stall_d = (stall_x == 1'b1) - || ( (interlock == 1'b1) - && (kill_d == 1'b0) - ) - || ( ( (eret_d == 1'b1) - || (scall_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_x == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( ( (break_d == 1'b1) - || (bret_d == 1'b1) - ) - && ( (load_q_x == 1'b1) - || (store_q_x == 1'b1) - || (load_q_m == 1'b1) - || (store_q_m == 1'b1) - || (D_CYC_O == 1'b1) - ) - && (kill_d == 1'b0) - ) - || ( (csr_write_enable_d == 1'b1) - && (load_q_x == 1'b1) - ) - ; -assign stall_x = (stall_m == 1'b1) - ; -assign stall_m = (stall_wb_load == 1'b1) - || ( (D_CYC_O == 1'b1) - && ( (store_m == 1'b1) - || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) - || (load_m == 1'b1) - || (load_x == 1'b1) - ) - ) - || (icache_stall_request == 1'b1) - || ((I_CYC_O == 1'b1) && ((branch_m == 1'b1) || (exception_m == 1'b1))) - ; -assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); -assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); -assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); -assign bret_q_x = (bret_x == 1'b1) && (q_x == 1'b1); -assign load_q_x = (load_x == 1'b1) - && (q_x == 1'b1) - && (bp_match == 1'b0) - ; -assign store_q_x = (store_x == 1'b1) - && (q_x == 1'b1) - && (bp_match == 1'b0) - ; -assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); -assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); -assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); -assign debug_exception_q_w = ((debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign non_debug_exception_q_w = ((non_debug_exception_w == 1'b1) && (valid_w == 1'b1)); -assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); -assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); -assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); -assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); -assign cfg = { - 6'h02, - watchpoints[3:0], - breakpoints[3:0], - interrupts[5:0], - 1'b1, - 1'b0, - 1'b1, - 1'b1, - 1'b1, - 1'b0, - 1'b0, - 1'b0, - 1'b1, - 1'b1, - 1'b0, - 1'b1 - }; -assign cfg2 = { - 30'b0, - 1'b0, - 1'b0 - }; -assign iflush = ( (csr_write_enable_d == 1'b1) - && (csr_d == 5'h3) - && (stall_d == 1'b0) - && (kill_d == 1'b0) - && (valid_d == 1'b1)) - || - ( (jtag_csr_write_enable == 1'b1) - && (jtag_csr == 5'h3)) - ; -assign csr_d = read_idx_0_d[ (5-1):0]; +endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin - case (csr_x) - 5'h0, - 5'h1, - 5'h2: csr_read_data_x = interrupt_csr_read_data_x; - 5'h6: csr_read_data_x = cfg; - 5'h7: csr_read_data_x = {eba, 8'h00}; - 5'h9: csr_read_data_x = {deba, 8'h00}; - 5'he: csr_read_data_x = jtx_csr_read_data; - 5'hf: csr_read_data_x = jrx_csr_read_data; - 5'ha: csr_read_data_x = cfg2; - 5'hb: csr_read_data_x = sdb_address; - default: csr_read_data_x = { 32{1'bx}}; - endcase -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - eba <= eba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - else - begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h7) && (stall_x == 1'b0)) - eba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h7)) - eba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - end + + + + + + + + if (branch_taken_m == 1'b1) + if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) + pc_a = pc_x; + else + pc_a = branch_target_m; + + + + + + else + if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) + pc_a = branch_predict_address_d; + else + + + + + + + pc_a = pc_f + 1'b1; end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_f = wb_data_f; + + + + + + + + + + + + +assign i_dat_o = 32'd0; +assign i_we_o = 1'b0; +assign i_sel_o = 4'b1111; + + +assign i_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - deba <= deba_reset[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + begin + pc_f <= eba_reset_minus_4[ ((32-2)+2-1):2]; + pc_d <= { (32-2){1'b0}}; + pc_x <= { (32-2){1'b0}}; + pc_m <= { (32-2){1'b0}}; + pc_w <= { (32-2){1'b0}}; + end else begin - if ((csr_write_enable_q_x == 1'b1) && (csr_x == 5'h9) && (stall_x == 1'b0)) - deba <= operand_1_x[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; - if ((jtag_csr_write_enable == 1'b1) && (jtag_csr == 5'h9)) - deba <= jtag_csr_write_data[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:8]; + if (stall_f == 1'b0) + pc_f <= pc_a; + if (stall_d == 1'b0) + pc_d <= pc_f; + if (stall_x == 1'b0) + pc_x <= pc_d; + if (stall_m == 1'b0) + pc_m <= pc_x; + pc_w <= pc_m; end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + wb_data_f <= { 32{1'b0}}; + + + + + end + else + begin + + if (i_cyc_o == 1'b1) + begin + + if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + + wb_data_f <= i_dat_i; + end + + + + + + + + + end + else + begin + + if ( (stall_a == 1'b0) + + + + + ) + begin + + + + + + i_adr_o <= {pc_a, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + + + + + end + else + begin + if ( (stall_a == 1'b0) + + + + + ) + begin + + + + + end + end + end + end + end + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_medium ( + + clk_i, + rst_i, + + interrupt, + + stall_x, + + + + + + exception, + + + eret_q_x, + + + + + csr, + csr_write_data, + csr_write_enable, + + interrupt_exception, + + csr_read_data + ); + + + + + +parameter interrupts = 32; + + + + + +input clk_i; +input rst_i; + +input [interrupts-1:0] interrupt; + +input stall_x; + + + + + + +input exception; + + +input eret_q_x; + + + + + +input [ (4 -1):0] csr; +input [ (32-1):0] csr_write_data; +input csr_write_enable; + + + + + +output interrupt_exception; +wire interrupt_exception; + +output [ (32-1):0] csr_read_data; +reg [ (32-1):0] csr_read_data; + + + + + +wire [interrupts-1:0] asserted; + +wire [interrupts-1:0] interrupt_n_exception; + + + +reg ie; +reg eie; + + + + +reg [interrupts-1:0] ip; +reg [interrupts-1:0] im; + + + + + + +assign interrupt_n_exception = ip & im; + + +assign interrupt_exception = (|interrupt_n_exception) & ie; + + +assign asserted = ip | interrupt; + +generate + if (interrupts > 1) + begin + always @(*) begin - if (icache_refill_request == 1'b1) - valid_a = 1'b0; - else if (icache_restart_request == 1'b1) - valid_a = 1'b1; - else - valid_a = !icache_refilling; -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - valid_f <= 1'b0; - valid_d <= 1'b0; - valid_x <= 1'b0; - valid_m <= 1'b0; - valid_w <= 1'b0; + case (csr) + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + + eie, + ie + }; + 4 'h2: csr_read_data = ip; + 4 'h1: csr_read_data = im; + default: csr_read_data = { 32{1'bx}}; + endcase +end end else - begin - if ((kill_f == 1'b1) || (stall_a == 1'b0)) - valid_f <= valid_a; - else if (stall_f == 1'b0) - valid_f <= 1'b0; - if (kill_d == 1'b1) - valid_d <= 1'b0; - else if (stall_f == 1'b0) - valid_d <= valid_f & !kill_f; - else if (stall_d == 1'b0) - valid_d <= 1'b0; - if (stall_d == 1'b0) - valid_x <= valid_d & !kill_d; - else if (kill_x == 1'b1) - valid_x <= 1'b0; - else if (stall_x == 1'b0) - valid_x <= 1'b0; - if (kill_m == 1'b1) - valid_m <= 1'b0; - else if (stall_x == 1'b0) - valid_m <= valid_x & !kill_x; - else if (stall_m == 1'b0) - valid_m <= 1'b0; - if (stall_m == 1'b0) - valid_w <= valid_m & !kill_m; - else - valid_w <= 1'b0; - end + begin + +always @(*) +begin + case (csr) + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + + eie, + ie + }; + 4 'h2: csr_read_data = ip; + default: csr_read_data = { 32{1'bx}}; + endcase end + end +endgenerate + + + + + + + + reg [ 10:0] eie_delay = 0; + + +generate + + + if (interrupts > 1) + begin + always @(posedge clk_i ) -begin + begin if (rst_i == 1'b1) begin - operand_0_x <= { 32{1'b0}}; - operand_1_x <= { 32{1'b0}}; - store_operand_x <= { 32{1'b0}}; - branch_target_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - x_result_sel_csr_x <= 1'b0; - x_result_sel_sext_x <= 1'b0; - x_result_sel_add_x <= 1'b0; - m_result_sel_compare_x <= 1'b0; - m_result_sel_shift_x <= 1'b0; - w_result_sel_load_x <= 1'b0; - w_result_sel_mul_x <= 1'b0; - x_bypass_enable_x <= 1'b0; - m_bypass_enable_x <= 1'b0; - write_enable_x <= 1'b0; - write_idx_x <= { 5{1'b0}}; - csr_x <= { 5{1'b0}}; - load_x <= 1'b0; - store_x <= 1'b0; - size_x <= { 2{1'b0}}; - sign_extend_x <= 1'b0; - adder_op_x <= 1'b0; - adder_op_x_n <= 1'b0; - logic_op_x <= 4'h0; - direction_x <= 1'b0; - branch_x <= 1'b0; - branch_predict_x <= 1'b0; - branch_predict_taken_x <= 1'b0; - condition_x <= 3'b000; - break_x <= 1'b0; - scall_x <= 1'b0; - eret_x <= 1'b0; - bret_x <= 1'b0; - csr_write_enable_x <= 1'b0; - operand_m <= { 32{1'b0}}; - branch_target_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - m_result_sel_compare_m <= 1'b0; - m_result_sel_shift_m <= 1'b0; - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; - m_bypass_enable_m <= 1'b0; - branch_m <= 1'b0; - branch_predict_m <= 1'b0; - branch_predict_taken_m <= 1'b0; - exception_m <= 1'b0; - load_m <= 1'b0; - store_m <= 1'b0; - write_enable_m <= 1'b0; - write_idx_m <= { 5{1'b0}}; - condition_met_m <= 1'b0; - debug_exception_m <= 1'b0; - non_debug_exception_m <= 1'b0; - operand_w <= { 32{1'b0}}; - w_result_sel_load_w <= 1'b0; - w_result_sel_mul_w <= 1'b0; - write_idx_w <= { 5{1'b0}}; - write_enable_w <= 1'b0; - debug_exception_w <= 1'b0; - non_debug_exception_w <= 1'b0; + ie <= 1'b0; + eie <= 1'b0; + + + + + im <= {interrupts{1'b0}}; + ip <= {interrupts{1'b0}}; + eie_delay <= 0; + end else begin - if (stall_x == 1'b0) + + ip <= asserted; + + + + + + + + + + + + + + + + if (exception == 1'b1) begin - operand_0_x <= d_result_0; - operand_1_x <= d_result_1; - store_operand_x <= bypass_data_1; - branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] : branch_target_d; - x_result_sel_csr_x <= x_result_sel_csr_d; - x_result_sel_sext_x <= x_result_sel_sext_d; - x_result_sel_add_x <= x_result_sel_add_d; - m_result_sel_compare_x <= m_result_sel_compare_d; - m_result_sel_shift_x <= m_result_sel_shift_d; - w_result_sel_load_x <= w_result_sel_load_d; - w_result_sel_mul_x <= w_result_sel_mul_d; - x_bypass_enable_x <= x_bypass_enable_d; - m_bypass_enable_x <= m_bypass_enable_d; - load_x <= load_d; - store_x <= store_d; - branch_x <= branch_d; - branch_predict_x <= branch_predict_d; - branch_predict_taken_x <= branch_predict_taken_d; - write_idx_x <= write_idx_d; - csr_x <= csr_d; - size_x <= size_d; - sign_extend_x <= sign_extend_d; - adder_op_x <= adder_op_d; - adder_op_x_n <= ~adder_op_d; - logic_op_x <= logic_op_d; - direction_x <= direction_d; - condition_x <= condition_d; - csr_write_enable_x <= csr_write_enable_d; - break_x <= break_d; - scall_x <= scall_d; - eret_x <= eret_d; - bret_x <= bret_d; - write_enable_x <= write_enable_d; + + eie <= ie; + ie <= 1'b0; end - if (stall_m == 1'b0) + + + else if (stall_x == 1'b0) begin - operand_m <= x_result; - m_result_sel_compare_m <= m_result_sel_compare_x; - m_result_sel_shift_m <= m_result_sel_shift_x; - if (exception_x == 1'b1) - begin - w_result_sel_load_m <= 1'b0; - w_result_sel_mul_m <= 1'b0; + + if(eie_delay[0]) + ie <= eie; + + eie_delay <= {1'b0, eie_delay[ 10:1]}; + + if (eret_q_x == 1'b1) begin + + eie_delay[ 10] <= 1'b1; + eie_delay[ 10-1:0] <= 0; end - else + + + + + + + + + + else if (csr_write_enable == 1'b1) begin - w_result_sel_load_m <= w_result_sel_load_x; - w_result_sel_mul_m <= w_result_sel_mul_x; + + if (csr == 4 'h0) + begin + ie <= csr_write_data[0]; + eie <= csr_write_data[1]; + + + + + end + if (csr == 4 'h1) + im <= csr_write_data[interrupts-1:0]; + if (csr == 4 'h2) + ip <= asserted & ~csr_write_data[interrupts-1:0]; end - m_bypass_enable_m <= m_bypass_enable_x; - load_m <= load_x; - store_m <= store_x; - branch_m <= branch_x; - branch_predict_m <= branch_predict_x; - branch_predict_taken_m <= branch_predict_taken_x; - if (non_debug_exception_x == 1'b1) - write_idx_m <= 5'd30; - else if (debug_exception_x == 1'b1) - write_idx_m <= 5'd31; - else - write_idx_m <= write_idx_x; - condition_met_m <= condition_met_x; - if (exception_x == 1'b1) - if ((dc_re == 1'b1) - || ((debug_exception_x == 1'b1) - && (non_debug_exception_x == 1'b0))) - branch_target_m <= {deba, eid_x, {3{1'b0}}}; - else - branch_target_m <= {eba, eid_x, {3{1'b0}}}; - else - branch_target_m <= branch_target_x; - write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; - debug_exception_m <= debug_exception_x; - non_debug_exception_m <= non_debug_exception_x; end - if (stall_m == 1'b0) + end +end + end +else + begin + +always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + ie <= 1'b0; + eie <= 1'b0; + + + + + ip <= {interrupts{1'b0}}; + eie_delay <= 0; + end + else + begin + + ip <= asserted; + + + + + + + + + + + + + + + + if (exception == 1'b1) begin - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - exception_m <= 1'b1; - else - exception_m <= 1'b0; - end - operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; - w_result_sel_load_w <= w_result_sel_load_m; - w_result_sel_mul_w <= w_result_sel_mul_m; - write_idx_w <= write_idx_m; - write_enable_w <= write_enable_m; - debug_exception_w <= debug_exception_m; - non_debug_exception_w <= non_debug_exception_m; + + eie <= ie; + ie <= 1'b0; + end + + + else if (stall_x == 1'b0) + begin + + if(eie_delay[0]) + ie <= eie; + + eie_delay <= {1'b0, eie_delay[ 10:1]}; + + if (eret_q_x == 1'b1) begin + + eie_delay[ 10] <= 1'b1; + eie_delay[ 10-1:0] <= 0; + end + + + + + + + + else if (csr_write_enable == 1'b1) + begin + + if (csr == 4 'h0) + begin + ie <= csr_write_data[0]; + eie <= csr_write_data[1]; + + + + + end + if (csr == 4 'h2) + ip <= asserted & ~csr_write_data[interrupts-1:0]; + end + end + end +end end +endgenerate + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_minimal ( + + clk_i, + rst_i, + + + interrupt, + + + + + + + + + + + I_DAT_I, + I_ACK_I, + I_ERR_I, + I_RTY_I, + + + + D_DAT_I, + D_ACK_I, + D_ERR_I, + D_RTY_I, + + + + + + + + + + + + I_DAT_O, + I_ADR_O, + I_CYC_O, + I_SEL_O, + I_STB_O, + I_WE_O, + I_CTI_O, + I_LOCK_O, + I_BTE_O, + + + + D_DAT_O, + D_ADR_O, + D_CYC_O, + D_SEL_O, + D_STB_O, + D_WE_O, + D_CTI_O, + D_LOCK_O, + D_BTE_O + ); + +parameter eba_reset = 32'h00000000; +parameter sdb_address = 32'h00000000; + + + + +input clk_i; +input rst_i; + + +input [ (32-1):0] interrupt; + + + + + + + + + + +input [ (32-1):0] I_DAT_I; +input I_ACK_I; +input I_ERR_I; +input I_RTY_I; + + + +input [ (32-1):0] D_DAT_I; +input D_ACK_I; +input D_ERR_I; +input D_RTY_I; + + + + + + + + + + + + + + + + + + + +output [ (32-1):0] I_DAT_O; +wire [ (32-1):0] I_DAT_O; +output [ (32-1):0] I_ADR_O; +wire [ (32-1):0] I_ADR_O; +output I_CYC_O; +wire I_CYC_O; +output [ (4-1):0] I_SEL_O; +wire [ (4-1):0] I_SEL_O; +output I_STB_O; +wire I_STB_O; +output I_WE_O; +wire I_WE_O; +output [ (3-1):0] I_CTI_O; +wire [ (3-1):0] I_CTI_O; +output I_LOCK_O; +wire I_LOCK_O; +output [ (2-1):0] I_BTE_O; +wire [ (2-1):0] I_BTE_O; + + + +output [ (32-1):0] D_DAT_O; +wire [ (32-1):0] D_DAT_O; +output [ (32-1):0] D_ADR_O; +wire [ (32-1):0] D_ADR_O; +output D_CYC_O; +wire D_CYC_O; +output [ (4-1):0] D_SEL_O; +wire [ (4-1):0] D_SEL_O; +output D_STB_O; +wire D_STB_O; +output D_WE_O; +wire D_WE_O; +output [ (3-1):0] D_CTI_O; +wire [ (3-1):0] D_CTI_O; +output D_LOCK_O; +wire D_LOCK_O; +output [ (2-1):0] D_BTE_O; +wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; +begin + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; +end +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; +begin + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; end +endfunction + + + + + + + + +lm32_cpu_minimal + #( + .eba_reset(eba_reset), + .sdb_address(sdb_address) + ) cpu ( + + .clk_i (clk_i), + + + + + .rst_i (rst_i), + + + + .interrupt (interrupt), + + + + + + + + + + + + + + + + + + + + .I_DAT_I (I_DAT_I), + .I_ACK_I (I_ACK_I), + .I_ERR_I (I_ERR_I), + .I_RTY_I (I_RTY_I), + + + + .D_DAT_I (D_DAT_I), + .D_ACK_I (D_ACK_I), + .D_ERR_I (D_ERR_I), + .D_RTY_I (D_RTY_I), + + + + + + + + + + + + + + + + + + + + + + + + + + + + .I_DAT_O (I_DAT_O), + .I_ADR_O (I_ADR_O), + .I_CYC_O (I_CYC_O), + .I_SEL_O (I_SEL_O), + .I_STB_O (I_STB_O), + .I_WE_O (I_WE_O), + .I_CTI_O (I_CTI_O), + .I_LOCK_O (I_LOCK_O), + .I_BTE_O (I_BTE_O), + + + + .D_DAT_O (D_DAT_O), + .D_ADR_O (D_ADR_O), + .D_CYC_O (D_CYC_O), + .D_SEL_O (D_SEL_O), + .D_STB_O (D_STB_O), + .D_WE_O (D_WE_O), + .D_CTI_O (D_CTI_O), + .D_LOCK_O (D_LOCK_O), + .D_BTE_O (D_BTE_O) + ); + + + + + + + + + + + + + + + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_minimal ( + + clk_i, + rst_i, + stall_d, + kill_x, + + + + + + + + + + + + + + + + operand_0_d, + operand_1_d, + + result_x, + + + + + stall_request_x + ); + + + + + +input clk_i; +input rst_i; +input stall_d; +input kill_x; + + + + + + + + + + + + + + + +input [ (32-1):0] operand_0_d; +input [ (32-1):0] operand_1_d; + + + + + +output [ (32-1):0] result_x; +reg [ (32-1):0] result_x; + + + + + +output stall_request_x; +wire stall_request_x; + + + + + +reg [ (32-1):0] p; +reg [ (32-1):0] a; +reg [ (32-1):0] b; + + + + + +reg [ 2:0] state; +reg [5:0] cycles; + + + + + + + + + + + + +assign stall_request_x = state != 3'b000; + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - use_buf <= 1'b0; - reg_data_buf_0 <= { 32{1'b0}}; - reg_data_buf_1 <= { 32{1'b0}}; + cycles <= {6{1'b0}}; + p <= { 32{1'b0}}; + a <= { 32{1'b0}}; + b <= { 32{1'b0}}; + + + + + + + + + result_x <= { 32{1'b0}}; + state <= 3'b000; end else begin - if (stall_d == 1'b0) - use_buf <= 1'b0; - else if (use_buf == 1'b0) - begin - reg_data_buf_0 <= reg_data_live_0; - reg_data_buf_1 <= reg_data_live_1; - use_buf <= 1'b1; - end - if (reg_write_enable_q_w == 1'b1) + + + + + case (state) + 3'b000: begin - if (write_idx_w == read_idx_0_d) - reg_data_buf_0 <= w_result; - if (write_idx_w == read_idx_1_d) - reg_data_buf_1 <= w_result; + if (stall_d == 1'b0) + begin + cycles <= 32; + p <= 32'b0; + a <= operand_0_d; + b <= operand_1_d; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end -end -initial -begin -end -endmodule -module lm32_load_store_unit_medium_icache_debug ( +end + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_minimal ( + clk_i, + + + + rst_i, - stall_a, - stall_x, - stall_m, - kill_x, - kill_m, - exception_m, - store_operand_x, - load_store_address_x, - load_store_address_m, - load_store_address_w, - load_x, - store_x, - load_q_x, - store_q_x, - load_q_m, - store_q_m, - sign_extend_x, - size_x, - d_dat_i, - d_ack_i, - d_err_i, - d_rty_i, - load_data_w, - stall_wb_load, - d_dat_o, - d_adr_o, - d_cyc_o, - d_sel_o, - d_stb_o, - d_we_o, - d_cti_o, - d_lock_o, - d_bte_o + + + + interrupt, + + + + + + + + + + + + + + + + + + + + I_DAT_I, + I_ACK_I, + I_ERR_I, + I_RTY_I, + + + + D_DAT_I, + D_ACK_I, + D_ERR_I, + D_RTY_I, + + + + + + + + + + + + + + + + + + + + + + + + + + + + I_DAT_O, + I_ADR_O, + I_CYC_O, + I_SEL_O, + I_STB_O, + I_WE_O, + I_CTI_O, + I_LOCK_O, + I_BTE_O, + + + + + + + + + + + + + + + + + + D_DAT_O, + D_ADR_O, + D_CYC_O, + D_SEL_O, + D_STB_O, + D_WE_O, + D_CTI_O, + D_LOCK_O, + D_BTE_O + + ); -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_x; -input stall_m; -input kill_x; -input kill_m; -input exception_m; -input [ (32-1):0] store_operand_x; -input [ (32-1):0] load_store_address_x; -input [ (32-1):0] load_store_address_m; -input [1:0] load_store_address_w; -input load_x; -input store_x; -input load_q_x; -input store_q_x; -input load_q_m; -input store_q_m; -input sign_extend_x; -input [ 1:0] size_x; -input [ (32-1):0] d_dat_i; -input d_ack_i; -input d_err_i; -input d_rty_i; -output [ (32-1):0] load_data_w; -reg [ (32-1):0] load_data_w; -output stall_wb_load; -reg stall_wb_load; -output [ (32-1):0] d_dat_o; -reg [ (32-1):0] d_dat_o; -output [ (32-1):0] d_adr_o; -reg [ (32-1):0] d_adr_o; -output d_cyc_o; -reg d_cyc_o; -output [ (4-1):0] d_sel_o; -reg [ (4-1):0] d_sel_o; -output d_stb_o; -reg d_stb_o; -output d_we_o; -reg d_we_o; -output [ (3-1):0] d_cti_o; -reg [ (3-1):0] d_cti_o; -output d_lock_o; -reg d_lock_o; -output [ (2-1):0] d_bte_o; -wire [ (2-1):0] d_bte_o; -reg [ 1:0] size_m; -reg [ 1:0] size_w; -reg sign_extend_m; -reg sign_extend_w; -reg [ (32-1):0] store_data_x; -reg [ (32-1):0] store_data_m; -reg [ (4-1):0] byte_enable_x; -reg [ (4-1):0] byte_enable_m; -wire [ (32-1):0] data_m; -reg [ (32-1):0] data_w; -wire wb_select_x; -reg wb_select_m; -reg [ (32-1):0] wb_data_m; -reg wb_load_complete; + + + + + +parameter eba_reset = 32'h00000000; + + + + +parameter sdb_address = 32'h00000000; + + + + + + + + + +parameter icache_associativity = 1; +parameter icache_sets = 512; +parameter icache_bytes_per_line = 16; +parameter icache_base_address = 0; +parameter icache_limit = 0; + + + + + + + + + + + +parameter dcache_associativity = 1; +parameter dcache_sets = 512; +parameter dcache_bytes_per_line = 16; +parameter dcache_base_address = 0; +parameter dcache_limit = 0; + + + + + + + +parameter watchpoints = 0; + + + + + + +parameter breakpoints = 0; + + + + + +parameter interrupts = 32; + + + + + + + + + +input clk_i; + + + + +input rst_i; + + + +input [ (32-1):0] interrupt; + + + + + + + + + + + + + + + + + + + +input [ (32-1):0] I_DAT_I; +input I_ACK_I; +input I_ERR_I; +input I_RTY_I; + + + +input [ (32-1):0] D_DAT_I; +input D_ACK_I; +input D_ERR_I; +input D_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +output [ (32-1):0] I_DAT_O; +wire [ (32-1):0] I_DAT_O; +output [ (32-1):0] I_ADR_O; +wire [ (32-1):0] I_ADR_O; +output I_CYC_O; +wire I_CYC_O; +output [ (4-1):0] I_SEL_O; +wire [ (4-1):0] I_SEL_O; +output I_STB_O; +wire I_STB_O; +output I_WE_O; +wire I_WE_O; +output [ (3-1):0] I_CTI_O; +wire [ (3-1):0] I_CTI_O; +output I_LOCK_O; +wire I_LOCK_O; +output [ (2-1):0] I_BTE_O; +wire [ (2-1):0] I_BTE_O; + + + +output [ (32-1):0] D_DAT_O; +wire [ (32-1):0] D_DAT_O; +output [ (32-1):0] D_ADR_O; +wire [ (32-1):0] D_ADR_O; +output D_CYC_O; +wire D_CYC_O; +output [ (4-1):0] D_SEL_O; +wire [ (4-1):0] D_SEL_O; +output D_STB_O; +wire D_STB_O; +output D_WE_O; +wire D_WE_O; +output [ (3-1):0] D_CTI_O; +wire [ (3-1):0] D_CTI_O; +output D_LOCK_O; +wire D_LOCK_O; +output [ (2-1):0] D_BTE_O; +wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + + + +reg valid_f; +reg valid_d; +reg valid_x; +reg valid_m; +reg valid_w; + +wire q_x; +wire [ (32-1):0] immediate_d; +wire load_d; +reg load_x; +reg load_m; +wire load_q_x; +wire store_q_x; +wire q_m; +wire load_q_m; +wire store_q_m; +wire store_d; +reg store_x; +reg store_m; +wire [ 1:0] size_d; +reg [ 1:0] size_x; +wire branch_d; +wire branch_predict_d; +wire branch_predict_taken_d; +wire [ ((32-2)+2-1):2] branch_predict_address_d; +wire [ ((32-2)+2-1):2] branch_target_d; +wire bi_unconditional; +wire bi_conditional; +reg branch_x; +reg branch_predict_x; +reg branch_predict_taken_x; +reg branch_m; +reg branch_predict_m; +reg branch_predict_taken_m; +wire branch_mispredict_taken_m; +wire branch_flushX_m; +wire branch_reg_d; +wire [ ((32-2)+2-1):2] branch_offset_d; +reg [ ((32-2)+2-1):2] branch_target_x; +reg [ ((32-2)+2-1):2] branch_target_m; +wire [ 0:0] d_result_sel_0_d; +wire [ 1:0] d_result_sel_1_d; + +wire x_result_sel_csr_d; +reg x_result_sel_csr_x; + + + + + + + + +wire x_result_sel_shift_d; +reg x_result_sel_shift_x; + + + + + + + +wire x_result_sel_logic_d; + + + + + +wire x_result_sel_add_d; +reg x_result_sel_add_x; +wire m_result_sel_compare_d; +reg m_result_sel_compare_x; +reg m_result_sel_compare_m; + + + + + + +wire w_result_sel_load_d; +reg w_result_sel_load_x; +reg w_result_sel_load_m; +reg w_result_sel_load_w; + + + + + + + +wire x_bypass_enable_d; +reg x_bypass_enable_x; +wire m_bypass_enable_d; +reg m_bypass_enable_x; +reg m_bypass_enable_m; +wire sign_extend_d; +reg sign_extend_x; +wire write_enable_d; +reg write_enable_x; +wire write_enable_q_x; +reg write_enable_m; +wire write_enable_q_m; +reg write_enable_w; +wire write_enable_q_w; +wire read_enable_0_d; +wire [ (5-1):0] read_idx_0_d; +wire read_enable_1_d; +wire [ (5-1):0] read_idx_1_d; +wire [ (5-1):0] write_idx_d; +reg [ (5-1):0] write_idx_x; +reg [ (5-1):0] write_idx_m; +reg [ (5-1):0] write_idx_w; +wire [ (4 -1):0] csr_d; +reg [ (4 -1):0] csr_x; +wire [ (3-1):0] condition_d; +reg [ (3-1):0] condition_x; + + + + + +wire scall_d; +reg scall_x; +wire eret_d; +reg eret_x; +wire eret_q_x; + + + + + + + + + + + + + + + +wire csr_write_enable_d; +reg csr_write_enable_x; +wire csr_write_enable_q_x; + + + + + + + + + + + + + +reg [ (32-1):0] d_result_0; +reg [ (32-1):0] d_result_1; +reg [ (32-1):0] x_result; +reg [ (32-1):0] m_result; +reg [ (32-1):0] w_result; + +reg [ (32-1):0] operand_0_x; +reg [ (32-1):0] operand_1_x; +reg [ (32-1):0] store_operand_x; +reg [ (32-1):0] operand_m; +reg [ (32-1):0] operand_w; + + + + +reg [ (32-1):0] reg_data_live_0; +reg [ (32-1):0] reg_data_live_1; +reg use_buf; +reg [ (32-1):0] reg_data_buf_0; +reg [ (32-1):0] reg_data_buf_1; + + + + + + + + +wire [ (32-1):0] reg_data_0; +wire [ (32-1):0] reg_data_1; +reg [ (32-1):0] bypass_data_0; +reg [ (32-1):0] bypass_data_1; +wire reg_write_enable_q_w; + +reg interlock; + +wire stall_a; +wire stall_f; +wire stall_d; +wire stall_x; +wire stall_m; + + +wire adder_op_d; +reg adder_op_x; +reg adder_op_x_n; +wire [ (32-1):0] adder_result_x; +wire adder_overflow_x; +wire adder_carry_n_x; + + +wire [ 3:0] logic_op_d; +reg [ 3:0] logic_op_x; +wire [ (32-1):0] logic_result_x; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +wire [ (32-1):0] shifter_result_x; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +wire [ (32-1):0] interrupt_csr_read_data_x; + + +wire [ (32-1):0] cfg; +wire [ (32-1):0] cfg2; + + + + +reg [ (32-1):0] csr_read_data_x; + + +wire [ ((32-2)+2-1):2] pc_f; +wire [ ((32-2)+2-1):2] pc_d; +wire [ ((32-2)+2-1):2] pc_x; +wire [ ((32-2)+2-1):2] pc_m; +wire [ ((32-2)+2-1):2] pc_w; + + + + + + +wire [ (32-1):0] instruction_f; + + + + +wire [ (32-1):0] instruction_d; + + + + + + + + + + + + + + + + + + + +wire [ (32-1):0] load_data_w; +wire stall_wb_load; + + + + + + + + + + + + + + + + + + + + + + + + + +wire raw_x_0; +wire raw_x_1; +wire raw_m_0; +wire raw_m_1; +wire raw_w_0; +wire raw_w_1; + + +wire cmp_zero; +wire cmp_negative; +wire cmp_overflow; +wire cmp_carry_n; +reg condition_met_x; +reg condition_met_m; + + + + +wire branch_taken_m; + +wire kill_f; +wire kill_d; +wire kill_x; +wire kill_m; +wire kill_w; + +reg [ (32-2)+2-1:8] eba; + + + + +reg [ (3-1):0] eid_x; + + + + + + + + + + + + + + + + + + + + + + + + + +wire exception_x; +reg exception_m; +reg exception_w; +wire exception_q_w; + + + + + + + + + + + +wire interrupt_exception; + + + + + + + + + + + + + + + + +wire system_call_exception; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -16980,6 +79038,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -16992,836 +79051,2891 @@ begin clogb2_v1 = i-1; end endfunction - assign wb_select_x = 1'b1 - ; -always @(*) -begin - case (size_x) - 2'b00: store_data_x = {4{store_operand_x[7:0]}}; - 2'b11: store_data_x = {2{store_operand_x[15:0]}}; - 2'b10: store_data_x = store_operand_x; - default: store_data_x = { 32{1'bx}}; - endcase -end -always @(*) -begin - casez ({size_x, load_store_address_x[1:0]}) - { 2'b00, 2'b11}: byte_enable_x = 4'b0001; - { 2'b00, 2'b10}: byte_enable_x = 4'b0010; - { 2'b00, 2'b01}: byte_enable_x = 4'b0100; - { 2'b00, 2'b00}: byte_enable_x = 4'b1000; - { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; - { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; - { 2'b10, 2'b??}: byte_enable_x = 4'b1111; - default: byte_enable_x = 4'bxxxx; - endcase -end - assign data_m = wb_data_m; + + + + + + + + + +lm32_instruction_unit_minimal #( + .eba_reset (eba_reset), + .associativity (icache_associativity), + .sets (icache_sets), + .bytes_per_line (icache_bytes_per_line), + .base_address (icache_base_address), + .limit (icache_limit) + ) instruction_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_f (stall_f), + .stall_d (stall_d), + .stall_x (stall_x), + .stall_m (stall_m), + .valid_f (valid_f), + .valid_d (valid_d), + .kill_f (kill_f), + .branch_predict_taken_d (branch_predict_taken_d), + .branch_predict_address_d (branch_predict_address_d), + + + + + + .exception_m (exception_m), + .branch_taken_m (branch_taken_m), + .branch_mispredict_taken_m (branch_mispredict_taken_m), + .branch_target_m (branch_target_m), + + + + + + + + + + + + + + .i_dat_i (I_DAT_I), + .i_ack_i (I_ACK_I), + .i_err_i (I_ERR_I), + .i_rty_i (I_RTY_I), + + + + + + + + + + + + .pc_f (pc_f), + .pc_d (pc_d), + .pc_x (pc_x), + .pc_m (pc_m), + .pc_w (pc_w), + + + + + + + + + + + .i_dat_o (I_DAT_O), + .i_adr_o (I_ADR_O), + .i_cyc_o (I_CYC_O), + .i_sel_o (I_SEL_O), + .i_stb_o (I_STB_O), + .i_we_o (I_WE_O), + .i_cti_o (I_CTI_O), + .i_lock_o (I_LOCK_O), + .i_bte_o (I_BTE_O), + + + + + + + + + + + + + + + + + + + + + + .instruction_f (instruction_f), + + + + + .instruction_d (instruction_d) + + + + ); + + +lm32_decoder_minimal decoder ( + + .instruction (instruction_d), + + .d_result_sel_0 (d_result_sel_0_d), + .d_result_sel_1 (d_result_sel_1_d), + .x_result_sel_csr (x_result_sel_csr_d), + + + + + + + .x_result_sel_shift (x_result_sel_shift_d), + + + + + + + .x_result_sel_logic (x_result_sel_logic_d), + + + + + .x_result_sel_add (x_result_sel_add_d), + .m_result_sel_compare (m_result_sel_compare_d), + + + + + .w_result_sel_load (w_result_sel_load_d), + + + + + .x_bypass_enable (x_bypass_enable_d), + .m_bypass_enable (m_bypass_enable_d), + .read_enable_0 (read_enable_0_d), + .read_idx_0 (read_idx_0_d), + .read_enable_1 (read_enable_1_d), + .read_idx_1 (read_idx_1_d), + .write_enable (write_enable_d), + .write_idx (write_idx_d), + .immediate (immediate_d), + .branch_offset (branch_offset_d), + .load (load_d), + .store (store_d), + .size (size_d), + .sign_extend (sign_extend_d), + .adder_op (adder_op_d), + .logic_op (logic_op_d), + + + + + + + + + + + + + + + + + + + .branch (branch_d), + .bi_unconditional (bi_unconditional), + .bi_conditional (bi_conditional), + .branch_reg (branch_reg_d), + .condition (condition_d), + + + + + .scall (scall_d), + .eret (eret_d), + + + + + + + + + .csr_write_enable (csr_write_enable_d) + ); + + +lm32_load_store_unit_minimal #( + .associativity (dcache_associativity), + .sets (dcache_sets), + .bytes_per_line (dcache_bytes_per_line), + .base_address (dcache_base_address), + .limit (dcache_limit) + ) load_store_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .stall_a (stall_a), + .stall_x (stall_x), + .stall_m (stall_m), + .kill_x (kill_x), + .kill_m (kill_m), + .exception_m (exception_m), + .store_operand_x (store_operand_x), + .load_store_address_x (adder_result_x), + .load_store_address_m (operand_m), + .load_store_address_w (operand_w[1:0]), + .load_x (load_x), + .store_x (store_x), + .load_q_x (load_q_x), + .store_q_x (store_q_x), + .load_q_m (load_q_m), + .store_q_m (store_q_m), + .sign_extend_x (sign_extend_x), + .size_x (size_x), + + + + + + + + + + + + + + + + + + .d_dat_i (D_DAT_I), + .d_ack_i (D_ACK_I), + .d_err_i (D_ERR_I), + .d_rty_i (D_RTY_I), + + + + + + + + + + .load_data_w (load_data_w), + .stall_wb_load (stall_wb_load), + + .d_dat_o (D_DAT_O), + .d_adr_o (D_ADR_O), + .d_cyc_o (D_CYC_O), + .d_sel_o (D_SEL_O), + .d_stb_o (D_STB_O), + .d_we_o (D_WE_O), + .d_cti_o (D_CTI_O), + .d_lock_o (D_LOCK_O), + .d_bte_o (D_BTE_O) + ); + + +lm32_adder adder ( + + .adder_op_x (adder_op_x), + .adder_op_x_n (adder_op_x_n), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .adder_result_x (adder_result_x), + .adder_carry_n_x (adder_carry_n_x), + .adder_overflow_x (adder_overflow_x) + ); + + +lm32_logic_op logic_op ( + + .logic_op_x (logic_op_x), + .operand_0_x (operand_0_x), + + .operand_1_x (operand_1_x), + + .logic_result_x (logic_result_x) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +lm32_interrupt_minimal interrupt_unit ( + + .clk_i (clk_i), + .rst_i (rst_i), + + .interrupt (interrupt), + + .stall_x (stall_x), + + + + + + .exception (exception_q_w), + + + .eret_q_x (eret_q_x), + + + + + .csr (csr_x), + .csr_write_data (operand_1_x), + .csr_write_enable (csr_write_enable_q_x), + + .interrupt_exception (interrupt_exception), + + .csr_read_data (interrupt_csr_read_data_x) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; + reg [31:0] w_result_d; + reg regfile_raw_0, regfile_raw_0_nxt; + reg regfile_raw_1, regfile_raw_1_nxt; + + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) + begin + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[25:21])) + regfile_raw_0_nxt = 1'b1; + else + regfile_raw_0_nxt = 1'b0; + + if (reg_write_enable_q_w + && (write_idx_w == instruction_f[20:16])) + regfile_raw_1_nxt = 1'b1; + else + regfile_raw_1_nxt = 1'b0; + end + + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) + if (regfile_raw_0) + reg_data_live_0 = w_result_d; + else + reg_data_live_0 = regfile_data_0; + + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) + if (regfile_raw_1) + reg_data_live_1 = w_result_d; + else + reg_data_live_1 = regfile_data_1; + + + + + always @(posedge clk_i ) + if (rst_i == 1'b1) + begin + regfile_raw_0 <= 1'b0; + regfile_raw_1 <= 1'b0; + w_result_d <= 32'b0; + end + else + begin + regfile_raw_0 <= regfile_raw_0_nxt; + regfile_raw_1 <= regfile_raw_1_nxt; + w_result_d <= w_result; + end + + + + + + lm32_dp_ram + #( + + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_0 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[25:21]), + + .rdata_o (regfile_data_0) + ); + + lm32_dp_ram + #( + .addr_depth(1<<5), + .addr_width(5), + .data_width(32) + ) + reg_1 + ( + + .clk_i (clk_i), + .rst_i (rst_i), + .we_i (reg_write_enable_q_w), + .wdata_i (w_result), + .waddr_i (write_idx_w), + .raddr_i (instruction_f[20:16]), + + .rdata_o (regfile_data_1) + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; +assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + +assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); +assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); +assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); +assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); +assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); +assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + always @(*) begin - casez ({size_w, load_store_address_w[1:0]}) - { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; - { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; - { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; - { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; - { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; - { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; - { 2'b10, 2'b??}: load_data_w = data_w; - default: load_data_w = { 32{1'bx}}; - endcase -end -assign d_bte_o = 2'b00; -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_dat_o <= { 32{1'b0}}; - d_adr_o <= { 32{1'b0}}; - d_sel_o <= { 4{ 1'b0}}; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; - d_lock_o <= 1'b0; - wb_data_m <= { 32{1'b0}}; - wb_load_complete <= 1'b0; - stall_wb_load <= 1'b0; - end + if ( ( (x_bypass_enable_x == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_x_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_x_1 == 1'b1)) + ) + ) + || ( (m_bypass_enable_m == 1'b0) + && ( ((read_enable_0_d == 1'b1) && (raw_m_0 == 1'b1)) + || ((read_enable_1_d == 1'b1) && (raw_m_1 == 1'b1)) + ) + ) + ) + interlock = 1'b1; else - begin - if (d_cyc_o == 1'b1) - begin - if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) - begin - begin - d_cyc_o <= 1'b0; - d_stb_o <= 1'b0; - d_lock_o <= 1'b0; - end - wb_data_m <= d_dat_i; - wb_load_complete <= !d_we_o; - end - if (d_err_i == 1'b1) - $display ("Data bus error. Address: %x", d_adr_o); - end - else - begin - if ( (store_q_m == 1'b1) - && (stall_m == 1'b0) - ) - begin - d_dat_o <= store_data_m; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b1; - d_cti_o <= 3'b111; - end - else if ( (load_q_m == 1'b1) - && (wb_select_m == 1'b1) - && (wb_load_complete == 1'b0) - ) - begin - stall_wb_load <= 1'b0; - d_adr_o <= load_store_address_m; - d_cyc_o <= 1'b1; - d_sel_o <= byte_enable_m; - d_stb_o <= 1'b1; - d_we_o <= 1'b0; - d_cti_o <= 3'b111; - end - end - if (stall_m == 1'b0) - wb_load_complete <= 1'b0; - if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) - stall_wb_load <= 1'b1; - if ((kill_m == 1'b1) || (exception_m == 1'b1)) - stall_wb_load <= 1'b0; - end + interlock = 1'b0; end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - sign_extend_m <= 1'b0; - size_m <= 2'b00; - byte_enable_m <= 1'b0; - store_data_m <= { 32{1'b0}}; - wb_select_m <= 1'b0; - end - else - begin - if (stall_m == 1'b0) - begin - sign_extend_m <= sign_extend_x; - size_m <= size_x; - byte_enable_m <= byte_enable_x; - store_data_m <= store_data_x; - wb_select_m <= wb_select_x; - end - end + + +always @(*) +begin + if (raw_x_0 == 1'b1) + bypass_data_0 = x_result; + else if (raw_m_0 == 1'b1) + bypass_data_0 = m_result; + else if (raw_w_0 == 1'b1) + bypass_data_0 = w_result; + else + bypass_data_0 = reg_data_0; end -always @(posedge clk_i ) + + +always @(*) begin - if (rst_i == 1'b1) - begin - size_w <= 2'b00; - data_w <= { 32{1'b0}}; - sign_extend_w <= 1'b0; - end + if (raw_x_1 == 1'b1) + bypass_data_1 = x_result; + else if (raw_m_1 == 1'b1) + bypass_data_1 = m_result; + else if (raw_w_1 == 1'b1) + bypass_data_1 = w_result; else - begin - size_w <= size_m; - data_w <= data_m; - sign_extend_w <= sign_extend_m; - end + bypass_data_1 = reg_data_1; end -always @(posedge clk_i) + + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; + assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + + assign branch_target_d = pc_d + branch_offset_d; + + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + +always @(*) begin - if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) - begin - if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) - $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); - if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) - $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); - end + d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; + case (d_result_sel_1_d) + 2'b00: d_result_1 = { 32{1'b0}}; + 2'b01: d_result_1 = bypass_data_1; + 2'b10: d_result_1 = immediate_d; + default: d_result_1 = { 32{1'bx}}; + endcase end -endmodule -module lm32_decoder_medium_icache_debug ( - instruction, - d_result_sel_0, - d_result_sel_1, - x_result_sel_csr, - x_result_sel_sext, - x_result_sel_logic, - x_result_sel_add, - m_result_sel_compare, - m_result_sel_shift, - w_result_sel_load, - w_result_sel_mul, - x_bypass_enable, - m_bypass_enable, - read_enable_0, - read_idx_0, - read_enable_1, - read_idx_1, - write_enable, - write_idx, - immediate, - branch_offset, - load, - store, - size, - sign_extend, - adder_op, - logic_op, - direction, - branch, - branch_reg, - condition, - bi_conditional, - bi_unconditional, - break_opcode, - scall, - eret, - bret, - csr_write_enable - ); -input [ (32-1):0] instruction; -output [ 0:0] d_result_sel_0; -reg [ 0:0] d_result_sel_0; -output [ 1:0] d_result_sel_1; -reg [ 1:0] d_result_sel_1; -output x_result_sel_csr; -reg x_result_sel_csr; -output x_result_sel_sext; -reg x_result_sel_sext; -output x_result_sel_logic; -reg x_result_sel_logic; -output x_result_sel_add; -reg x_result_sel_add; -output m_result_sel_compare; -reg m_result_sel_compare; -output m_result_sel_shift; -reg m_result_sel_shift; -output w_result_sel_load; -reg w_result_sel_load; -output w_result_sel_mul; -reg w_result_sel_mul; -output x_bypass_enable; -wire x_bypass_enable; -output m_bypass_enable; -wire m_bypass_enable; -output read_enable_0; -wire read_enable_0; -output [ (5-1):0] read_idx_0; -wire [ (5-1):0] read_idx_0; -output read_enable_1; -wire read_enable_1; -output [ (5-1):0] read_idx_1; -wire [ (5-1):0] read_idx_1; -output write_enable; -wire write_enable; -output [ (5-1):0] write_idx; -wire [ (5-1):0] write_idx; -output [ (32-1):0] immediate; -wire [ (32-1):0] immediate; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_offset; -output load; -wire load; -output store; -wire store; -output [ 1:0] size; -wire [ 1:0] size; -output sign_extend; -wire sign_extend; -output adder_op; -wire adder_op; -output [ 3:0] logic_op; -wire [ 3:0] logic_op; -output direction; -wire direction; -output branch; -wire branch; -output branch_reg; -wire branch_reg; -output [ (3-1):0] condition; -wire [ (3-1):0] condition; -output bi_conditional; -wire bi_conditional; -output bi_unconditional; -wire bi_unconditional; -output break_opcode; -wire break_opcode; -output scall; -wire scall; -output eret; -wire eret; -output bret; -wire bret; -output csr_write_enable; -wire csr_write_enable; -wire [ (32-1):0] extended_immediate; -wire [ (32-1):0] high_immediate; -wire [ (32-1):0] call_immediate; -wire [ (32-1):0] branch_immediate; -wire sign_extend_immediate; -wire select_high_immediate; -wire select_call_immediate; -wire op_add; -wire op_and; -wire op_andhi; -wire op_b; -wire op_bi; -wire op_be; -wire op_bg; -wire op_bge; -wire op_bgeu; -wire op_bgu; -wire op_bne; -wire op_call; -wire op_calli; -wire op_cmpe; -wire op_cmpg; -wire op_cmpge; -wire op_cmpgeu; -wire op_cmpgu; -wire op_cmpne; -wire op_lb; -wire op_lbu; -wire op_lh; -wire op_lhu; -wire op_lw; -wire op_mul; -wire op_nor; -wire op_or; -wire op_orhi; -wire op_raise; -wire op_rcsr; -wire op_sb; -wire op_sextb; -wire op_sexth; -wire op_sh; -wire op_sl; -wire op_sr; -wire op_sru; -wire op_sub; -wire op_sw; -wire op_wcsr; -wire op_xnor; -wire op_xor; -wire arith; -wire logical; -wire cmp; -wire bra; -wire call; -wire shift; -wire sext; -function integer clogb2; -input [31:0] value; + + + + + + + + + + + + + + + + + + + +assign shifter_result_x = {operand_0_x[ 32-1] & sign_extend_x, operand_0_x[ 32-1:1]}; + + + + +assign cmp_zero = operand_0_x == operand_1_x; +assign cmp_negative = adder_result_x[ 32-1]; +assign cmp_overflow = adder_overflow_x; +assign cmp_carry_n = adder_carry_n_x; +always @(*) begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; + case (condition_x) + 3'b000: condition_met_x = 1'b1; + 3'b110: condition_met_x = 1'b1; + 3'b001: condition_met_x = cmp_zero; + 3'b111: condition_met_x = !cmp_zero; + 3'b010: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); + 3'b101: condition_met_x = cmp_carry_n && !cmp_zero; + 3'b011: condition_met_x = cmp_negative == cmp_overflow; + 3'b100: condition_met_x = cmp_carry_n; + default: condition_met_x = 1'bx; + endcase end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + +always @(*) +begin + x_result = x_result_sel_add_x ? adder_result_x + : x_result_sel_csr_x ? csr_read_data_x + + + + + + + + + + + : x_result_sel_shift_x ? shifter_result_x + + + + + + + : logic_result_x; +end + + +always @(*) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; + m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + + + + : operand_m; end -endfunction -assign op_add = instruction[ 30:26] == 5'b01101; -assign op_and = instruction[ 30:26] == 5'b01000; -assign op_andhi = instruction[ 31:26] == 6'b011000; -assign op_b = instruction[ 31:26] == 6'b110000; -assign op_bi = instruction[ 31:26] == 6'b111000; -assign op_be = instruction[ 31:26] == 6'b010001; -assign op_bg = instruction[ 31:26] == 6'b010010; -assign op_bge = instruction[ 31:26] == 6'b010011; -assign op_bgeu = instruction[ 31:26] == 6'b010100; -assign op_bgu = instruction[ 31:26] == 6'b010101; -assign op_bne = instruction[ 31:26] == 6'b010111; -assign op_call = instruction[ 31:26] == 6'b110110; -assign op_calli = instruction[ 31:26] == 6'b111110; -assign op_cmpe = instruction[ 30:26] == 5'b11001; -assign op_cmpg = instruction[ 30:26] == 5'b11010; -assign op_cmpge = instruction[ 30:26] == 5'b11011; -assign op_cmpgeu = instruction[ 30:26] == 5'b11100; -assign op_cmpgu = instruction[ 30:26] == 5'b11101; -assign op_cmpne = instruction[ 30:26] == 5'b11111; -assign op_lb = instruction[ 31:26] == 6'b000100; -assign op_lbu = instruction[ 31:26] == 6'b010000; -assign op_lh = instruction[ 31:26] == 6'b000111; -assign op_lhu = instruction[ 31:26] == 6'b001011; -assign op_lw = instruction[ 31:26] == 6'b001010; -assign op_mul = instruction[ 30:26] == 5'b00010; -assign op_nor = instruction[ 30:26] == 5'b00001; -assign op_or = instruction[ 30:26] == 5'b01110; -assign op_orhi = instruction[ 31:26] == 6'b011110; -assign op_raise = instruction[ 31:26] == 6'b101011; -assign op_rcsr = instruction[ 31:26] == 6'b100100; -assign op_sb = instruction[ 31:26] == 6'b001100; -assign op_sextb = instruction[ 31:26] == 6'b101100; -assign op_sexth = instruction[ 31:26] == 6'b110111; -assign op_sh = instruction[ 31:26] == 6'b000011; -assign op_sl = instruction[ 30:26] == 5'b01111; -assign op_sr = instruction[ 30:26] == 5'b00101; -assign op_sru = instruction[ 30:26] == 5'b00000; -assign op_sub = instruction[ 31:26] == 6'b110010; -assign op_sw = instruction[ 31:26] == 6'b010110; -assign op_wcsr = instruction[ 31:26] == 6'b110100; -assign op_xnor = instruction[ 30:26] == 5'b01001; -assign op_xor = instruction[ 30:26] == 5'b00110; -assign arith = op_add | op_sub; -assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; -assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; -assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; -assign bi_unconditional = op_bi; -assign bra = op_b | bi_unconditional | bi_conditional; -assign call = op_call | op_calli; -assign shift = op_sl | op_sr | op_sru; -assign sext = op_sextb | op_sexth; -assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; -assign store = op_sb | op_sh | op_sw; + + always @(*) begin - if (call) - d_result_sel_0 = 1'b1; - else - d_result_sel_0 = 1'b0; - if (call) - d_result_sel_1 = 2'b00; - else if ((instruction[31] == 1'b0) && !bra) - d_result_sel_1 = 2'b10; - else - d_result_sel_1 = 2'b01; - x_result_sel_csr = 1'b0; - x_result_sel_sext = 1'b0; - x_result_sel_logic = 1'b0; - x_result_sel_add = 1'b0; - if (op_rcsr) - x_result_sel_csr = 1'b1; - else if (sext) - x_result_sel_sext = 1'b1; - else if (logical) - x_result_sel_logic = 1'b1; - else - x_result_sel_add = 1'b1; - m_result_sel_compare = cmp; - m_result_sel_shift = shift; - w_result_sel_load = load; - w_result_sel_mul = op_mul; + w_result = w_result_sel_load_w ? load_data_w + + + + + : operand_w; end -assign x_bypass_enable = arith - | logical - | sext - | op_rcsr - ; -assign m_bypass_enable = x_bypass_enable - | shift - | cmp - ; -assign read_enable_0 = ~(op_bi | op_calli); -assign read_idx_0 = instruction[25:21]; -assign read_enable_1 = ~(op_bi | op_calli | load); -assign read_idx_1 = instruction[20:16]; -assign write_enable = ~(bra | op_raise | store | op_wcsr); -assign write_idx = call - ? 5'd29 - : instruction[31] == 1'b0 - ? instruction[20:16] - : instruction[15:11]; -assign size = instruction[27:26]; -assign sign_extend = instruction[28]; -assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; -assign logic_op = instruction[29:26]; -assign direction = instruction[29]; -assign branch = bra | call; -assign branch_reg = op_call | op_b; -assign condition = instruction[28:26]; -assign break_opcode = op_raise & ~instruction[2]; -assign scall = op_raise & instruction[2]; -assign eret = op_b & (instruction[25:21] == 5'd30); -assign bret = op_b & (instruction[25:21] == 5'd31); -assign csr_write_enable = op_wcsr; -assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); -assign select_high_immediate = op_andhi | op_orhi; -assign select_call_immediate = instruction[31]; -assign high_immediate = {instruction[15:0], 16'h0000}; -assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; -assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; -assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; -assign immediate = select_high_immediate == 1'b1 - ? high_immediate - : extended_immediate; -assign branch_offset = select_call_immediate == 1'b1 - ? (call_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]) - : (branch_immediate[ (clogb2(32'h7fffffff-32'h0)-2)-1:0]); -endmodule -module lm32_icache_medium_icache_debug ( - clk_i, - rst_i, - stall_a, - stall_f, - address_a, - address_f, - read_enable_f, - refill_ready, - refill_data, - iflush, - valid_d, - branch_predict_taken_d, - stall_request, - restart_request, - refill_request, - refill_address, - refilling, - inst - ); -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam addr_offset_width = clogb2(bytes_per_line)-1-2; -localparam addr_set_width = clogb2(sets)-1; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -localparam addr_set_lsb = (addr_offset_msb+1); -localparam addr_set_msb = (addr_set_lsb+addr_set_width-1); -localparam addr_tag_lsb = (addr_set_msb+1); -localparam addr_tag_msb = clogb2( 32'h7fffffff- 32'h0)-1; -localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1); -input clk_i; -input rst_i; -input stall_a; -input stall_f; -input valid_d; -input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_a; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] address_f; -input read_enable_f; -input refill_ready; -input [ (32-1):0] refill_data; -input iflush; -output stall_request; -wire stall_request; -output restart_request; -reg restart_request; -output refill_request; -wire refill_request; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] refill_address; -output refilling; -reg refilling; -output [ (32-1):0] inst; -wire [ (32-1):0] inst; -wire enable; -wire [0:associativity-1] way_mem_we; -wire [ (32-1):0] way_data[0:associativity-1]; -wire [ ((addr_tag_width+1)-1):1] way_tag[0:associativity-1]; -wire [0:associativity-1] way_valid; -wire [0:associativity-1] way_match; -wire miss; -wire [ (addr_set_width-1):0] tmem_read_address; -wire [ (addr_set_width-1):0] tmem_write_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_read_address; -wire [ ((addr_offset_width+addr_set_width)-1):0] dmem_write_address; -wire [ ((addr_tag_width+1)-1):0] tmem_write_data; -reg [ 3:0] state; -wire flushing; -wire check; -wire refill; -reg [associativity-1:0] refill_way_select; -reg [ addr_offset_msb:addr_offset_lsb] refill_offset; -wire last_refill; -reg [ (addr_set_width-1):0] flush_set; -genvar i; -function integer clogb2; -input [31:0] value; + + + + + + + + + + + + + +assign branch_taken_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( ( (condition_met_m == 1'b1) + && (branch_predict_taken_m == 1'b0) + ) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign branch_mispredict_taken_m = (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1); + + +assign branch_flushX_m = (stall_m == 1'b0) + && ( ( (branch_m == 1'b1) + && (valid_m == 1'b1) + && ( (condition_met_m == 1'b1) + || ( (condition_met_m == 1'b0) + && (branch_predict_m == 1'b1) + && (branch_predict_taken_m == 1'b1) + ) + ) + ) + || (exception_m == 1'b1) + ); + + +assign kill_f = ( (valid_d == 1'b1) + && (branch_predict_taken_d == 1'b1) + ) + || (branch_taken_m == 1'b1) + + + + + + + + + + + + + ; +assign kill_d = (branch_taken_m == 1'b1) + + + + + + + + + + + + + ; +assign kill_x = (branch_flushX_m == 1'b1) + + + + + ; +assign kill_m = 1'b0 + + + + + ; +assign kill_w = 1'b0 + + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign system_call_exception = ( (scall_x == 1'b1) + + + + + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign exception_x = (system_call_exception == 1'b1) + + + + + + + + + + + + || ( (interrupt_exception == 1'b1) + + + + + + + + + + ) + + + ; + + + + +always @(*) begin - for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) - value = value >> 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if ( (interrupt_exception == 1'b1) + + + + + ) + eid_x = 3'h6; + else + + + eid_x = 3'h7; end -endfunction -function integer clogb2_v1; -input [31:0] value; -reg [31:0] i; -reg [31:0] temp; + + + +assign stall_a = (stall_f == 1'b1); + +assign stall_f = (stall_d == 1'b1); + +assign stall_d = (stall_x == 1'b1) + || ( (interlock == 1'b1) + && (kill_d == 1'b0) + ) + || ( ( (eret_d == 1'b1) + || (scall_d == 1'b1) + + + + + ) + && ( (load_q_x == 1'b1) + || (load_q_m == 1'b1) + || (store_q_x == 1'b1) + || (store_q_m == 1'b1) + || (D_CYC_O == 1'b1) + ) + && (kill_d == 1'b0) + ) + + + + + + + + + + + + + + + || ( (csr_write_enable_d == 1'b1) + && (load_q_x == 1'b1) + ) + + + + + + + + + + + ; + +assign stall_x = (stall_m == 1'b1) + + + + + + + + + ; + +assign stall_m = (stall_wb_load == 1'b1) + + + + + || ( (D_CYC_O == 1'b1) + && ( (store_m == 1'b1) + + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + + || (load_m == 1'b1) + || (load_x == 1'b1) + ) + ) + + + + + + + + + + + + + + || (I_CYC_O == 1'b1) + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + +assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); +assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); +assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + + + +assign load_q_x = (load_x == 1'b1) + && (q_x == 1'b1) + + + + + ; +assign store_q_x = (store_x == 1'b1) + && (q_x == 1'b1) + + + + + ; + + + + +assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); +assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); +assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + + + + +assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + + +assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); +assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); +assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + +assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + +assign cfg = { + 6'h02, + watchpoints[3:0], + breakpoints[3:0], + interrupts[5:0], + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0, + + + + + + + 1'b0 + + + }; + +assign cfg2 = { + 30'b0, + + + + + 1'b0, + + + + + + + 1'b0 + + + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign csr_d = read_idx_0_d[ (4 -1):0]; + + +always @(*) begin - temp = 0; - i = 0; - for (i = 0; temp < value; i = i + 1) - temp = 1<<i; - clogb2_v1 = i-1; + case (csr_x) + + + 4 'h0, + 4 'h1, + 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + + 4 'h6: csr_read_data_x = cfg; + 4 'h7: csr_read_data_x = {eba, 8'h00}; + + + + + + + + + + 4 'ha: csr_read_data_x = cfg2; + 4 'hb: csr_read_data_x = sdb_address; + + default: csr_read_data_x = { 32{1'bx}}; + endcase end -endfunction - generate - for (i = 0; i < associativity; i = i + 1) - begin : memories - lm32_ram - #( - .data_width (32), - .address_width ( (addr_offset_width+addr_set_width)) -) - way_0_data_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (dmem_read_address), - .enable_read (enable), - .write_address (dmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i]), - .write_data (refill_data), - .read_data (way_data[i]) - ); - lm32_ram - #( - .data_width ( (addr_tag_width+1)), - .address_width ( addr_set_width) - ) - way_0_tag_ram - ( - .read_clk (clk_i), - .write_clk (clk_i), - .reset (rst_i), - .read_address (tmem_read_address), - .enable_read (enable), - .write_address (tmem_write_address), - .enable_write ( 1'b1), - .write_enable (way_mem_we[i] | flushing), - .write_data (tmem_write_data), - .read_data ({way_tag[i], way_valid[i]}) - ); - end -endgenerate -generate - for (i = 0; i < associativity; i = i + 1) - begin : match -assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_f[ addr_tag_msb:addr_tag_lsb], 1'b1}); - end -endgenerate -generate - if (associativity == 1) - begin : inst_1 -assign inst = way_match[0] ? way_data[0] : 32'b0; - end - else if (associativity == 2) - begin : inst_2 -assign inst = way_match[0] ? way_data[0] : (way_match[1] ? way_data[1] : 32'b0); - end -endgenerate -generate - if (bytes_per_line > 4) -assign dmem_write_address = {refill_address[ addr_set_msb:addr_set_lsb], refill_offset}; - else -assign dmem_write_address = refill_address[ addr_set_msb:addr_set_lsb]; -endgenerate -assign dmem_read_address = address_a[ addr_set_msb:addr_offset_lsb]; -assign tmem_read_address = address_a[ addr_set_msb:addr_set_lsb]; -assign tmem_write_address = flushing - ? flush_set - : refill_address[ addr_set_msb:addr_set_lsb]; -generate - if (bytes_per_line > 4) -assign last_refill = refill_offset == {addr_offset_width{1'b1}}; - else -assign last_refill = 1'b1; -endgenerate -assign enable = (stall_a == 1'b0); -generate - if (associativity == 1) - begin : we_1 -assign way_mem_we[0] = (refill_ready == 1'b1); - end - else - begin : we_2 -assign way_mem_we[0] = (refill_ready == 1'b1) && (refill_way_select[0] == 1'b1); -assign way_mem_we[1] = (refill_ready == 1'b1) && (refill_way_select[1] == 1'b1); - end -endgenerate -assign tmem_write_data[ 0] = last_refill & !flushing; -assign tmem_write_data[ ((addr_tag_width+1)-1):1] = refill_address[ addr_tag_msb:addr_tag_lsb]; -assign flushing = |state[1:0]; -assign check = state[2]; -assign refill = state[3]; -assign miss = (~(|way_match)) && (read_enable_f == 1'b1) && (stall_f == 1'b0) && !(valid_d && branch_predict_taken_d); -assign stall_request = (check == 1'b0); -assign refill_request = (refill == 1'b1); -generate - if (associativity >= 2) - begin : way_select + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - refill_way_select <= {{associativity-1{1'b0}}, 1'b1}; + eba <= eba_reset[ (32-2)+2-1:8]; else - begin - if (miss == 1'b1) - refill_way_select <= {refill_way_select[0], refill_way_select[1]}; + begin + if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) + eba <= operand_1_x[ (32-2)+2-1:8]; + + + + + end end - end -endgenerate + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - refilling <= 1'b0; + begin + valid_f <= 1'b0; + valid_d <= 1'b0; + valid_x <= 1'b0; + valid_m <= 1'b0; + valid_w <= 1'b0; + end else - refilling <= refill; + begin + if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + + + + valid_f <= 1'b1; + + + else if (stall_f == 1'b0) + valid_f <= 1'b0; + + if (kill_d == 1'b1) + valid_d <= 1'b0; + else if (stall_f == 1'b0) + valid_d <= valid_f & !kill_f; + else if (stall_d == 1'b0) + valid_d <= 1'b0; + + if (stall_d == 1'b0) + valid_x <= valid_d & !kill_d; + else if (kill_x == 1'b1) + valid_x <= 1'b0; + else if (stall_x == 1'b0) + valid_x <= 1'b0; + + if (kill_m == 1'b1) + valid_m <= 1'b0; + else if (stall_x == 1'b0) + valid_m <= valid_x & !kill_x; + else if (stall_m == 1'b0) + valid_m <= 1'b0; + + if (stall_m == 1'b0) + valid_w <= valid_m & !kill_m; + else + valid_w <= 1'b0; + end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - state <= 4'b0001; - flush_set <= { addr_set_width{1'b1}}; - refill_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - restart_request <= 1'b0; + + + + + operand_0_x <= { 32{1'b0}}; + operand_1_x <= { 32{1'b0}}; + store_operand_x <= { 32{1'b0}}; + branch_target_x <= { (32-2){1'b0}}; + x_result_sel_csr_x <= 1'b0; + + + + + + + x_result_sel_shift_x <= 1'b0; + + + + + + + + + + + x_result_sel_add_x <= 1'b0; + m_result_sel_compare_x <= 1'b0; + + + + + w_result_sel_load_x <= 1'b0; + + + + + x_bypass_enable_x <= 1'b0; + m_bypass_enable_x <= 1'b0; + write_enable_x <= 1'b0; + write_idx_x <= { 5{1'b0}}; + csr_x <= { 4 {1'b0}}; + load_x <= 1'b0; + store_x <= 1'b0; + size_x <= { 2{1'b0}}; + sign_extend_x <= 1'b0; + adder_op_x <= 1'b0; + adder_op_x_n <= 1'b0; + logic_op_x <= 4'h0; + + + + + + + + + + branch_x <= 1'b0; + branch_predict_x <= 1'b0; + branch_predict_taken_x <= 1'b0; + condition_x <= 3'b000; + + + + + scall_x <= 1'b0; + eret_x <= 1'b0; + + + + + + + + + + csr_write_enable_x <= 1'b0; + operand_m <= { 32{1'b0}}; + branch_target_m <= { (32-2){1'b0}}; + m_result_sel_compare_m <= 1'b0; + + + + + w_result_sel_load_m <= 1'b0; + + + + + m_bypass_enable_m <= 1'b0; + branch_m <= 1'b0; + branch_predict_m <= 1'b0; + branch_predict_taken_m <= 1'b0; + exception_m <= 1'b0; + load_m <= 1'b0; + store_m <= 1'b0; + write_enable_m <= 1'b0; + write_idx_m <= { 5{1'b0}}; + condition_met_m <= 1'b0; + + + + + + + + + + operand_w <= { 32{1'b0}}; + w_result_sel_load_w <= 1'b0; + + + + + write_idx_w <= { 5{1'b0}}; + write_enable_w <= 1'b0; + + + + + + exception_w <= 1'b0; + + + + + + end - else + else begin - case (state) - 4'b0001: - begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 4'b0100; - flush_set <= flush_set - 1'b1; - end - 4'b0010: - begin - if (flush_set == { addr_set_width{1'b0}}) - state <= 4'b0100; - flush_set <= flush_set - 1'b1; + + + if (stall_x == 1'b0) + begin + + + + + operand_0_x <= d_result_0; + operand_1_x <= d_result_1; + store_operand_x <= bypass_data_1; + branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; + x_result_sel_csr_x <= x_result_sel_csr_d; + + + + + + + x_result_sel_shift_x <= x_result_sel_shift_d; + + + + + + + + + + + x_result_sel_add_x <= x_result_sel_add_d; + m_result_sel_compare_x <= m_result_sel_compare_d; + + + + + w_result_sel_load_x <= w_result_sel_load_d; + + + + + x_bypass_enable_x <= x_bypass_enable_d; + m_bypass_enable_x <= m_bypass_enable_d; + load_x <= load_d; + store_x <= store_d; + branch_x <= branch_d; + branch_predict_x <= branch_predict_d; + branch_predict_taken_x <= branch_predict_taken_d; + write_idx_x <= write_idx_d; + csr_x <= csr_d; + size_x <= size_d; + sign_extend_x <= sign_extend_d; + adder_op_x <= adder_op_d; + adder_op_x_n <= ~adder_op_d; + logic_op_x <= logic_op_d; + + + + + + + + + condition_x <= condition_d; + csr_write_enable_x <= csr_write_enable_d; + + + + + scall_x <= scall_d; + + + + + eret_x <= eret_d; + + + + + write_enable_x <= write_enable_d; end - 4'b0100: - begin - if (stall_a == 1'b0) - restart_request <= 1'b0; - if (iflush == 1'b1) - begin - refill_address <= address_f; - state <= 4'b0010; - end - else if (miss == 1'b1) + + + + if (stall_m == 1'b0) + begin + operand_m <= x_result; + m_result_sel_compare_m <= m_result_sel_compare_x; + + + + + if (exception_x == 1'b1) begin - refill_address <= address_f; - state <= 4'b1000; + w_result_sel_load_m <= 1'b0; + + + + end - end - 4'b1000: - begin - if (refill_ready == 1'b1) + else begin - if (last_refill == 1'b1) - begin - restart_request <= 1'b1; - state <= 4'b0100; - end + w_result_sel_load_m <= w_result_sel_load_x; + + + + end + m_bypass_enable_m <= m_bypass_enable_x; + load_m <= load_x; + store_m <= store_x; + + + + + branch_m <= branch_x; + branch_predict_m <= branch_predict_x; + branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + + + + + + + + + if (exception_x == 1'b1) + write_idx_m <= 5'd30; + else + write_idx_m <= write_idx_x; + + + condition_met_m <= condition_met_x; + + + + + + + + + + + + + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + + + end - endcase + + + if (stall_m == 1'b0) + begin + if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) + exception_m <= 1'b1; + else + exception_m <= 1'b0; + + + + + + + + + end + + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + + w_result_sel_load_w <= w_result_sel_load_m; + + + + + write_idx_w <= write_idx_m; + + + + + + + + + write_enable_w <= write_enable_m; + + + + + + exception_w <= exception_m; + + + + + + + + + + + end end -generate - if (bytes_per_line > 4) - begin + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else begin - case (state) - 4'b0100: - begin - if (iflush == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - else if (miss == 1'b1) - refill_offset <= {addr_offset_width{1'b0}}; - end - 4'b1000: - begin - if (refill_ready == 1'b1) - refill_offset <= refill_offset + 1'b1; + use_buf <= 1'b0; + reg_data_buf_0 <= { 32{1'b0}}; + reg_data_buf_1 <= { 32{1'b0}}; + end + else + begin + if (stall_d == 1'b0) + use_buf <= 1'b0; + else if (use_buf == 1'b0) + begin + reg_data_buf_0 <= reg_data_live_0; + reg_data_buf_1 <= reg_data_live_1; + use_buf <= 1'b1; + end + if (reg_write_enable_q_w == 1'b1) + begin + if (write_idx_w == read_idx_0_d) + reg_data_buf_0 <= w_result; + if (write_idx_w == read_idx_1_d) + reg_data_buf_1 <= w_result; end - endcase end end - end -endgenerate -endmodule -module lm32_debug_medium_icache_debug ( - clk_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +initial +begin + + + + + + +end + + + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_minimal +( + + clk_i, + + + + rst_i, - pc_x, - load_x, - store_x, - load_store_address_x, - csr_write_enable_x, - csr_write_data, - csr_x, - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - eret_q_x, - bret_q_x, - stall_x, - exception_x, - q_x, - dc_ss, - dc_re, - bp_match, - wp_match - ); -parameter breakpoints = 0; -parameter watchpoints = 0; -input clk_i; -input rst_i; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -input load_x; -input store_x; -input [ (32-1):0] load_store_address_x; -input csr_write_enable_x; -input [ (32-1):0] csr_write_data; -input [ (5-1):0] csr_x; -input jtag_csr_write_enable; -input [ (32-1):0] jtag_csr_write_data; -input [ (5-1):0] jtag_csr; -input eret_q_x; -input bret_q_x; -input stall_x; -input exception_x; -input q_x; -output dc_ss; -reg dc_ss; -output dc_re; -reg dc_re; -output bp_match; -wire bp_match; -output wp_match; -wire wp_match; -genvar i; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] bp_a[0:breakpoints-1]; -reg bp_e[0:breakpoints-1]; -wire [0:breakpoints-1]bp_match_n; -reg [ 1:0] wpc_c[0:watchpoints-1]; -reg [ (32-1):0] wp[0:watchpoints-1]; -wire [0:watchpoints-1]wp_match_n; -wire debug_csr_write_enable; -wire [ (32-1):0] debug_csr_write_data; -wire [ (5-1):0] debug_csr; -reg [ 2:0] state; + + stall_a, + stall_x, + stall_m, + kill_x, + kill_m, + exception_m, + store_operand_x, + load_store_address_x, + load_store_address_m, + load_store_address_w, + load_x, + store_x, + load_q_x, + store_q_x, + load_q_m, + store_q_m, + sign_extend_x, + size_x, + + + + + + d_dat_i, + d_ack_i, + d_err_i, + d_rty_i, + + + + + + + + + + + + + + + + + + + + load_data_w, + stall_wb_load, + + d_dat_o, + d_adr_o, + d_cyc_o, + d_sel_o, + d_stb_o, + d_we_o, + d_cti_o, + d_lock_o, + d_bte_o + ); + + + + + +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + input clk_i; + +input rst_i; + +input stall_a; +input stall_x; +input stall_m; +input kill_x; +input kill_m; +input exception_m; + +input [ (32-1):0] store_operand_x; +input [ (32-1):0] load_store_address_x; +input [ (32-1):0] load_store_address_m; +input [1:0] load_store_address_w; +input load_x; +input store_x; +input load_q_x; +input store_q_x; +input load_q_m; +input store_q_m; +input sign_extend_x; +input [ 1:0] size_x; + + + + + + + + + + + + + + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + +input [ (32-1):0] d_dat_i; +input d_ack_i; +input d_err_i; +input d_rty_i; + + + + + + + + + + + + + + + + + + +output [ (32-1):0] load_data_w; +reg [ (32-1):0] load_data_w; +output stall_wb_load; +reg stall_wb_load; + +output [ (32-1):0] d_dat_o; +reg [ (32-1):0] d_dat_o; +output [ (32-1):0] d_adr_o; +reg [ (32-1):0] d_adr_o; +output d_cyc_o; +reg d_cyc_o; +output [ (4-1):0] d_sel_o; +reg [ (4-1):0] d_sel_o; +output d_stb_o; +reg d_stb_o; +output d_we_o; +reg d_we_o; +output [ (3-1):0] d_cti_o; +reg [ (3-1):0] d_cti_o; +output d_lock_o; +reg d_lock_o; +output [ (2-1):0] d_bte_o; +wire [ (2-1):0] d_bte_o; + + + + + + +reg [ 1:0] size_m; +reg [ 1:0] size_w; +reg sign_extend_m; +reg sign_extend_w; +reg [ (32-1):0] store_data_x; +reg [ (32-1):0] store_data_m; +reg [ (4-1):0] byte_enable_x; +reg [ (4-1):0] byte_enable_m; +wire [ (32-1):0] data_m; +reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + +wire wb_select_x; + + + + + + + + + + +reg wb_select_m; +reg [ (32-1):0] wb_data_m; +reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -17829,6 +81943,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -17841,275 +81956,1328 @@ begin clogb2_v1 = i-1; end endfunction -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_comb -assign bp_match_n[i] = ((bp_a[i] == pc_x) && (bp_e[i] == 1'b1)); - end -endgenerate -generate - if (breakpoints > 0) -assign bp_match = (|bp_match_n) || (state == 3'b011); - else -assign bp_match = state == 3'b011; -endgenerate -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_comb -assign wp_match_n[i] = (wp[i] == load_store_address_x) && ((load_x & wpc_c[i][0]) | (store_x & wpc_c[i][1])); - end -endgenerate -generate - if (watchpoints > 0) -assign wp_match = |wp_match_n; - else -assign wp_match = 1'b0; -endgenerate -assign debug_csr_write_enable = (csr_write_enable_x == 1'b1) || (jtag_csr_write_enable == 1'b1); -assign debug_csr_write_data = jtag_csr_write_enable == 1'b1 ? jtag_csr_write_data : csr_write_data; -assign debug_csr = jtag_csr_write_enable == 1'b1 ? jtag_csr : csr_x; -generate - for (i = 0; i < breakpoints; i = i + 1) - begin : bp_seq + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + + + ; + + +always @(*) +begin + case (size_x) + 2'b00: store_data_x = {4{store_operand_x[7:0]}}; + 2'b11: store_data_x = {2{store_operand_x[15:0]}}; + 2'b10: store_data_x = store_operand_x; + default: store_data_x = { 32{1'bx}}; + endcase +end + + +always @(*) +begin + casez ({size_x, load_store_address_x[1:0]}) + { 2'b00, 2'b11}: byte_enable_x = 4'b0001; + { 2'b00, 2'b10}: byte_enable_x = 4'b0010; + { 2'b00, 2'b01}: byte_enable_x = 4'b0100; + { 2'b00, 2'b00}: byte_enable_x = 4'b1000; + { 2'b11, 2'b1?}: byte_enable_x = 4'b0011; + { 2'b11, 2'b0?}: byte_enable_x = 4'b1100; + { 2'b10, 2'b??}: byte_enable_x = 4'b1111; + default: byte_enable_x = 4'bxxxx; + endcase +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_data_m; + + + + + + + + +always @(*) +begin + casez ({size_w, load_store_address_w[1:0]}) + { 2'b00, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]}; + { 2'b00, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]}; + { 2'b00, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]}; + { 2'b00, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]}; + { 2'b11, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]}; + { 2'b11, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]}; + { 2'b10, 2'b??}: load_data_w = data_w; + default: load_data_w = { 32{1'bx}}; + endcase +end + + +assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - bp_a[i] <= { (clogb2(32'h7fffffff-32'h0)-2){1'bx}}; - bp_e[i] <= 1'b0; + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_dat_o <= { 32{1'b0}}; + d_adr_o <= { 32{1'b0}}; + d_sel_o <= { 4{ 1'b0}}; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + d_lock_o <= 1'b0; + wb_data_m <= { 32{1'b0}}; + wb_load_complete <= 1'b0; + stall_wb_load <= 1'b0; + + + + end else begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h10 + i)) + + + + + + + if (d_cyc_o == 1'b1) begin - bp_a[i] <= debug_csr_write_data[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - bp_e[i] <= debug_csr_write_data[0]; + + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) + begin + + + + + + + + + + begin + + d_cyc_o <= 1'b0; + d_stb_o <= 1'b0; + d_lock_o <= 1'b0; + end + + + + + + + + wb_data_m <= d_dat_i; + + wb_load_complete <= !d_we_o; + end + + if (d_err_i == 1'b1) + $display ("Data bus error. Address: %x", d_adr_o); + end - end -end - end -endgenerate -generate - for (i = 0; i < watchpoints; i = i + 1) - begin : wp_seq -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - wp[i] <= { 32{1'bx}}; - wpc_c[i] <= 2'b00; - end - else - begin - if (debug_csr_write_enable == 1'b1) + else begin - if (debug_csr == 5'h8) - wpc_c[i] <= debug_csr_write_data[3+i*2:2+i*2]; - if (debug_csr == 5'h18 + i) - wp[i] <= debug_csr_write_data; + + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) + && (stall_m == 1'b0) + + + + + + + + + ) + begin + + d_dat_o <= store_data_m; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b1; + d_cti_o <= 3'b111; + end + else if ( (load_q_m == 1'b1) + && (wb_select_m == 1'b1) + && (wb_load_complete == 1'b0) + + ) + begin + + stall_wb_load <= 1'b0; + d_adr_o <= load_store_address_m; + d_cyc_o <= 1'b1; + d_sel_o <= byte_enable_m; + d_stb_o <= 1'b1; + d_we_o <= 1'b0; + d_cti_o <= 3'b111; + end end - end -end + + if (stall_m == 1'b0) + wb_load_complete <= 1'b0; + + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) + stall_wb_load <= 1'b1; + + if ((kill_m == 1'b1) || (exception_m == 1'b1)) + stall_wb_load <= 1'b0; end -endgenerate +end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - dc_re <= 1'b0; + begin + sign_extend_m <= 1'b0; + size_m <= 2'b00; + byte_enable_m <= 1'b0; + store_data_m <= { 32{1'b0}}; + + + + + + + + + + + + + + wb_select_m <= 1'b0; + end else begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - dc_re <= debug_csr_write_data[1]; + if (stall_m == 1'b0) + begin + sign_extend_m <= sign_extend_x; + size_m <= size_x; + byte_enable_m <= byte_enable_x; + store_data_m <= store_data_x; + + + + + + + + + + + + + + wb_select_m <= wb_select_x; + end end -end +end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin - state <= 3'b000; - dc_ss <= 1'b0; + size_w <= 2'b00; + data_w <= { 32{1'b0}}; + sign_extend_w <= 1'b0; end else begin - if ((debug_csr_write_enable == 1'b1) && (debug_csr == 5'h8)) - begin - dc_ss <= debug_csr_write_data[0]; - if (debug_csr_write_data[0] == 1'b0) - state <= 3'b000; - else - state <= 3'b001; - end - case (state) - 3'b001: - begin - if ( ( (eret_q_x == 1'b1) - || (bret_q_x == 1'b1) - ) - && (stall_x == 1'b0) - ) - state <= 3'b010; - end - 3'b010: - begin - if ((q_x == 1'b1) && (stall_x == 1'b0)) - state <= 3'b011; - end - 3'b011: - begin - if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) - begin - dc_ss <= 1'b0; - state <= 3'b100; - end - end - 3'b100: - begin - state <= 3'b000; - end - endcase + size_w <= size_m; + + + + + + data_w <= data_m; + + sign_extend_w <= sign_extend_m; end end + + + + + + + + +always @(posedge clk_i) +begin + if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) + begin + if ((size_m === 2'b11) && (load_store_address_m[0] !== 1'b0)) + $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + if ((size_m === 2'b10) && (load_store_address_m[1:0] !== 2'b00)) + $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); + end +end + + + endmodule -module lm32_instruction_unit_medium_icache_debug ( - clk_i, - rst_i, - stall_a, - stall_f, - stall_d, - stall_x, - stall_m, - valid_f, - valid_d, - kill_f, - branch_predict_taken_d, - branch_predict_address_d, - exception_m, - branch_taken_m, - branch_mispredict_taken_m, - branch_target_m, - iflush, - i_dat_i, - i_ack_i, - i_err_i, - i_rty_i, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - pc_f, - pc_d, - pc_x, - pc_m, - pc_w, - icache_stall_request, - icache_restart_request, - icache_refill_request, - icache_refilling, - i_dat_o, - i_adr_o, - i_cyc_o, - i_sel_o, - i_stb_o, - i_we_o, - i_cti_o, - i_lock_o, - i_bte_o, - jtag_read_data, - jtag_access_complete, - instruction_f, - instruction_d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_minimal ( + + instruction, + + d_result_sel_0, + d_result_sel_1, + x_result_sel_csr, + + + + + + + x_result_sel_shift, + + + + + + + x_result_sel_logic, + + + + + x_result_sel_add, + m_result_sel_compare, + + + + + w_result_sel_load, + + + + + x_bypass_enable, + m_bypass_enable, + read_enable_0, + read_idx_0, + read_enable_1, + read_idx_1, + write_enable, + write_idx, + immediate, + branch_offset, + load, + store, + size, + sign_extend, + adder_op, + logic_op, + + + + + + + + + + + + + + + + + + + branch, + branch_reg, + condition, + bi_conditional, + bi_unconditional, + + + + + scall, + eret, + + + + + + + + + csr_write_enable ); -parameter eba_reset = 32'h00000000; -parameter associativity = 1; -parameter sets = 512; -parameter bytes_per_line = 16; -parameter base_address = 0; -parameter limit = 0; -localparam eba_reset_minus_4 = eba_reset - 4; -localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; -localparam addr_offset_lsb = 2; -localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; -input rst_i; -input stall_a; -input stall_f; -input stall_d; -input stall_x; -input stall_m; -input valid_f; -input valid_d; -input kill_f; -input branch_predict_taken_d; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_predict_address_d; -input exception_m; -input branch_taken_m; -input branch_mispredict_taken_m; -input [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] branch_target_m; -input iflush; -input [ (32-1):0] i_dat_i; -input i_ack_i; -input i_err_i; -input i_rty_i; -input jtag_read_enable; -input jtag_write_enable; -input [ 7:0] jtag_write_data; -input [ (32-1):0] jtag_address; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_f; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_d; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_x; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_m; -output [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_w; -output icache_stall_request; -wire icache_stall_request; -output icache_restart_request; -wire icache_restart_request; -output icache_refill_request; -wire icache_refill_request; -output icache_refilling; -wire icache_refilling; -output [ (32-1):0] i_dat_o; -reg [ (32-1):0] i_dat_o; -output [ (32-1):0] i_adr_o; -reg [ (32-1):0] i_adr_o; -output i_cyc_o; -reg i_cyc_o; -output [ (4-1):0] i_sel_o; -reg [ (4-1):0] i_sel_o; -output i_stb_o; -reg i_stb_o; -output i_we_o; -reg i_we_o; -output [ (3-1):0] i_cti_o; -reg [ (3-1):0] i_cti_o; -output i_lock_o; -reg i_lock_o; -output [ (2-1):0] i_bte_o; -wire [ (2-1):0] i_bte_o; -output [ 7:0] jtag_read_data; -reg [ 7:0] jtag_read_data; -output jtag_access_complete; -wire jtag_access_complete; -output [ (32-1):0] instruction_f; -wire [ (32-1):0] instruction_f; -output [ (32-1):0] instruction_d; -reg [ (32-1):0] instruction_d; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] pc_a; -reg [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] restart_address; -wire icache_read_enable_f; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] icache_refill_address; -reg icache_refill_ready; -reg [ (32-1):0] icache_refill_data; -wire [ (32-1):0] icache_data_f; -wire [ (3-1):0] first_cycle_type; -wire [ (3-1):0] next_cycle_type; -wire last_word; -wire [ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2] first_address; -reg jtag_access; + + + + + +input [ (32-1):0] instruction; + + + + + +output [ 0:0] d_result_sel_0; +reg [ 0:0] d_result_sel_0; +output [ 1:0] d_result_sel_1; +reg [ 1:0] d_result_sel_1; +output x_result_sel_csr; +reg x_result_sel_csr; + + + + + + + +output x_result_sel_shift; +reg x_result_sel_shift; + + + + + + + +output x_result_sel_logic; +reg x_result_sel_logic; + + + + + +output x_result_sel_add; +reg x_result_sel_add; +output m_result_sel_compare; +reg m_result_sel_compare; + + + + + +output w_result_sel_load; +reg w_result_sel_load; + + + + + +output x_bypass_enable; +wire x_bypass_enable; +output m_bypass_enable; +wire m_bypass_enable; +output read_enable_0; +wire read_enable_0; +output [ (5-1):0] read_idx_0; +wire [ (5-1):0] read_idx_0; +output read_enable_1; +wire read_enable_1; +output [ (5-1):0] read_idx_1; +wire [ (5-1):0] read_idx_1; +output write_enable; +wire write_enable; +output [ (5-1):0] write_idx; +wire [ (5-1):0] write_idx; +output [ (32-1):0] immediate; +wire [ (32-1):0] immediate; +output [ ((32-2)+2-1):2] branch_offset; +wire [ ((32-2)+2-1):2] branch_offset; +output load; +wire load; +output store; +wire store; +output [ 1:0] size; +wire [ 1:0] size; +output sign_extend; +wire sign_extend; +output adder_op; +wire adder_op; +output [ 3:0] logic_op; +wire [ 3:0] logic_op; + + + + + + + + + + + + + + + + + + + + + + + + +output branch; +wire branch; +output branch_reg; +wire branch_reg; +output [ (3-1):0] condition; +wire [ (3-1):0] condition; +output bi_conditional; +wire bi_conditional; +output bi_unconditional; +wire bi_unconditional; + + + + + +output scall; +wire scall; +output eret; +wire eret; + + + + + + + + + + +output csr_write_enable; +wire csr_write_enable; + + + + + +wire [ (32-1):0] extended_immediate; +wire [ (32-1):0] high_immediate; +wire [ (32-1):0] call_immediate; +wire [ (32-1):0] branch_immediate; +wire sign_extend_immediate; +wire select_high_immediate; +wire select_call_immediate; + +wire op_add; +wire op_and; +wire op_andhi; +wire op_b; +wire op_bi; +wire op_be; +wire op_bg; +wire op_bge; +wire op_bgeu; +wire op_bgu; +wire op_bne; +wire op_call; +wire op_calli; +wire op_cmpe; +wire op_cmpg; +wire op_cmpge; +wire op_cmpgeu; +wire op_cmpgu; +wire op_cmpne; + + + + +wire op_lb; +wire op_lbu; +wire op_lh; +wire op_lhu; +wire op_lw; + + + + + + + + +wire op_nor; +wire op_or; +wire op_orhi; +wire op_raise; +wire op_rcsr; +wire op_sb; + + + + + +wire op_sh; + + + + +wire op_sr; +wire op_sru; +wire op_sub; +wire op_sw; + + + + +wire op_wcsr; +wire op_xnor; +wire op_xor; + +wire arith; +wire logical; +wire cmp; +wire bra; +wire call; + + + + + + +wire shift; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -18117,6 +83285,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -18129,631 +83298,5259 @@ begin clogb2_v1 = i-1; end endfunction -lm32_icache_medium_icache_debug #( - .associativity (associativity), - .sets (sets), - .bytes_per_line (bytes_per_line), - .base_address (base_address), - .limit (limit) - ) icache ( - .clk_i (clk_i), - .rst_i (rst_i), - .stall_a (stall_a), - .stall_f (stall_f), - .branch_predict_taken_d (branch_predict_taken_d), - .valid_d (valid_d), - .address_a (pc_a), - .address_f (pc_f), - .read_enable_f (icache_read_enable_f), - .refill_ready (icache_refill_ready), - .refill_data (icache_refill_data), - .iflush (iflush), - .stall_request (icache_stall_request), - .restart_request (icache_restart_request), - .refill_request (icache_refill_request), - .refill_address (icache_refill_address), - .refilling (icache_refilling), - .inst (icache_data_f) - ); -assign icache_read_enable_f = (valid_f == 1'b1) - && (kill_f == 1'b0) - ; -always @(*) -begin - if (branch_taken_m == 1'b1) - if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) - pc_a = pc_x; - else - pc_a = branch_target_m; - else - if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) - pc_a = branch_predict_address_d; - else - if (icache_restart_request == 1'b1) - pc_a = restart_address; - else - pc_a = pc_f + 1'b1; -end -assign instruction_f = icache_data_f; -assign i_bte_o = 2'b00; -generate - case (bytes_per_line) - 4: - begin -assign first_cycle_type = 3'b111; -assign next_cycle_type = 3'b111; -assign last_word = 1'b1; -assign first_address = icache_refill_address; - end - 8: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = 3'b111; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; - end - 16: - begin -assign first_cycle_type = 3'b010; -assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? 3'b111 : 3'b010; -assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11; -assign first_address = {icache_refill_address[ (clogb2(32'h7fffffff-32'h0)-2)+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}}; - end - endcase -endgenerate -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - pc_f <= eba_reset_minus_4[ ((clogb2(32'h7fffffff-32'h0)-2)+2-1):2]; - pc_d <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_x <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_m <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - pc_w <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - end - else - begin - if (stall_f == 1'b0) - pc_f <= pc_a; - if (stall_d == 1'b0) - pc_d <= pc_f; - if (stall_x == 1'b0) - pc_x <= pc_d; - if (stall_m == 1'b0) - pc_m <= pc_x; - pc_w <= pc_m; - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - restart_address <= { (clogb2(32'h7fffffff-32'h0)-2){1'b0}}; - else - begin - if (icache_refill_request == 1'b1) - restart_address <= icache_refill_address; - end -end -assign jtag_access_complete = (i_cyc_o == 1'b1) && ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) && (jtag_access == 1'b1); + + + + + + + + + +assign op_add = instruction[ 30:26] == 5'b01101; +assign op_and = instruction[ 30:26] == 5'b01000; +assign op_andhi = instruction[ 31:26] == 6'b011000; +assign op_b = instruction[ 31:26] == 6'b110000; +assign op_bi = instruction[ 31:26] == 6'b111000; +assign op_be = instruction[ 31:26] == 6'b010001; +assign op_bg = instruction[ 31:26] == 6'b010010; +assign op_bge = instruction[ 31:26] == 6'b010011; +assign op_bgeu = instruction[ 31:26] == 6'b010100; +assign op_bgu = instruction[ 31:26] == 6'b010101; +assign op_bne = instruction[ 31:26] == 6'b010111; +assign op_call = instruction[ 31:26] == 6'b110110; +assign op_calli = instruction[ 31:26] == 6'b111110; +assign op_cmpe = instruction[ 30:26] == 5'b11001; +assign op_cmpg = instruction[ 30:26] == 5'b11010; +assign op_cmpge = instruction[ 30:26] == 5'b11011; +assign op_cmpgeu = instruction[ 30:26] == 5'b11100; +assign op_cmpgu = instruction[ 30:26] == 5'b11101; +assign op_cmpne = instruction[ 30:26] == 5'b11111; + + + + +assign op_lb = instruction[ 31:26] == 6'b000100; +assign op_lbu = instruction[ 31:26] == 6'b010000; +assign op_lh = instruction[ 31:26] == 6'b000111; +assign op_lhu = instruction[ 31:26] == 6'b001011; +assign op_lw = instruction[ 31:26] == 6'b001010; + + + + + + + + +assign op_nor = instruction[ 30:26] == 5'b00001; +assign op_or = instruction[ 30:26] == 5'b01110; +assign op_orhi = instruction[ 31:26] == 6'b011110; +assign op_raise = instruction[ 31:26] == 6'b101011; +assign op_rcsr = instruction[ 31:26] == 6'b100100; +assign op_sb = instruction[ 31:26] == 6'b001100; + + + + + +assign op_sh = instruction[ 31:26] == 6'b000011; + + + + +assign op_sr = instruction[ 30:26] == 5'b00101; +assign op_sru = instruction[ 30:26] == 5'b00000; +assign op_sub = instruction[ 31:26] == 6'b110010; +assign op_sw = instruction[ 31:26] == 6'b010110; + + + + +assign op_wcsr = instruction[ 31:26] == 6'b110100; +assign op_xnor = instruction[ 30:26] == 5'b01001; +assign op_xor = instruction[ 30:26] == 5'b00110; + + +assign arith = op_add | op_sub; +assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; +assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; +assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; +assign bi_unconditional = op_bi; +assign bra = op_b | bi_unconditional | bi_conditional; +assign call = op_call | op_calli; + + + + + + +assign shift = op_sr | op_sru; + + + + + + + + + + + + + + + + + + + + +assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; +assign store = op_sb | op_sh | op_sw; + + always @(*) begin - case (jtag_address[1:0]) - 2'b00: jtag_read_data = i_dat_i[ 31:24]; - 2'b01: jtag_read_data = i_dat_i[ 23:16]; - 2'b10: jtag_read_data = i_dat_i[ 15:8]; - 2'b11: jtag_read_data = i_dat_i[ 7:0]; - endcase -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - icache_refill_data <= { 32{1'b0}}; - icache_refill_ready <= 1'b0; - i_we_o <= 1'b0; - i_sel_o <= 4'b1111; - jtag_access <= 1'b0; - end + + if (call) + d_result_sel_0 = 1'b1; + else + d_result_sel_0 = 1'b0; + if (call) + d_result_sel_1 = 2'b00; + else if ((instruction[31] == 1'b0) && !bra) + d_result_sel_1 = 2'b10; else - begin - icache_refill_ready <= 1'b0; - if (i_cyc_o == 1'b1) - begin - if ((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - if (jtag_access == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_we_o <= 1'b0; - jtag_access <= 1'b0; - end - else - begin - if (last_word == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_lock_o <= 1'b0; - end - i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1; - i_cti_o <= next_cycle_type; - icache_refill_ready <= 1'b1; - icache_refill_data <= i_dat_i; - end - end - end - else - begin - if ((icache_refill_request == 1'b1) && (icache_refill_ready == 1'b0)) - begin - i_sel_o <= 4'b1111; - i_adr_o <= {first_address, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_cti_o <= first_cycle_type; - end - else - begin - if ((jtag_read_enable == 1'b1) || (jtag_write_enable == 1'b1)) - begin - case (jtag_address[1:0]) - 2'b00: i_sel_o <= 4'b1000; - 2'b01: i_sel_o <= 4'b0100; - 2'b10: i_sel_o <= 4'b0010; - 2'b11: i_sel_o <= 4'b0001; - endcase - i_adr_o <= jtag_address; - i_dat_o <= {4{jtag_write_data}}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - i_we_o <= jtag_write_enable; - i_cti_o <= 3'b111; - jtag_access <= 1'b1; - end - end - end - end + d_result_sel_1 = 2'b01; + + x_result_sel_csr = 1'b0; + + + + + + + x_result_sel_shift = 1'b0; + + + + + + + x_result_sel_logic = 1'b0; + + + + + x_result_sel_add = 1'b0; + if (op_rcsr) + x_result_sel_csr = 1'b1; + + + + + + + + + + + + + + + + + + else if (shift) + x_result_sel_shift = 1'b1; + + + + + + + + else if (logical) + x_result_sel_logic = 1'b1; + + + + + + else + x_result_sel_add = 1'b1; + + + + m_result_sel_compare = cmp; + + + + + + + w_result_sel_load = load; + + + + end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - end - else - begin - if (stall_d == 1'b0) - begin - instruction_d <= instruction_f; - end - end -end -endmodule -module lm32_jtag_medium_icache_debug ( + + +assign x_bypass_enable = arith + | logical + + + + + + + + + + + + + + + + + | shift + + + + + + + + + + + | op_rcsr + ; + +assign m_bypass_enable = x_bypass_enable + + + + + | cmp + ; + +assign read_enable_0 = ~(op_bi | op_calli); +assign read_idx_0 = instruction[25:21]; + +assign read_enable_1 = ~(op_bi | op_calli | load); +assign read_idx_1 = instruction[20:16]; + +assign write_enable = ~(bra | op_raise | store | op_wcsr); +assign write_idx = call + ? 5'd29 + : instruction[31] == 1'b0 + ? instruction[20:16] + : instruction[15:11]; + + +assign size = instruction[27:26]; + +assign sign_extend = instruction[28]; + +assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + +assign logic_op = instruction[29:26]; + + + + + + +assign branch = bra | call; +assign branch_reg = op_call | op_b; +assign condition = instruction[28:26]; + + + + +assign scall = op_raise & instruction[2]; +assign eret = op_b & (instruction[25:21] == 5'd30); + + + + + + + + + + +assign csr_write_enable = op_wcsr; + + + +assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); +assign select_high_immediate = op_andhi | op_orhi; +assign select_call_immediate = instruction[31]; + +assign high_immediate = {instruction[15:0], 16'h0000}; +assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; +assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; +assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + +assign immediate = select_high_immediate == 1'b1 + ? high_immediate + : extended_immediate; + +assign branch_offset = select_call_immediate == 1'b1 + ? (call_immediate[ (32-2)-1:0]) + : (branch_immediate[ (32-2)-1:0]); + +endmodule + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_minimal ( + clk_i, rst_i, - jtag_clk, - jtag_update, - jtag_reg_q, - jtag_reg_addr_q, - csr, - csr_write_enable, - csr_write_data, + + stall_a, + stall_f, + stall_d, stall_x, - jtag_read_data, - jtag_access_complete, - exception_q_w, - jtx_csr_read_data, - jrx_csr_read_data, - jtag_csr_write_enable, - jtag_csr_write_data, - jtag_csr, - jtag_read_enable, - jtag_write_enable, - jtag_write_data, - jtag_address, - jtag_break, - jtag_reset, - jtag_reg_d, - jtag_reg_addr_d + stall_m, + valid_f, + valid_d, + kill_f, + branch_predict_taken_d, + branch_predict_address_d, + + + + + + exception_m, + branch_taken_m, + branch_mispredict_taken_m, + branch_target_m, + + + + + + + + + + + + + + i_dat_i, + i_ack_i, + i_err_i, + i_rty_i, + + + + + + + + + + + + pc_f, + pc_d, + pc_x, + pc_m, + pc_w, + + + + + + + + + + + i_dat_o, + i_adr_o, + i_cyc_o, + i_sel_o, + i_stb_o, + i_we_o, + i_cti_o, + i_lock_o, + i_bte_o, + + + + + + + + + + + + + + + + + + + + instruction_f, + + + instruction_d ); + + + + + +parameter eba_reset = 32'h00000000; +parameter associativity = 1; +parameter sets = 512; +parameter bytes_per_line = 16; +parameter base_address = 0; +parameter limit = 0; + + +localparam eba_reset_minus_4 = eba_reset - 4; +localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; +localparam addr_offset_lsb = 2; +localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + + + + + + + input clk_i; input rst_i; -input jtag_clk; -input jtag_update; -input [ 7:0] jtag_reg_q; -input [2:0] jtag_reg_addr_q; -input [ (5-1):0] csr; -input csr_write_enable; -input [ (32-1):0] csr_write_data; + +input stall_a; +input stall_f; +input stall_d; input stall_x; -input [ 7:0] jtag_read_data; -input jtag_access_complete; -input exception_q_w; -output [ (32-1):0] jtx_csr_read_data; -wire [ (32-1):0] jtx_csr_read_data; -output [ (32-1):0] jrx_csr_read_data; -wire [ (32-1):0] jrx_csr_read_data; -output jtag_csr_write_enable; -reg jtag_csr_write_enable; -output [ (32-1):0] jtag_csr_write_data; -wire [ (32-1):0] jtag_csr_write_data; -output [ (5-1):0] jtag_csr; -wire [ (5-1):0] jtag_csr; -output jtag_read_enable; -reg jtag_read_enable; -output jtag_write_enable; -reg jtag_write_enable; -output [ 7:0] jtag_write_data; -wire [ 7:0] jtag_write_data; -output [ (32-1):0] jtag_address; -wire [ (32-1):0] jtag_address; -output jtag_break; -reg jtag_break; -output jtag_reset; -reg jtag_reset; -output [ 7:0] jtag_reg_d; -reg [ 7:0] jtag_reg_d; -output [2:0] jtag_reg_addr_d; -wire [2:0] jtag_reg_addr_d; -reg rx_update; -reg rx_update_r; -reg rx_update_r_r; -reg rx_update_r_r_r; -wire [ 7:0] rx_byte; -wire [2:0] rx_addr; -reg [ 7:0] uart_tx_byte; -reg uart_tx_valid; -reg [ 7:0] uart_rx_byte; -reg uart_rx_valid; -reg [ 3:0] command; -reg [ 7:0] jtag_byte_0; -reg [ 7:0] jtag_byte_1; -reg [ 7:0] jtag_byte_2; -reg [ 7:0] jtag_byte_3; -reg [ 7:0] jtag_byte_4; -reg processing; -reg [ 3:0] state; -assign jtag_csr_write_data = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_csr = jtag_byte_4[ (5-1):0]; -assign jtag_address = {jtag_byte_0, jtag_byte_1, jtag_byte_2, jtag_byte_3}; -assign jtag_write_data = jtag_byte_4; -assign jtag_reg_addr_d[1:0] = {uart_rx_valid, uart_tx_valid}; -assign jtag_reg_addr_d[2] = processing; -assign jtx_csr_read_data = {{ 32-9{1'b0}}, uart_tx_valid, 8'h00}; -assign jrx_csr_read_data = {{ 32-9{1'b0}}, uart_rx_valid, uart_rx_byte}; -assign rx_byte = jtag_reg_q; -assign rx_addr = jtag_reg_addr_q; -always @(posedge clk_i ) +input stall_m; +input valid_f; +input valid_d; +input kill_f; + +input branch_predict_taken_d; +input [ ((32-2)+2-1):2] branch_predict_address_d; + + + + + + +input exception_m; +input branch_taken_m; +input branch_mispredict_taken_m; +input [ ((32-2)+2-1):2] branch_target_m; + + + + + + + + + + + + + + + +input [ (32-1):0] i_dat_i; +input i_ack_i; +input i_err_i; +input i_rty_i; + + + + + + + + + + + + + + + +output [ ((32-2)+2-1):2] pc_f; +reg [ ((32-2)+2-1):2] pc_f; +output [ ((32-2)+2-1):2] pc_d; +reg [ ((32-2)+2-1):2] pc_d; +output [ ((32-2)+2-1):2] pc_x; +reg [ ((32-2)+2-1):2] pc_x; +output [ ((32-2)+2-1):2] pc_m; +reg [ ((32-2)+2-1):2] pc_m; +output [ ((32-2)+2-1):2] pc_w; +reg [ ((32-2)+2-1):2] pc_w; + + + + + + + + + + + + + + + +output [ (32-1):0] i_dat_o; + + + + +wire [ (32-1):0] i_dat_o; + + +output [ (32-1):0] i_adr_o; +reg [ (32-1):0] i_adr_o; +output i_cyc_o; +reg i_cyc_o; +output [ (4-1):0] i_sel_o; + + + + +wire [ (4-1):0] i_sel_o; + + +output i_stb_o; +reg i_stb_o; +output i_we_o; + + + + +wire i_we_o; + + +output [ (3-1):0] i_cti_o; +reg [ (3-1):0] i_cti_o; +output i_lock_o; +reg i_lock_o; +output [ (2-1):0] i_bte_o; +wire [ (2-1):0] i_bte_o; + + + + + + + + + + + + + + + + + + +output [ (32-1):0] instruction_f; +wire [ (32-1):0] instruction_f; + + +output [ (32-1):0] instruction_d; +reg [ (32-1):0] instruction_d; + + + + + +reg [ ((32-2)+2-1):2] pc_a; + + + + + + + + + + + + + + + + + + + + +reg [ (32-1):0] wb_data_f; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +function integer clogb2; +input [31:0] value; begin - if (rst_i == 1'b1) - begin - rx_update <= 1'b0; - rx_update_r <= 1'b0; - rx_update_r_r <= 1'b0; - rx_update_r_r_r <= 1'b0; - end - else - begin - rx_update <= jtag_update; - rx_update_r <= rx_update; - rx_update_r_r <= rx_update_r; - rx_update_r_r_r <= rx_update_r_r; - end + for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) + value = value >> 1; end -always @(posedge clk_i ) +endfunction + +function integer clogb2_v1; +input [31:0] value; +reg [31:0] i; +reg [31:0] temp; begin - if (rst_i == 1'b1) - begin - state <= 4'h0; - command <= 4'b0000; - jtag_reg_d <= 8'h00; - processing <= 1'b0; - jtag_csr_write_enable <= 1'b0; - jtag_read_enable <= 1'b0; - jtag_write_enable <= 1'b0; - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - uart_tx_byte <= 8'h00; - uart_tx_valid <= 1'b0; - uart_rx_byte <= 8'h00; - uart_rx_valid <= 1'b0; - end - else - begin - if ((csr_write_enable == 1'b1) && (stall_x == 1'b0)) - begin - case (csr) - 5'he: - begin - uart_tx_byte <= csr_write_data[ 7:0]; - uart_tx_valid <= 1'b1; - end - 5'hf: - begin - uart_rx_valid <= 1'b0; - end - endcase - end - if (exception_q_w == 1'b1) - begin - jtag_break <= 1'b0; - jtag_reset <= 1'b0; - end - case (state) - 4'h0: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - command <= rx_byte[7:4]; - case (rx_addr) - 3'b000: - begin - case (rx_byte[7:4]) - 4'b0001: - state <= 4'h1; - 4'b0011: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 4'h6; - end - 4'b0010: - state <= 4'h1; - 4'b0100: - begin - {jtag_byte_2, jtag_byte_3} <= {jtag_byte_2, jtag_byte_3} + 1'b1; - state <= 5; - end - 4'b0101: - state <= 4'h1; - 4'b0110: - begin - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - jtag_break <= 1'b1; - end - 4'b0111: - begin - uart_rx_valid <= 1'b0; - uart_tx_valid <= 1'b0; - jtag_reset <= 1'b1; - end - endcase - end - 3'b001: - begin - uart_rx_byte <= rx_byte; - uart_rx_valid <= 1'b1; - end - 3'b010: - begin - jtag_reg_d <= uart_tx_byte; - uart_tx_valid <= 1'b0; - end - default: - ; - endcase - end - end - 4'h1: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_0 <= rx_byte; - state <= 4'h2; - end - end - 4'h2: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_1 <= rx_byte; - state <= 4'h3; - end - end - 4'h3: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_2 <= rx_byte; - state <= 4'h4; - end - end - 4'h4: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_3 <= rx_byte; - if (command == 4'b0001) - state <= 4'h6; - else - state <= 4'h5; - end - end - 4'h5: - begin - if ((~rx_update_r_r_r & rx_update_r_r) == 1'b1) - begin - jtag_byte_4 <= rx_byte; - state <= 4'h6; - end - end - 4'h6: - begin - case (command) - 4'b0001, - 4'b0011: - begin - jtag_read_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0010, - 4'b0100: - begin - jtag_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h7; - end - 4'b0101: - begin - jtag_csr_write_enable <= 1'b1; - processing <= 1'b1; - state <= 4'h8; - end - endcase - end - 4'h7: - begin - if (jtag_access_complete == 1'b1) - begin - jtag_read_enable <= 1'b0; - jtag_reg_d <= jtag_read_data; - jtag_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - end - 4'h8: - begin - jtag_csr_write_enable <= 1'b0; - processing <= 1'b0; - state <= 4'h0; - end - endcase + temp = 0; + i = 0; + for (i = 0; temp < value; i = i + 1) + temp = 1<<i; + clogb2_v1 = i-1; +end +endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(*) +begin + + + + + + + + if (branch_taken_m == 1'b1) + if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) + pc_a = pc_x; + else + pc_a = branch_target_m; + + + + + + else + if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) + pc_a = branch_predict_address_d; + else + + + + + + + pc_a = pc_f + 1'b1; +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign instruction_f = wb_data_f; + + + + + + + + + + + + +assign i_dat_o = 32'd0; +assign i_we_o = 1'b0; +assign i_sel_o = 4'b1111; + + +assign i_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +always @(posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + pc_f <= eba_reset_minus_4[ ((32-2)+2-1):2]; + pc_d <= { (32-2){1'b0}}; + pc_x <= { (32-2){1'b0}}; + pc_m <= { (32-2){1'b0}}; + pc_w <= { (32-2){1'b0}}; + end + else + begin + if (stall_f == 1'b0) + pc_f <= pc_a; + if (stall_d == 1'b0) + pc_d <= pc_f; + if (stall_x == 1'b0) + pc_x <= pc_d; + if (stall_m == 1'b0) + pc_m <= pc_x; + pc_w <= pc_m; end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + i_adr_o <= { 32{1'b0}}; + i_cti_o <= 3'b111; + i_lock_o <= 1'b0; + wb_data_f <= { 32{1'b0}}; + + + + + end + else + begin + + if (i_cyc_o == 1'b1) + begin + + if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) + begin + + i_cyc_o <= 1'b0; + i_stb_o <= 1'b0; + + wb_data_f <= i_dat_i; + end + + + + + + + + + end + else + begin + + if ( (stall_a == 1'b0) + + + + + ) + begin + + + + + + i_adr_o <= {pc_a, 2'b00}; + i_cyc_o <= 1'b1; + i_stb_o <= 1'b1; + + + + + end + else + begin + if ( (stall_a == 1'b0) + + + + + ) + begin + + + + + end + end + end + end + end + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + endmodule -module lm32_interrupt_medium_icache_debug ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_minimal ( + clk_i, rst_i, + interrupt, + stall_x, - non_debug_exception, - debug_exception, + + + + + + exception, + + eret_q_x, - bret_q_x, + + + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; -input non_debug_exception; -input debug_exception; + + + + + + +input exception; + + input eret_q_x; -input bret_q_x; -input [ (5-1):0] csr; + + + + + +input [ (4 -1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; -reg bie; + + + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, - bie, + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + eie, ie }; - 5'h2: csr_read_data = ip; - 5'h1: csr_read_data = im; + 4 'h2: csr_read_data = ip; + 4 'h1: csr_read_data = im; default: csr_read_data = { 32{1'bx}}; endcase end end else begin + always @(*) begin case (csr) - 5'h0: csr_read_data = {{ 32-3{1'b0}}, - bie, + 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + + 1'b0, + + eie, ie }; - 5'h2: csr_read_data = ip; + 4 'h2: csr_read_data = ip; default: csr_read_data = { 32{1'bx}}; endcase end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; - bie <= 1'b0; + + + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; - if (non_debug_exception == 1'b1) + + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end - else if (debug_exception == 1'b1) - begin - bie <= ie; - ie <= 1'b0; - end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end - else if (bret_q_x == 1'b1) - ie <= bie; + + + + + + + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - bie <= csr_write_data[2]; + + + + end - if (csr == 5'h1) + if (csr == 4 'h1) im <= csr_write_data[interrupts-1:0]; - if (csr == 5'h2) + if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -18762,49 +88559,80 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; - bie <= 1'b0; + + + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; - if (non_debug_exception == 1'b1) + + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end - else if (debug_exception == 1'b1) - begin - bie <= ie; - ie <= 1'b0; - end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end - else if (bret_q_x == 1'b1) - ie <= bie; + + + + + + + else if (csr_write_enable == 1'b1) begin - if (csr == 5'h0) + + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; - bie <= csr_write_data[2]; + + + + end - if (csr == 5'h2) + if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; end end @@ -18812,28 +88640,627 @@ always @(posedge clk_i ) end end endgenerate + endmodule -module lm32_top_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_top_wr_node ( + clk_i, rst_i, + + interrupt, - I_DAT_I, - I_ACK_I, - I_ERR_I, - I_RTY_I, + + + + + + + + + + + + + + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, - I_DAT_O, - I_ADR_O, - I_CYC_O, - I_SEL_O, - I_STB_O, - I_WE_O, - I_CTI_O, - I_LOCK_O, - I_BTE_O, + + + + + + + + + + + + + + + + + + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -18844,37 +89271,77 @@ module lm32_top_minimal ( D_LOCK_O, D_BTE_O ); + parameter eba_reset = 32'h00000000; parameter sdb_address = 32'h00000000; + + + + input clk_i; input rst_i; + + input [ (32-1):0] interrupt; -input [ (32-1):0] I_DAT_I; -input I_ACK_I; -input I_ERR_I; -input I_RTY_I; + + + + + + + + + + + + + + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; -output [ (32-1):0] I_DAT_O; -wire [ (32-1):0] I_DAT_O; -output [ (32-1):0] I_ADR_O; -wire [ (32-1):0] I_ADR_O; -output I_CYC_O; -wire I_CYC_O; -output [ (4-1):0] I_SEL_O; -wire [ (4-1):0] I_SEL_O; -output I_STB_O; -wire I_STB_O; -output I_WE_O; -wire I_WE_O; -output [ (3-1):0] I_CTI_O; -wire [ (3-1):0] I_CTI_O; -output I_LOCK_O; -wire I_LOCK_O; -output [ (2-1):0] I_BTE_O; -wire [ (2-1):0] I_BTE_O; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -18893,6 +89360,71 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -18900,6 +89432,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -18912,31 +89445,97 @@ begin clogb2_v1 = i-1; end endfunction -lm32_cpu_minimal + + + + + + + + +lm32_cpu_wr_node #( .eba_reset(eba_reset), .sdb_address(sdb_address) ) cpu ( + .clk_i (clk_i), + + + + .rst_i (rst_i), + + + .interrupt (interrupt), - .I_DAT_I (I_DAT_I), - .I_ACK_I (I_ACK_I), - .I_ERR_I (I_ERR_I), - .I_RTY_I (I_RTY_I), + + + + + + + + + + + + + + + + + + + + + + + + + .D_DAT_I (D_DAT_I), .D_ACK_I (D_ACK_I), .D_ERR_I (D_ERR_I), .D_RTY_I (D_RTY_I), - .I_DAT_O (I_DAT_O), - .I_ADR_O (I_ADR_O), - .I_CYC_O (I_CYC_O), - .I_SEL_O (I_SEL_O), - .I_STB_O (I_STB_O), - .I_WE_O (I_WE_O), - .I_CTI_O (I_CTI_O), - .I_LOCK_O (I_LOCK_O), - .I_BTE_O (I_BTE_O), + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .D_DAT_O (D_DAT_O), .D_ADR_O (D_ADR_O), .D_CYC_O (D_CYC_O), @@ -18947,33 +89546,520 @@ lm32_cpu_minimal .D_LOCK_O (D_LOCK_O), .D_BTE_O (D_BTE_O) ); + + + + + + + + + + + + + + + + + endmodule -module lm32_mc_arithmetic_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_mc_arithmetic_wr_node ( + clk_i, rst_i, stall_d, kill_x, + + + divide_d, + modulus_d, + + + + + + + + + + + + operand_0_d, operand_1_d, + result_x, + + + divide_by_zero_x, + + stall_request_x ); + + + + + input clk_i; input rst_i; input stall_d; input kill_x; + + +input divide_d; +input modulus_d; + + + + + + + + + + + + input [ (32-1):0] operand_0_d; input [ (32-1):0] operand_1_d; + + + + + output [ (32-1):0] result_x; reg [ (32-1):0] result_x; + + +output divide_by_zero_x; +reg divide_by_zero_x; + + output stall_request_x; wire stall_request_x; + + + + + reg [ (32-1):0] p; reg [ (32-1):0] a; reg [ (32-1):0] b; + + +wire [32:0] t; + + + reg [ 2:0] state; reg [5:0] cycles; + + + + + + + + + + + + assign stall_request_x = state != 3'b000; + + + + +assign t = {p[ 32-2:0], a[ 32-1]} - b; + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -18982,11 +90068,25 @@ begin p <= { 32{1'b0}}; a <= { 32{1'b0}}; b <= { 32{1'b0}}; + + + + + + + divide_by_zero_x <= 1'b0; + + result_x <= { 32{1'b0}}; state <= 3'b000; end else begin + + + divide_by_zero_x <= 1'b0; + + case (state) 3'b000: begin @@ -18996,33 +90096,612 @@ begin p <= 32'b0; a <= operand_0_d; b <= operand_1_d; + + + if (divide_d == 1'b1) + state <= 3'b011 ; + if (modulus_d == 1'b1) + state <= 3'b010 ; + + + + + + + + + + + + + + + + + + + + + + + + + + end end + + + 3'b011 : + begin + if (t[32] == 1'b0) + begin + p <= t[31:0]; + a <= {a[ 32-2:0], 1'b1}; + end + else + begin + p <= {p[ 32-2:0], a[ 32-1]}; + a <= {a[ 32-2:0], 1'b0}; + end + result_x <= a; + if ((cycles == 32'd0) || (kill_x == 1'b1)) + begin + + divide_by_zero_x <= b == { 32{1'b0}}; + state <= 3'b000; + end + cycles <= cycles - 1'b1; + end + 3'b010 : + begin + if (t[32] == 1'b0) + begin + p <= t[31:0]; + a <= {a[ 32-2:0], 1'b1}; + end + else + begin + p <= {p[ 32-2:0], a[ 32-1]}; + a <= {a[ 32-2:0], 1'b0}; + end + result_x <= p; + if ((cycles == 32'd0) || (kill_x == 1'b1)) + begin + + divide_by_zero_x <= b == { 32{1'b0}}; + state <= 3'b000; + end + cycles <= cycles - 1'b1; + end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endcase end end + endmodule -module lm32_cpu_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_cpu_wr_node ( + clk_i, + + + + rst_i, + + + interrupt, - I_DAT_I, - I_ACK_I, - I_ERR_I, - I_RTY_I, + + + + + + + + + + + + + + + + + + + + + + + + + D_DAT_I, D_ACK_I, D_ERR_I, D_RTY_I, - I_DAT_O, - I_ADR_O, - I_CYC_O, - I_SEL_O, - I_STB_O, - I_WE_O, - I_CTI_O, - I_LOCK_O, - I_BTE_O, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iram_i_adr_o, + iram_i_dat_i, + iram_i_en_o, + iram_d_adr_o, + iram_d_dat_o, + iram_d_dat_i, + iram_d_sel_o, + iram_d_we_o, + iram_d_en_o, + + + + + D_DAT_O, D_ADR_O, D_CYC_O, @@ -19032,51 +90711,184 @@ module lm32_cpu_minimal ( D_CTI_O, D_LOCK_O, D_BTE_O + + ); + + + + + parameter eba_reset = 32'h00000000; + + + + parameter sdb_address = 32'h00000000; + + + + + + + + + parameter icache_associativity = 1; parameter icache_sets = 512; parameter icache_bytes_per_line = 16; parameter icache_base_address = 0; parameter icache_limit = 0; + + + + + + + + + + + parameter dcache_associativity = 1; parameter dcache_sets = 512; parameter dcache_bytes_per_line = 16; parameter dcache_base_address = 0; parameter dcache_limit = 0; + + + + + + + parameter watchpoints = 0; + + + + + + parameter breakpoints = 0; + + + + + parameter interrupts = 32; + + + + + + + + + input clk_i; + + + + input rst_i; + + + input [ (32-1):0] interrupt; -input [ (32-1):0] I_DAT_I; -input I_ACK_I; -input I_ERR_I; -input I_RTY_I; + + + + + + + + + + + + + + + + + + + + + + + + + input [ (32-1):0] D_DAT_I; input D_ACK_I; input D_ERR_I; input D_RTY_I; -output [ (32-1):0] I_DAT_O; -wire [ (32-1):0] I_DAT_O; -output [ (32-1):0] I_ADR_O; -wire [ (32-1):0] I_ADR_O; -output I_CYC_O; -wire I_CYC_O; -output [ (4-1):0] I_SEL_O; -wire [ (4-1):0] I_SEL_O; -output I_STB_O; -wire I_STB_O; -output I_WE_O; -wire I_WE_O; -output [ (3-1):0] I_CTI_O; -wire [ (3-1):0] I_CTI_O; -output I_LOCK_O; -wire I_LOCK_O; -output [ (2-1):0] I_BTE_O; -wire [ (2-1):0] I_BTE_O; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ (32-1):0] D_DAT_O; wire [ (32-1):0] D_DAT_O; output [ (32-1):0] D_ADR_O; @@ -19095,11 +90907,33 @@ output D_LOCK_O; wire D_LOCK_O; output [ (2-1):0] D_BTE_O; wire [ (2-1):0] D_BTE_O; + + + + output [31:0] iram_i_adr_o, iram_d_adr_o; + output [31:0] iram_d_dat_o; + input [31:0] iram_i_dat_i, iram_d_dat_i; + output [3:0] iram_d_sel_o; + output iram_d_en_o, iram_i_en_o, iram_d_we_o; + + + + + + + + + + + + + reg valid_f; reg valid_d; reg valid_x; reg valid_m; reg valid_w; + wire q_x; wire [ (32-1):0] immediate_d; wire load_d; @@ -19136,20 +90970,57 @@ reg [ ((32-2)+2-1):2] branch_target_x; reg [ ((32-2)+2-1):2] branch_target_m; wire [ 0:0] d_result_sel_0_d; wire [ 1:0] d_result_sel_1_d; + wire x_result_sel_csr_d; reg x_result_sel_csr_x; -wire x_result_sel_shift_d; -reg x_result_sel_shift_x; + + +wire q_d; +wire x_result_sel_mc_arith_d; +reg x_result_sel_mc_arith_x; + + + + + + + + + +wire x_result_sel_sext_d; +reg x_result_sel_sext_x; + + wire x_result_sel_logic_d; + + + + + wire x_result_sel_add_d; reg x_result_sel_add_x; wire m_result_sel_compare_d; reg m_result_sel_compare_x; reg m_result_sel_compare_m; + + +wire m_result_sel_shift_d; +reg m_result_sel_shift_x; +reg m_result_sel_shift_m; + + wire w_result_sel_load_d; reg w_result_sel_load_x; reg w_result_sel_load_m; reg w_result_sel_load_w; + + +wire w_result_sel_mul_d; +reg w_result_sel_mul_x; +reg w_result_sel_mul_m; +reg w_result_sel_mul_w; + + wire x_bypass_enable_d; reg x_bypass_enable_x; wire m_bypass_enable_d; @@ -19176,89 +91047,383 @@ wire [ (4 -1):0] csr_d; reg [ (4 -1):0] csr_x; wire [ (3-1):0] condition_d; reg [ (3-1):0] condition_x; + + + + + wire scall_d; reg scall_x; wire eret_d; reg eret_x; wire eret_q_x; + + + + + + + + + + + + + + + wire csr_write_enable_d; reg csr_write_enable_x; wire csr_write_enable_q_x; + + + + + + + + + + + + + reg [ (32-1):0] d_result_0; reg [ (32-1):0] d_result_1; reg [ (32-1):0] x_result; reg [ (32-1):0] m_result; reg [ (32-1):0] w_result; + reg [ (32-1):0] operand_0_x; reg [ (32-1):0] operand_1_x; reg [ (32-1):0] store_operand_x; reg [ (32-1):0] operand_m; reg [ (32-1):0] operand_w; + + + + reg [ (32-1):0] reg_data_live_0; reg [ (32-1):0] reg_data_live_1; reg use_buf; reg [ (32-1):0] reg_data_buf_0; reg [ (32-1):0] reg_data_buf_1; + + + + + + + + wire [ (32-1):0] reg_data_0; wire [ (32-1):0] reg_data_1; reg [ (32-1):0] bypass_data_0; reg [ (32-1):0] bypass_data_1; wire reg_write_enable_q_w; + reg interlock; + wire stall_a; wire stall_f; wire stall_d; wire stall_x; wire stall_m; + + wire adder_op_d; reg adder_op_x; reg adder_op_x_n; wire [ (32-1):0] adder_result_x; wire adder_overflow_x; wire adder_carry_n_x; + + wire [ 3:0] logic_op_d; reg [ 3:0] logic_op_x; wire [ (32-1):0] logic_result_x; -wire [ (32-1):0] shifter_result_x; + + + + +wire [ (32-1):0] sextb_result_x; +wire [ (32-1):0] sexth_result_x; +wire [ (32-1):0] sext_result_x; + + + + + + + + + + + +wire direction_d; +reg direction_x; +wire [ (32-1):0] shifter_result_m; + + + + + + + + + + + + + + + + + +wire [ (32-1):0] multiplier_result_w; + + + + + + + + + + + +wire divide_d; +wire divide_q_d; +wire modulus_d; +wire modulus_q_d; +wire divide_by_zero_x; + + + + + + +wire mc_stall_request_x; +wire [ (32-1):0] mc_result_x; + + + + + + wire [ (32-1):0] interrupt_csr_read_data_x; + + wire [ (32-1):0] cfg; wire [ (32-1):0] cfg2; + + + + reg [ (32-1):0] csr_read_data_x; + + wire [ ((32-2)+2-1):2] pc_f; wire [ ((32-2)+2-1):2] pc_d; wire [ ((32-2)+2-1):2] pc_x; wire [ ((32-2)+2-1):2] pc_m; wire [ ((32-2)+2-1):2] pc_w; + + + + + + wire [ (32-1):0] instruction_f; + + + + wire [ (32-1):0] instruction_d; + + + + + + + + + + + + + + + + + + + wire [ (32-1):0] load_data_w; wire stall_wb_load; + + + + + + + + + + + + + + + + + + + + + + + + + wire raw_x_0; wire raw_x_1; wire raw_m_0; wire raw_m_1; wire raw_w_0; wire raw_w_1; + + wire cmp_zero; wire cmp_negative; wire cmp_overflow; wire cmp_carry_n; reg condition_met_x; reg condition_met_m; + + + + wire branch_taken_m; + wire kill_f; wire kill_d; wire kill_x; wire kill_m; wire kill_w; + reg [ (32-2)+2-1:8] eba; + + + + reg [ (3-1):0] eid_x; + + + + + + + + + + + + + + + + + + + + + + + + + wire exception_x; reg exception_m; reg exception_w; wire exception_q_w; + + + + + + + + + + + wire interrupt_exception; + + + + + + + + + + + + + + +wire divide_by_zero_exception; + + wire system_call_exception; + + + + + + + + + wire iram_stall_request_x; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -19266,6 +91431,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -19278,7 +91444,16 @@ begin clogb2_v1 = i-1; end endfunction -lm32_instruction_unit_minimal #( + + + + + + + + + +lm32_instruction_unit_wr_node #( .eba_reset (eba_reset), .associativity (icache_associativity), .sets (icache_sets), @@ -19286,8 +91461,10 @@ lm32_instruction_unit_minimal #( .base_address (icache_base_address), .limit (icache_limit) ) instruction_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_f (stall_f), .stall_d (stall_d), @@ -19298,41 +91475,138 @@ lm32_instruction_unit_minimal #( .kill_f (kill_f), .branch_predict_taken_d (branch_predict_taken_d), .branch_predict_address_d (branch_predict_address_d), + + + + + .exception_m (exception_m), .branch_taken_m (branch_taken_m), .branch_mispredict_taken_m (branch_mispredict_taken_m), .branch_target_m (branch_target_m), - .i_dat_i (I_DAT_I), - .i_ack_i (I_ACK_I), - .i_err_i (I_ERR_I), - .i_rty_i (I_RTY_I), + + + + + + + + + + + + + + + + + + + + + + + + + + + .pc_f (pc_f), .pc_d (pc_d), .pc_x (pc_x), .pc_m (pc_m), .pc_w (pc_w), - .i_dat_o (I_DAT_O), - .i_adr_o (I_ADR_O), - .i_cyc_o (I_CYC_O), - .i_sel_o (I_SEL_O), - .i_stb_o (I_STB_O), - .i_we_o (I_WE_O), - .i_cti_o (I_CTI_O), - .i_lock_o (I_LOCK_O), - .i_bte_o (I_BTE_O), + + + + + + + + + + + + + + + + + + + + + + + + .iram_i_adr_o(iram_i_adr_o), + .iram_i_dat_i(iram_i_dat_i), + .iram_i_en_o(iram_i_en_o), + + + + + + + + + + + + + + .instruction_f (instruction_f), + + + + .instruction_d (instruction_d) + + + ); -lm32_decoder_minimal decoder ( + + +lm32_decoder_wr_node decoder ( + .instruction (instruction_d), + .d_result_sel_0 (d_result_sel_0_d), .d_result_sel_1 (d_result_sel_1_d), .x_result_sel_csr (x_result_sel_csr_d), - .x_result_sel_shift (x_result_sel_shift_d), + + + .x_result_sel_mc_arith (x_result_sel_mc_arith_d), + + + + + + + + + .x_result_sel_sext (x_result_sel_sext_d), + + .x_result_sel_logic (x_result_sel_logic_d), + + + + .x_result_sel_add (x_result_sel_add_d), .m_result_sel_compare (m_result_sel_compare_d), + + + .m_result_sel_shift (m_result_sel_shift_d), + + .w_result_sel_load (w_result_sel_load_d), + + + .w_result_sel_mul (w_result_sel_mul_d), + + .x_bypass_enable (x_bypass_enable_d), .m_bypass_enable (m_bypass_enable_d), .read_enable_0 (read_enable_0_d), @@ -19349,24 +91623,60 @@ lm32_decoder_minimal decoder ( .sign_extend (sign_extend_d), .adder_op (adder_op_d), .logic_op (logic_op_d), + + + .direction (direction_d), + + + + + + + + + + + + + + .divide (divide_d), + .modulus (modulus_d), + + .branch (branch_d), .bi_unconditional (bi_unconditional), .bi_conditional (bi_conditional), .branch_reg (branch_reg_d), .condition (condition_d), + + + + .scall (scall_d), .eret (eret_d), + + + + + + + + .csr_write_enable (csr_write_enable_d) ); -lm32_load_store_unit_minimal #( + + +lm32_load_store_unit_wr_node #( .associativity (dcache_associativity), .sets (dcache_sets), .bytes_per_line (dcache_bytes_per_line), .base_address (dcache_base_address), .limit (dcache_limit) ) load_store_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .stall_a (stall_a), .stall_x (stall_x), .stall_m (stall_m), @@ -19385,12 +91695,40 @@ lm32_load_store_unit_minimal #( .store_q_m (store_q_m), .sign_extend_x (sign_extend_x), .size_x (size_x), + + + + + + + + .iram_d_adr_o(iram_d_adr_o), + .iram_d_dat_o(iram_d_dat_o), + .iram_d_dat_i(iram_d_dat_i), + .iram_d_sel_o(iram_d_sel_o), + .iram_d_we_o(iram_d_we_o), + .iram_d_en_o(iram_d_en_o), + .iram_stall_request_x(iram_stall_request_x), + + + + .d_dat_i (D_DAT_I), .d_ack_i (D_ACK_I), .d_err_i (D_ERR_I), .d_rty_i (D_RTY_I), + + + + + + + + + .load_data_w (load_data_w), .stall_wb_load (stall_wb_load), + .d_dat_o (D_DAT_O), .d_adr_o (D_ADR_O), .d_cyc_o (D_CYC_O), @@ -19401,38 +91739,257 @@ lm32_load_store_unit_minimal #( .d_lock_o (D_LOCK_O), .d_bte_o (D_BTE_O) ); + + lm32_adder adder ( + .adder_op_x (adder_op_x), .adder_op_x_n (adder_op_x_n), .operand_0_x (operand_0_x), .operand_1_x (operand_1_x), + .adder_result_x (adder_result_x), .adder_carry_n_x (adder_carry_n_x), .adder_overflow_x (adder_overflow_x) ); + + lm32_logic_op logic_op ( + .logic_op_x (logic_op_x), .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + .logic_result_x (logic_result_x) ); -lm32_interrupt_minimal interrupt_unit ( + + + + +lm32_shifter shifter ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .direction_x (direction_x), + .sign_extend_x (sign_extend_x), + .operand_0_x (operand_0_x), + .operand_1_x (operand_1_x), + + .shifter_result_m (shifter_result_m) + ); + + + + + + +lm32_multiplier multiplier ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_x (stall_x), + .stall_m (stall_m), + .operand_0 (d_result_0), + .operand_1 (d_result_1), + + .result (multiplier_result_w) + ); + + + + + + +lm32_mc_arithmetic_wr_node mc_arithmetic ( + + .clk_i (clk_i), + .rst_i (rst_i), + .stall_d (stall_d), + .kill_x (kill_x), + + + .divide_d (divide_q_d), + .modulus_d (modulus_q_d), + + + + + + + + + + + + + .operand_0_d (d_result_0), + .operand_1_d (d_result_1), + + .result_x (mc_result_x), + + + .divide_by_zero_x (divide_by_zero_x), + + + .stall_request_x (mc_stall_request_x) + ); + + + + + + +lm32_interrupt_wr_node interrupt_unit ( + .clk_i (clk_i), .rst_i (rst_i), + .interrupt (interrupt), + .stall_x (stall_x), + + + + + .exception (exception_q_w), + + .eret_q_x (eret_q_x), + + + + .csr (csr_x), .csr_write_data (operand_1_x), .csr_write_enable (csr_write_enable_q_x), + .interrupt_exception (interrupt_exception), + .csr_read_data (interrupt_csr_read_data_x) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wire [31:0] regfile_data_0, regfile_data_1; reg [31:0] w_result_d; reg regfile_raw_0, regfile_raw_0_nxt; reg regfile_raw_1, regfile_raw_1_nxt; + + + + + always @(reg_write_enable_q_w or write_idx_w or instruction_f) begin if (reg_write_enable_q_w @@ -19440,22 +91997,39 @@ lm32_interrupt_minimal interrupt_unit ( regfile_raw_0_nxt = 1'b1; else regfile_raw_0_nxt = 1'b0; + if (reg_write_enable_q_w && (write_idx_w == instruction_f[20:16])) regfile_raw_1_nxt = 1'b1; else regfile_raw_1_nxt = 1'b0; end + + + + + + always @(regfile_raw_0 or w_result_d or regfile_data_0) if (regfile_raw_0) reg_data_live_0 = w_result_d; else reg_data_live_0 = regfile_data_0; + + + + + + always @(regfile_raw_1 or w_result_d or regfile_data_1) if (regfile_raw_1) reg_data_live_1 = w_result_d; else reg_data_live_1 = regfile_data_1; + + + + always @(posedge clk_i ) if (rst_i == 1'b1) begin @@ -19469,22 +92043,31 @@ lm32_interrupt_minimal interrupt_unit ( regfile_raw_1 <= regfile_raw_1_nxt; w_result_d <= w_result; end + + + + + lm32_dp_ram #( + .addr_depth(1<<5), .addr_width(5), .data_width(32) ) reg_0 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[25:21]), + .rdata_o (regfile_data_0) ); + lm32_dp_ram #( .addr_depth(1<<5), @@ -19493,22 +92076,118 @@ lm32_interrupt_minimal interrupt_unit ( ) reg_1 ( + .clk_i (clk_i), .rst_i (rst_i), .we_i (reg_write_enable_q_w), .wdata_i (w_result), .waddr_i (write_idx_w), .raddr_i (instruction_f[20:16]), + .rdata_o (regfile_data_1) ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; + + + + + + + + + + + + assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == 1'b1); assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == 1'b1); assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == 1'b1); assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == 1'b1); assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == 1'b1); assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == 1'b1); + + always @(*) begin if ( ( (x_bypass_enable_x == 1'b0) @@ -19526,6 +92205,8 @@ begin else interlock = 1'b0; end + + always @(*) begin if (raw_x_0 == 1'b1) @@ -19537,6 +92218,8 @@ begin else bypass_data_0 = reg_data_0; end + + always @(*) begin if (raw_x_1 == 1'b1) @@ -19548,10 +92231,25 @@ begin else bypass_data_1 = reg_data_1; end + + + + + + + assign branch_predict_d = bi_unconditional | bi_conditional; assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); + + assign branch_target_d = pc_d + branch_offset_d; + + + + assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; + + always @(*) begin d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; @@ -19562,7 +92260,30 @@ begin default: d_result_1 = { 32{1'bx}}; endcase end -assign shifter_result_x = {operand_0_x[ 32-1] & sign_extend_x, operand_0_x[ 32-1:1]}; + + + + + + + + + + + +assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; +assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; +assign sext_result_x = size_x == 2'b00 ? sextb_result_x : sexth_result_x; + + + + + + + + + + assign cmp_zero = operand_0_x == operand_1_x; assign cmp_negative = adder_result_x[ 32-1]; assign cmp_overflow = adder_overflow_x; @@ -19581,23 +92302,69 @@ begin default: condition_met_x = 1'bx; endcase end + + always @(*) begin x_result = x_result_sel_add_x ? adder_result_x : x_result_sel_csr_x ? csr_read_data_x - : x_result_sel_shift_x ? shifter_result_x + + + : x_result_sel_sext_x ? sext_result_x + + + + + + + + + + + + + : x_result_sel_mc_arith_x ? mc_result_x + + : logic_result_x; end + + always @(*) begin m_result = m_result_sel_compare_m ? {{ 32-1{1'b0}}, condition_met_m} + + + : m_result_sel_shift_m ? shifter_result_m + + : operand_m; end + + always @(*) begin w_result = w_result_sel_load_w ? load_data_w + + + : w_result_sel_mul_w ? multiplier_result_w + + : operand_w; end + + + + + + + + + + + + + assign branch_taken_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -19612,9 +92379,13 @@ assign branch_taken_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign branch_mispredict_taken_m = (condition_met_m == 1'b0) && (branch_predict_m == 1'b1) && (branch_predict_taken_m == 1'b1); + + assign branch_flushX_m = (stall_m == 1'b0) && ( ( (branch_m == 1'b1) && (valid_m == 1'b1) @@ -19627,41 +92398,233 @@ assign branch_flushX_m = (stall_m == 1'b0) ) || (exception_m == 1'b1) ); + + assign kill_f = ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) || (branch_taken_m == 1'b1) + + + + + + + + + + + + ; assign kill_d = (branch_taken_m == 1'b1) + + + + + + + + + + + + ; assign kill_x = (branch_flushX_m == 1'b1) + + + + ; assign kill_m = 1'b0 + + + + ; assign kill_w = 1'b0 + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +assign divide_by_zero_exception = divide_by_zero_x == 1'b1; + + + assign system_call_exception = ( (scall_x == 1'b1) + + + + ); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign exception_x = (system_call_exception == 1'b1) + + + + + + + + || (divide_by_zero_exception == 1'b1) + + + + || ( (interrupt_exception == 1'b1) + + + + + + + + + ) + + ; + + + + always @(*) begin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (divide_by_zero_exception == 1'b1) + eid_x = 3'h5; + else + + + + if ( (interrupt_exception == 1'b1) + + + + ) eid_x = 3'h6; else + + eid_x = 3'h7; end + + + assign stall_a = (stall_f == 1'b1); + assign stall_f = (stall_d == 1'b1); + assign stall_d = (stall_x == 1'b1) || ( (interlock == 1'b1) && (kill_d == 1'b0) ) || ( ( (eret_d == 1'b1) || (scall_d == 1'b1) + + + + ) && ( (load_q_x == 1'b1) || (load_q_m == 1'b1) @@ -19671,76 +92634,346 @@ assign stall_d = (stall_x == 1'b1) ) && (kill_d == 1'b0) ) + + + + + + + + + + + + + + || ( (csr_write_enable_d == 1'b1) && (load_q_x == 1'b1) ) + + + + + || ( (iram_stall_request_x == 1'b1) + && ( (load_d == 1'b1) + + ) + ) + + ; + assign stall_x = (stall_m == 1'b1) + + + || ( (mc_stall_request_x == 1'b1) + && (kill_x == 1'b0) + ) + + + + ; + assign stall_m = (stall_wb_load == 1'b1) + + + + || ( (D_CYC_O == 1'b1) && ( (store_m == 1'b1) + + + + + + + + + + + + + + + || ((store_x == 1'b1) && (interrupt_exception == 1'b1)) + + || (load_m == 1'b1) || (load_x == 1'b1) ) ) - || (I_CYC_O == 1'b1) + + + + + + + + + + + + + + + + + + + + + + + ; + + + + +assign q_d = (valid_d == 1'b1) && (kill_d == 1'b0); + + + + + + + + + + + + + +assign divide_q_d = (divide_d == 1'b1) && (q_d == 1'b1); +assign modulus_q_d = (modulus_d == 1'b1) && (q_d == 1'b1); + + assign q_x = (valid_x == 1'b1) && (kill_x == 1'b0); assign csr_write_enable_q_x = (csr_write_enable_x == 1'b1) && (q_x == 1'b1); assign eret_q_x = (eret_x == 1'b1) && (q_x == 1'b1); + + + + assign load_q_x = (load_x == 1'b1) && (q_x == 1'b1) + + + + ; assign store_q_x = (store_x == 1'b1) && (q_x == 1'b1) + + + + ; + + + + assign q_m = (valid_m == 1'b1) && (kill_m == 1'b0) && (exception_m == 1'b0); assign load_q_m = (load_m == 1'b1) && (q_m == 1'b1); assign store_q_m = (store_m == 1'b1) && (q_m == 1'b1); + + + + + assign exception_q_w = ((exception_w == 1'b1) && (valid_w == 1'b1)); + + + assign write_enable_q_x = (write_enable_x == 1'b1) && (valid_x == 1'b1) && (branch_flushX_m == 1'b0); assign write_enable_q_m = (write_enable_m == 1'b1) && (valid_m == 1'b1); assign write_enable_q_w = (write_enable_w == 1'b1) && (valid_w == 1'b1); + assign reg_write_enable_q_w = (write_enable_w == 1'b1) && (kill_w == 1'b0) && (valid_w == 1'b1); + + assign cfg = { 6'h02, watchpoints[3:0], breakpoints[3:0], interrupts[5:0], + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, + + + + + + 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0 + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + 1'b1, + + + + + + + 1'b1 + + + + }; + assign cfg2 = { 30'b0, - 1'b0, + + + 1'b1, + + + + + + + + 1'b0 + + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign csr_d = read_idx_0_d[ (4 -1):0]; + + always @(*) begin case (csr_x) + + 4 'h0, 4 'h1, 4 'h2: csr_read_data_x = interrupt_csr_read_data_x; + + + + + + 4 'h6: csr_read_data_x = cfg; 4 'h7: csr_read_data_x = {eba, 8'h00}; + + + + + + + + + 4 'ha: csr_read_data_x = cfg2; 4 'hb: csr_read_data_x = sdb_address; + default: csr_read_data_x = { 32{1'bx}}; endcase end + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -19749,8 +92982,109 @@ begin begin if ((csr_write_enable_q_x == 1'b1) && (csr_x == 4 'h7) && (stall_x == 1'b0)) eba <= operand_1_x[ (32-2)+2-1:8]; + + + + + end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -19764,46 +93098,89 @@ begin else begin if ((kill_f == 1'b1) || (stall_a == 1'b0)) + + + + valid_f <= 1'b1; + + else if (stall_f == 1'b0) valid_f <= 1'b0; + if (kill_d == 1'b1) valid_d <= 1'b0; else if (stall_f == 1'b0) valid_d <= valid_f & !kill_f; else if (stall_d == 1'b0) valid_d <= 1'b0; + if (stall_d == 1'b0) valid_x <= valid_d & !kill_d; else if (kill_x == 1'b1) valid_x <= 1'b0; else if (stall_x == 1'b0) valid_x <= 1'b0; + if (kill_m == 1'b1) valid_m <= 1'b0; else if (stall_x == 1'b0) valid_m <= valid_x & !kill_x; else if (stall_m == 1'b0) valid_m <= 1'b0; + if (stall_m == 1'b0) valid_w <= valid_m & !kill_m; else valid_w <= 1'b0; end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin + + + + operand_0_x <= { 32{1'b0}}; operand_1_x <= { 32{1'b0}}; store_operand_x <= { 32{1'b0}}; branch_target_x <= { (32-2){1'b0}}; x_result_sel_csr_x <= 1'b0; - x_result_sel_shift_x <= 1'b0; + + + x_result_sel_mc_arith_x <= 1'b0; + + + + + + + + + x_result_sel_sext_x <= 1'b0; + + + + + + x_result_sel_add_x <= 1'b0; m_result_sel_compare_x <= 1'b0; + + + m_result_sel_shift_x <= 1'b0; + + w_result_sel_load_x <= 1'b0; + + + w_result_sel_mul_x <= 1'b0; + + x_bypass_enable_x <= 1'b0; m_bypass_enable_x <= 1'b0; write_enable_x <= 1'b0; @@ -19816,17 +93193,50 @@ begin adder_op_x <= 1'b0; adder_op_x_n <= 1'b0; logic_op_x <= 4'h0; + + + direction_x <= 1'b0; + + + + + + + branch_x <= 1'b0; branch_predict_x <= 1'b0; branch_predict_taken_x <= 1'b0; condition_x <= 3'b000; + + + + scall_x <= 1'b0; eret_x <= 1'b0; + + + + + + + + + csr_write_enable_x <= 1'b0; operand_m <= { 32{1'b0}}; branch_target_m <= { (32-2){1'b0}}; m_result_sel_compare_m <= 1'b0; + + + m_result_sel_shift_m <= 1'b0; + + w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + m_bypass_enable_m <= 1'b0; branch_m <= 1'b0; branch_predict_m <= 1'b0; @@ -19837,25 +93247,83 @@ begin write_enable_m <= 1'b0; write_idx_m <= { 5{1'b0}}; condition_met_m <= 1'b0; + + + + + + + + + operand_w <= { 32{1'b0}}; w_result_sel_load_w <= 1'b0; + + + w_result_sel_mul_w <= 1'b0; + + write_idx_w <= { 5{1'b0}}; write_enable_w <= 1'b0; + + + + + exception_w <= 1'b0; + + + + + + end else begin + + if (stall_x == 1'b0) begin + + + + operand_0_x <= d_result_0; operand_1_x <= d_result_1; store_operand_x <= bypass_data_1; branch_target_x <= branch_reg_d == 1'b1 ? bypass_data_0[ ((32-2)+2-1):2] : branch_target_d; x_result_sel_csr_x <= x_result_sel_csr_d; - x_result_sel_shift_x <= x_result_sel_shift_d; + + + x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d; + + + + + + + + + x_result_sel_sext_x <= x_result_sel_sext_d; + + + + + + x_result_sel_add_x <= x_result_sel_add_d; m_result_sel_compare_x <= m_result_sel_compare_d; + + + m_result_sel_shift_x <= m_result_sel_shift_d; + + w_result_sel_load_x <= w_result_sel_load_d; + + + w_result_sel_mul_x <= w_result_sel_mul_d; + + x_bypass_enable_x <= x_bypass_enable_d; m_bypass_enable_x <= m_bypass_enable_d; load_x <= load_d; @@ -19870,52 +93338,199 @@ begin adder_op_x <= adder_op_d; adder_op_x_n <= ~adder_op_d; logic_op_x <= logic_op_d; + + + direction_x <= direction_d; + + + + + + condition_x <= condition_d; csr_write_enable_x <= csr_write_enable_d; + + + + scall_x <= scall_d; + + + + eret_x <= eret_d; + + + + write_enable_x <= write_enable_d; end + + + if (stall_m == 1'b0) begin operand_m <= x_result; m_result_sel_compare_m <= m_result_sel_compare_x; + + + m_result_sel_shift_m <= m_result_sel_shift_x; + + if (exception_x == 1'b1) begin w_result_sel_load_m <= 1'b0; + + + w_result_sel_mul_m <= 1'b0; + + end else begin w_result_sel_load_m <= w_result_sel_load_x; + + + w_result_sel_mul_m <= w_result_sel_mul_x; + + end m_bypass_enable_m <= m_bypass_enable_x; load_m <= load_x; store_m <= store_x; + + + + branch_m <= branch_x; branch_predict_m <= branch_predict_x; branch_predict_taken_m <= branch_predict_taken_x; + + + + + + + + + + + + + + + + if (exception_x == 1'b1) write_idx_m <= 5'd30; else write_idx_m <= write_idx_x; + + condition_met_m <= condition_met_x; + + + + + + + + + + + + branch_target_m <= exception_x == 1'b1 ? {eba, eid_x, {3{1'b0}}} : branch_target_x; + + + + + + + + + + + + + + + + + write_enable_m <= exception_x == 1'b1 ? 1'b1 : write_enable_x; + + + + + end + + if (stall_m == 1'b0) begin if ((exception_x == 1'b1) && (q_x == 1'b1) && (stall_x == 1'b0)) exception_m <= 1'b1; else exception_m <= 1'b0; + + + + + + + + end + + + + + + operand_w <= exception_m == 1'b1 ? {pc_m, 2'b00} : m_result; + + w_result_sel_load_w <= w_result_sel_load_m; + + + w_result_sel_mul_w <= w_result_sel_mul_m; + + write_idx_w <= write_idx_m; + + + + + + + + write_enable_w <= write_enable_m; + + + + + exception_w <= exception_m; + + + + + + + + + + + end end + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -19943,13 +93558,521 @@ begin end end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + initial begin + + + + + + end + + + endmodule -module lm32_load_store_unit_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_load_store_unit_wr_node +( + clk_i, + + + + rst_i, + stall_a, stall_x, stall_m, @@ -19968,12 +94091,38 @@ module lm32_load_store_unit_minimal ( store_q_m, sign_extend_x, size_x, + + + + + d_dat_i, d_ack_i, d_err_i, d_rty_i, + + + + + + + + + + + + iram_d_adr_o, + iram_d_dat_o, + iram_d_dat_i, + iram_d_sel_o, + iram_d_we_o, + iram_d_en_o, + iram_stall_request_x, + + load_data_w, stall_wb_load, + d_dat_o, d_adr_o, d_cyc_o, @@ -19984,22 +94133,37 @@ module lm32_load_store_unit_minimal ( d_lock_o, d_bte_o ); + + + + + parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); -input clk_i; + + + + + + input clk_i; + input rst_i; + input stall_a; input stall_x; input stall_m; input kill_x; input kill_m; input exception_m; + input [ (32-1):0] store_operand_x; input [ (32-1):0] load_store_address_x; input [ (32-1):0] load_store_address_m; @@ -20012,14 +94176,58 @@ input load_q_m; input store_q_m; input sign_extend_x; input [ 1:0] size_x; + + + + + + + + + output [31:0] iram_d_adr_o; + output [31:0] iram_d_dat_o; + input [31:0] iram_d_dat_i; + output [3:0] iram_d_sel_o; + output iram_d_en_o, iram_d_we_o; + output iram_stall_request_x; + + + + + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + input [ (32-1):0] d_dat_i; input d_ack_i; input d_err_i; input d_rty_i; + + + + + + + + + + + + + + + + + + output [ (32-1):0] load_data_w; reg [ (32-1):0] load_data_w; output stall_wb_load; reg stall_wb_load; + output [ (32-1):0] d_dat_o; reg [ (32-1):0] d_dat_o; output [ (32-1):0] d_adr_o; @@ -20038,6 +94246,12 @@ output d_lock_o; reg d_lock_o; output [ (2-1):0] d_bte_o; wire [ (2-1):0] d_bte_o; + + + + + + reg [ 1:0] size_m; reg [ 1:0] size_w; reg sign_extend_m; @@ -20048,10 +94262,114 @@ reg [ (4-1):0] byte_enable_x; reg [ (4-1):0] byte_enable_m; wire [ (32-1):0] data_m; reg [ (32-1):0] data_w; + + + + + + + + + + + + + + + + + + + + + + + + + wire wb_select_x; + + +wire iram_select_x; + +reg iram_enable_m; + reg iram_select_m; + reg iram_d_en_d0; + + + + reg wb_select_m; reg [ (32-1):0] wb_data_m; reg wb_load_complete; + + reg clk_div2, clk_div2_d0; + reg wb_io_sync; + + + + + + + + + + + + + + + + + + + + + + + always@(posedge clk_i) + wb_io_sync <= 1; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -20059,6 +94377,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -20071,8 +94390,118 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign iram_select_x = (load_store_address_x >= 0) + && (load_store_address_x <= 32'h000fffff); + + assign iram_d_sel_o = byte_enable_m; + assign iram_en = !stall_x || !stall_m; + + always@(posedge clk_i) + iram_en_d0 <= iram_en; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign wb_select_x = 1'b1 + + + + + + + + + + + && !iram_select_x + + ; + + always @(*) begin case (size_x) @@ -20082,6 +94511,8 @@ begin default: store_data_x = { 32{1'bx}}; endcase end + + always @(*) begin casez ({size_x, load_store_address_x[1:0]}) @@ -20095,7 +94526,91 @@ begin default: byte_enable_x = 4'bxxxx; endcase end - assign data_m = wb_data_m; + + + + assign iram_d_dat_o = store_data_m; + assign iram_d_adr_o = (iram_enable_m && store_q_m) ? load_store_address_m : load_store_address_x; + + assign iram_stall_request_x = (iram_select_x == 1'b1) + && (store_q_x == 1'b1); + + + assign iram_d_we_o = (iram_enable_m == 1'b1) && (store_q_m == 1'b1); + assign iram_d_en_o = !stall_m || !stall_x; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + assign data_m = wb_select_m == 1'b1 + ? wb_data_m + : iram_d_dat_i; + + + + + + + + + + + + always @(*) begin casez ({size_w, load_store_address_w[1:0]}) @@ -20109,7 +94624,45 @@ begin default: load_data_w = { 32{1'bx}}; endcase end + + assign d_bte_o = 2'b00; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -20125,30 +94678,86 @@ begin wb_data_m <= { 32{1'b0}}; wb_load_complete <= 1'b0; stall_wb_load <= 1'b0; + + + + end else begin + + + + + + if (d_cyc_o == 1'b1) begin + if ((d_ack_i == 1'b1) || (d_err_i == 1'b1)) begin + + + + + + + + + begin + d_cyc_o <= 1'b0; d_stb_o <= 1'b0; d_lock_o <= 1'b0; end + + + + + + + wb_data_m <= d_dat_i; + wb_load_complete <= !d_we_o; end + if (d_err_i == 1'b1) $display ("Data bus error. Address: %x", d_adr_o); + end else begin + + + + + + + + + + + + + + + if ( (store_q_m == 1'b1) && (stall_m == 1'b0) + + + + + + + && (iram_enable_m == 1'b0) + + ) begin + d_dat_o <= store_data_m; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -20160,8 +94769,10 @@ begin else if ( (load_q_m == 1'b1) && (wb_select_m == 1'b1) && (wb_load_complete == 1'b0) + ) begin + stall_wb_load <= 1'b0; d_adr_o <= load_store_address_m; d_cyc_o <= 1'b1; @@ -20171,14 +94782,21 @@ begin d_cti_o <= 3'b111; end end + if (stall_m == 1'b0) wb_load_complete <= 1'b0; + if ((load_q_x == 1'b1) && (wb_select_x == 1'b1) && (stall_x == 1'b0)) stall_wb_load <= 1'b1; + if ((kill_m == 1'b1) || (exception_m == 1'b1)) stall_wb_load <= 1'b0; end end + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -20187,6 +94805,20 @@ begin size_m <= 2'b00; byte_enable_m <= 1'b0; store_data_m <= { 32{1'b0}}; + + + + + + + + + + + iram_enable_m <= 1'b0; + iram_select_m <= 1'b0; + + wb_select_m <= 1'b0; end else @@ -20197,10 +94829,26 @@ begin size_m <= size_x; byte_enable_m <= byte_enable_x; store_data_m <= store_data_x; + + + + + + + + + + + iram_enable_m <= iram_select_x; + iram_select_m <= iram_select_x; + + wb_select_m <= wb_select_x; end end end + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -20212,10 +94860,25 @@ begin else begin size_w <= size_m; + + + + if(!iram_select_m || iram_en_d0) + + data_w <= data_m; + sign_extend_w <= sign_extend_m; end end + + + + + + + + always @(posedge clk_i) begin if (((load_q_m == 1'b1) || (store_q_m == 1'b1)) && (stall_m == 1'b0)) @@ -20226,17 +94889,511 @@ begin $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time); end end + + + endmodule -module lm32_decoder_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_decoder_wr_node ( + instruction, + d_result_sel_0, d_result_sel_1, x_result_sel_csr, - x_result_sel_shift, + + + x_result_sel_mc_arith, + + + + + + + + + x_result_sel_sext, + + x_result_sel_logic, + + + + x_result_sel_add, m_result_sel_compare, + + + m_result_sel_shift, + + w_result_sel_load, + + + w_result_sel_mul, + + x_bypass_enable, m_bypass_enable, read_enable_0, @@ -20253,32 +95410,106 @@ module lm32_decoder_minimal ( sign_extend, adder_op, logic_op, + + + direction, + + + + + + + + + + + + + + divide, + modulus, + + branch, branch_reg, condition, bi_conditional, bi_unconditional, + + + + scall, eret, + + + + + + + + csr_write_enable ); + + + + + input [ (32-1):0] instruction; + + + + + output [ 0:0] d_result_sel_0; reg [ 0:0] d_result_sel_0; output [ 1:0] d_result_sel_1; reg [ 1:0] d_result_sel_1; output x_result_sel_csr; reg x_result_sel_csr; -output x_result_sel_shift; -reg x_result_sel_shift; + + +output x_result_sel_mc_arith; +reg x_result_sel_mc_arith; + + + + + + + + + +output x_result_sel_sext; +reg x_result_sel_sext; + + output x_result_sel_logic; reg x_result_sel_logic; + + + + + output x_result_sel_add; reg x_result_sel_add; output m_result_sel_compare; reg m_result_sel_compare; + + +output m_result_sel_shift; +reg m_result_sel_shift; + + output w_result_sel_load; reg w_result_sel_load; + + +output w_result_sel_mul; +reg w_result_sel_mul; + + output x_bypass_enable; wire x_bypass_enable; output m_bypass_enable; @@ -20311,6 +95542,32 @@ output adder_op; wire adder_op; output [ 3:0] logic_op; wire [ 3:0] logic_op; + + +output direction; +wire direction; + + + + + + + + + + + + + + + + +output divide; +wire divide; +output modulus; +wire modulus; + + output branch; wire branch; output branch_reg; @@ -20321,12 +95578,32 @@ output bi_conditional; wire bi_conditional; output bi_unconditional; wire bi_unconditional; + + + + + output scall; wire scall; output eret; wire eret; + + + + + + + + + + output csr_write_enable; wire csr_write_enable; + + + + + wire [ (32-1):0] extended_immediate; wire [ (32-1):0] high_immediate; wire [ (32-1):0] call_immediate; @@ -20334,6 +95611,7 @@ wire [ (32-1):0] branch_immediate; wire sign_extend_immediate; wire select_high_immediate; wire select_call_immediate; + wire op_add; wire op_and; wire op_andhi; @@ -20353,31 +95631,110 @@ wire op_cmpge; wire op_cmpgeu; wire op_cmpgu; wire op_cmpne; + + +wire op_divu; + + wire op_lb; wire op_lbu; wire op_lh; wire op_lhu; wire op_lw; + + +wire op_modu; + + + + +wire op_mul; + + wire op_nor; wire op_or; wire op_orhi; wire op_raise; wire op_rcsr; wire op_sb; + + +wire op_sextb; +wire op_sexth; + + wire op_sh; + + +wire op_sl; + + wire op_sr; wire op_sru; wire op_sub; wire op_sw; + + + + wire op_wcsr; wire op_xnor; wire op_xor; + wire arith; wire logical; wire cmp; wire bra; wire call; + + wire shift; + + + + + + + + +wire sext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -20385,6 +95742,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -20397,6 +95755,15 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + assign op_add = instruction[ 30:26] == 5'b01101; assign op_and = instruction[ 30:26] == 5'b01000; assign op_andhi = instruction[ 31:26] == 6'b011000; @@ -20416,25 +95783,57 @@ assign op_cmpge = instruction[ 30:26] == 5'b11011; assign op_cmpgeu = instruction[ 30:26] == 5'b11100; assign op_cmpgu = instruction[ 30:26] == 5'b11101; assign op_cmpne = instruction[ 30:26] == 5'b11111; + + +assign op_divu = instruction[ 31:26] == 6'b100011; + + assign op_lb = instruction[ 31:26] == 6'b000100; assign op_lbu = instruction[ 31:26] == 6'b010000; assign op_lh = instruction[ 31:26] == 6'b000111; assign op_lhu = instruction[ 31:26] == 6'b001011; assign op_lw = instruction[ 31:26] == 6'b001010; + + +assign op_modu = instruction[ 31:26] == 6'b110001; + + + + +assign op_mul = instruction[ 30:26] == 5'b00010; + + assign op_nor = instruction[ 30:26] == 5'b00001; assign op_or = instruction[ 30:26] == 5'b01110; assign op_orhi = instruction[ 31:26] == 6'b011110; assign op_raise = instruction[ 31:26] == 6'b101011; assign op_rcsr = instruction[ 31:26] == 6'b100100; assign op_sb = instruction[ 31:26] == 6'b001100; + + +assign op_sextb = instruction[ 31:26] == 6'b101100; +assign op_sexth = instruction[ 31:26] == 6'b110111; + + assign op_sh = instruction[ 31:26] == 6'b000011; + + +assign op_sl = instruction[ 30:26] == 5'b01111; + + assign op_sr = instruction[ 30:26] == 5'b00101; assign op_sru = instruction[ 30:26] == 5'b00000; assign op_sub = instruction[ 31:26] == 6'b110010; assign op_sw = instruction[ 31:26] == 6'b010110; + + + + assign op_wcsr = instruction[ 31:26] == 6'b110100; assign op_xnor = instruction[ 30:26] == 5'b01001; assign op_xor = instruction[ 30:26] == 5'b00110; + + assign arith = op_add | op_sub; assign logical = op_and | op_andhi | op_nor | op_or | op_orhi | op_xor | op_xnor; assign cmp = op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne; @@ -20442,11 +95841,42 @@ assign bi_conditional = op_be | op_bg | op_bge | op_bgeu | op_bgu | op_bne; assign bi_unconditional = op_bi; assign bra = op_b | bi_unconditional | bi_conditional; assign call = op_call | op_calli; -assign shift = op_sr | op_sru; + + +assign shift = op_sl | op_sr | op_sru; + + + + + + + + + + + + + +assign sext = op_sextb | op_sexth; + + + + + + + + +assign divide = op_divu; +assign modulus = op_modu; + + assign load = op_lb | op_lbu | op_lh | op_lhu | op_lw; assign store = op_sb | op_sh | op_sw; + + always @(*) begin + if (call) d_result_sel_0 = 1'b1; else @@ -20457,66 +95887,2872 @@ begin d_result_sel_1 = 2'b10; else d_result_sel_1 = 2'b01; + x_result_sel_csr = 1'b0; - x_result_sel_shift = 1'b0; + + + x_result_sel_mc_arith = 1'b0; + + + + + + + + + x_result_sel_sext = 1'b0; + + x_result_sel_logic = 1'b0; + + + + x_result_sel_add = 1'b0; if (op_rcsr) x_result_sel_csr = 1'b1; - else if (shift) - x_result_sel_shift = 1'b1; + + + + + + + + + + else if (divide | modulus) + x_result_sel_mc_arith = 1'b1; + + + + + + + + + + + + + + + + + else if (sext) + x_result_sel_sext = 1'b1; + + else if (logical) x_result_sel_logic = 1'b1; + + + + + else x_result_sel_add = 1'b1; + + + m_result_sel_compare = cmp; + + + m_result_sel_shift = shift; + + + + w_result_sel_load = load; + + + w_result_sel_mul = op_mul; + + end + + assign x_bypass_enable = arith | logical - | shift + + + + + + + + + + + + | divide + | modulus + + + + + + + + + | sext + + + + + + | op_rcsr ; + assign m_bypass_enable = x_bypass_enable + + + | shift + + | cmp ; + assign read_enable_0 = ~(op_bi | op_calli); assign read_idx_0 = instruction[25:21]; + assign read_enable_1 = ~(op_bi | op_calli | load); assign read_idx_1 = instruction[20:16]; + assign write_enable = ~(bra | op_raise | store | op_wcsr); assign write_idx = call ? 5'd29 : instruction[31] == 1'b0 ? instruction[20:16] : instruction[15:11]; + + assign size = instruction[27:26]; + assign sign_extend = instruction[28]; + assign adder_op = op_sub | op_cmpe | op_cmpg | op_cmpge | op_cmpgeu | op_cmpgu | op_cmpne | bra; + assign logic_op = instruction[29:26]; + + + +assign direction = instruction[29]; + + + assign branch = bra | call; assign branch_reg = op_call | op_b; assign condition = instruction[28:26]; + + + + assign scall = op_raise & instruction[2]; assign eret = op_b & (instruction[25:21] == 5'd30); + + + + + + + + + + assign csr_write_enable = op_wcsr; + + + assign sign_extend_immediate = ~(op_and | op_cmpgeu | op_cmpgu | op_nor | op_or | op_xnor | op_xor); assign select_high_immediate = op_andhi | op_orhi; assign select_call_immediate = instruction[31]; + assign high_immediate = {instruction[15:0], 16'h0000}; assign extended_immediate = {{16{sign_extend_immediate & instruction[15]}}, instruction[15:0]}; assign call_immediate = {{6{instruction[25]}}, instruction[25:0]}; assign branch_immediate = {{16{instruction[15]}}, instruction[15:0]}; + assign immediate = select_high_immediate == 1'b1 ? high_immediate : extended_immediate; + assign branch_offset = select_call_immediate == 1'b1 ? (call_immediate[ (32-2)-1:0]) : (branch_immediate[ (32-2)-1:0]); + endmodule -module lm32_instruction_unit_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_instruction_unit_wr_node ( + clk_i, rst_i, + stall_a, stall_f, stall_d, @@ -20527,43 +98763,123 @@ module lm32_instruction_unit_minimal ( kill_f, branch_predict_taken_d, branch_predict_address_d, + + + + + exception_m, branch_taken_m, branch_mispredict_taken_m, branch_target_m, - i_dat_i, - i_ack_i, - i_err_i, - i_rty_i, + + + + + + + + + + + + + + + + + + + + + + + + + + + pc_f, pc_d, pc_x, pc_m, pc_w, - i_dat_o, - i_adr_o, - i_cyc_o, - i_sel_o, - i_stb_o, - i_we_o, - i_cti_o, - i_lock_o, - i_bte_o, + + + + + + + + + + + + + + + + + + + + + + + iram_i_adr_o, + iram_i_dat_i, + iram_i_en_o, + + + + + + + + + + + + + instruction_f, + + instruction_d ); + + + + + parameter eba_reset = 32'h00000000; parameter associativity = 1; parameter sets = 512; parameter bytes_per_line = 16; parameter base_address = 0; parameter limit = 0; + + localparam eba_reset_minus_4 = eba_reset - 4; localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2; localparam addr_offset_lsb = 2; localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); + + + + + + +output [31:0] iram_i_adr_o; +input [31:0] iram_i_dat_i; + output iram_i_en_o; + + + + input clk_i; input rst_i; + input stall_a; input stall_f; input stall_d; @@ -20572,16 +98888,52 @@ input stall_m; input valid_f; input valid_d; input kill_f; + input branch_predict_taken_d; input [ ((32-2)+2-1):2] branch_predict_address_d; + + + + + + input exception_m; input branch_taken_m; input branch_mispredict_taken_m; input [ ((32-2)+2-1):2] branch_target_m; -input [ (32-1):0] i_dat_i; -input i_ack_i; -input i_err_i; -input i_rty_i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ ((32-2)+2-1):2] pc_f; reg [ ((32-2)+2-1):2] pc_f; output [ ((32-2)+2-1):2] pc_d; @@ -20592,30 +98944,161 @@ output [ ((32-2)+2-1):2] pc_m; reg [ ((32-2)+2-1):2] pc_m; output [ ((32-2)+2-1):2] pc_w; reg [ ((32-2)+2-1):2] pc_w; -output [ (32-1):0] i_dat_o; -wire [ (32-1):0] i_dat_o; -output [ (32-1):0] i_adr_o; -reg [ (32-1):0] i_adr_o; -output i_cyc_o; -reg i_cyc_o; -output [ (4-1):0] i_sel_o; -wire [ (4-1):0] i_sel_o; -output i_stb_o; -reg i_stb_o; -output i_we_o; -wire i_we_o; -output [ (3-1):0] i_cti_o; -reg [ (3-1):0] i_cti_o; -output i_lock_o; -reg i_lock_o; -output [ (2-1):0] i_bte_o; -wire [ (2-1):0] i_bte_o; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + output [ (32-1):0] instruction_f; wire [ (32-1):0] instruction_f; + + output [ (32-1):0] instruction_d; reg [ (32-1):0] instruction_d; + + + + + reg [ ((32-2)+2-1):2] pc_a; -reg [ (32-1):0] wb_data_f; + + + + + + + + + + + + + + + + + + + + + + + + + + +wire iram_select_a; + reg iram_select_f; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + function integer clogb2; input [31:0] value; begin @@ -20623,6 +99106,7 @@ begin value = value >> 1; end endfunction + function integer clogb2_v1; input [31:0] value; reg [31:0] i; @@ -20635,24 +99119,188 @@ begin clogb2_v1 = i-1; end endfunction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(*) begin + + + + + + + if (branch_taken_m == 1'b1) if ((branch_mispredict_taken_m == 1'b1) && (exception_m == 1'b0)) pc_a = pc_x; else pc_a = branch_target_m; + + + + + else if ( (valid_d == 1'b1) && (branch_predict_taken_d == 1'b1) ) pc_a = branch_predict_address_d; else + + + + + + pc_a = pc_f + 1'b1; end -assign instruction_f = wb_data_f; -assign i_dat_o = 32'd0; -assign i_we_o = 1'b0; -assign i_sel_o = 4'b1111; -assign i_bte_o = 2'b00; + + + + + assign iram_select_a = 1'b1; + assign iram_i_en_o = !stall_a; + assign iram_i_adr_o = {pc_a, 2'b00}; + + + + + + + reg [31:0] prev_instruction_f; + reg iram_i_en_d0; + + always@(posedge clk_i) + if(rst_i) begin + iram_i_en_d0 <= 0; + end else begin + iram_i_en_d0 <= !stall_a; + if(iram_i_en_d0) + prev_instruction_f <= iram_i_dat_i; + end + + + assign instruction_f = (!iram_i_en_d0) ? prev_instruction_f : iram_i_dat_i; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) @@ -20676,106 +99324,1560 @@ begin pc_w <= pc_m; end end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) begin if (rst_i == 1'b1) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - i_adr_o <= { 32{1'b0}}; - i_cti_o <= 3'b111; - i_lock_o <= 1'b0; - wb_data_f <= { 32{1'b0}}; - end - else - begin - if (i_cyc_o == 1'b1) - begin - if((i_ack_i == 1'b1) || (i_err_i == 1'b1)) - begin - i_cyc_o <= 1'b0; - i_stb_o <= 1'b0; - wb_data_f <= i_dat_i; - end - end - else - begin - if ( (stall_a == 1'b0) - ) - begin - i_adr_o <= {pc_a, 2'b00}; - i_cyc_o <= 1'b1; - i_stb_o <= 1'b1; - end - else - begin - if ( (stall_a == 1'b0) - ) - begin - end - end - end - end -end -always @(posedge clk_i ) -begin - if (rst_i == 1'b1) - begin - instruction_d <= { 32{1'b0}}; - end + iram_select_f <= 1'b0; else begin - if (stall_d == 1'b0) - begin - instruction_d <= instruction_f; - end + if (stall_f == 1'b0) + iram_select_f <= iram_select_a; end -end +end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + always @(posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + instruction_d <= { 32{1'b0}}; + + + + + end + else + begin + if (stall_d == 1'b0) + begin + instruction_d <= instruction_f; + + + + + end + end + end + endmodule -module lm32_interrupt_minimal ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +module lm32_interrupt_wr_node ( + clk_i, rst_i, + interrupt, + stall_x, + + + + + exception, + + eret_q_x, + + + + csr, csr_write_data, csr_write_enable, + interrupt_exception, + csr_read_data ); + + + + + parameter interrupts = 32; + + + + + input clk_i; input rst_i; + input [interrupts-1:0] interrupt; + input stall_x; + + + + + + input exception; + + input eret_q_x; + + + + + input [ (4 -1):0] csr; input [ (32-1):0] csr_write_data; input csr_write_enable; + + + + + output interrupt_exception; wire interrupt_exception; + output [ (32-1):0] csr_read_data; reg [ (32-1):0] csr_read_data; + + + + + wire [interrupts-1:0] asserted; + wire [interrupts-1:0] interrupt_n_exception; + + + reg ie; reg eie; + + + + reg [interrupts-1:0] ip; reg [interrupts-1:0] im; + + + + + + assign interrupt_n_exception = ip & im; + + assign interrupt_exception = (|interrupt_n_exception) & ie; + + assign asserted = ip | interrupt; + generate if (interrupts > 1) begin + always @(*) begin case (csr) 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + 1'b0, + + eie, ie }; @@ -20787,11 +100889,18 @@ end end else begin + always @(*) begin case (csr) 4 'h0: csr_read_data = {{ 32-3{1'b0}}, + + + + 1'b0, + + eie, ie }; @@ -20801,43 +100910,97 @@ begin end end endgenerate + + + + + + + reg [ 10:0] eie_delay = 0; + + generate + + if (interrupts > 1) begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + + im <= {interrupts{1'b0}}; ip <= {interrupts{1'b0}}; eie_delay <= 0; + end else begin + ip <= asserted; + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + + + + + else if (csr_write_enable == 1'b1) begin + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + + end if (csr == 4 'h1) im <= csr_write_data[interrupts-1:0]; @@ -20850,38 +101013,78 @@ end end else begin + always @(posedge clk_i ) begin if (rst_i == 1'b1) begin ie <= 1'b0; eie <= 1'b0; + + + + ip <= {interrupts{1'b0}}; eie_delay <= 0; end else begin + ip <= asserted; + + + + + + + + + + + + + + + if (exception == 1'b1) begin + eie <= ie; ie <= 1'b0; end + + else if (stall_x == 1'b0) begin + if(eie_delay[0]) ie <= eie; + eie_delay <= {1'b0, eie_delay[ 10:1]}; + if (eret_q_x == 1'b1) begin + eie_delay[ 10] <= 1'b1; eie_delay[ 10-1:0] <= 0; end + + + + + + + else if (csr_write_enable == 1'b1) begin + if (csr == 4 'h0) begin ie <= csr_write_data[0]; eie <= csr_write_data[1]; + + + + end if (csr == 4 'h2) ip <= asserted & ~csr_write_data[interrupts-1:0]; @@ -20891,4 +101094,7 @@ always @(posedge clk_i ) end end endgenerate + endmodule + + diff --git a/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd b/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd index aba9c172..1a0f69f0 100644 --- a/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd +++ b/modules/wishbone/wb_lm32/generated/xwb_lm32.vhd @@ -26,6 +26,7 @@ if profile_name = "medium_debug" then return 4; end if; if profile_name = "medium_icache_debug" then return 4; end if; if profile_name = "full" then return 4; end if; if profile_name = "full_debug" then return 4; end if; +if profile_name = "wr_node" then return 1; end if; return 0; end function; function f_eval_d_burst_length(profile_name:string) return natural is @@ -37,6 +38,7 @@ if profile_name = "medium_debug" then return 1; end if; if profile_name = "medium_icache_debug" then return 1; end if; if profile_name = "full" then return 4; end if; if profile_name = "full_debug" then return 4; end if; +if profile_name = "wr_node" then return 1; end if; return 0; end function; component lm32_top_minimal is @@ -250,6 +252,41 @@ port ( D_BTE_O : out std_logic_vector(1 downto 0)); end component; component lm32_top_full_debug is +generic ( eba_reset: std_logic_vector(31 downto 0); + sdb_address: std_logic_vector(31 downto 0)); +port ( + + clk_i : in std_logic; + rst_i : in std_logic; + interrupt : in std_logic_vector(31 downto 0); + I_DAT_I : in std_logic_vector(31 downto 0); + I_ACK_I : in std_logic; + I_ERR_I : in std_logic; + I_RTY_I : in std_logic; + D_DAT_I : in std_logic_vector(31 downto 0); + D_ACK_I : in std_logic; + D_ERR_I : in std_logic; + D_RTY_I : in std_logic; + I_DAT_O : out std_logic_vector(31 downto 0); + I_ADR_O : out std_logic_vector(31 downto 0); + I_CYC_O : out std_logic; + I_SEL_O : out std_logic_vector(3 downto 0); + I_STB_O : out std_logic; + I_WE_O : out std_logic; + I_CTI_O : out std_logic_vector(2 downto 0); + I_LOCK_O : out std_logic; + I_BTE_O : out std_logic_vector(1 downto 0); + D_DAT_O : out std_logic_vector(31 downto 0); + D_ADR_O : out std_logic_vector(31 downto 0); + D_CYC_O : out std_logic; + D_SEL_O : out std_logic_vector(3 downto 0); + D_STB_O : out std_logic; + D_WE_O : out std_logic; + D_CTI_O : out std_logic_vector(2 downto 0); + D_LOCK_O : out std_logic; + D_BTE_O : out std_logic_vector(1 downto 0)); +end component; +component lm32_top_wr_node is generic ( eba_reset: std_logic_vector(31 downto 0); sdb_address: std_logic_vector(31 downto 0)); port ( @@ -654,6 +691,50 @@ port map( D_CYC_O => D_CYC, D_CTI_O => D_CTI); end generate gen_profile_full_debug; +gen_profile_wr_node: if (g_profile = "wr_node") generate +U_Wrapped_LM32: lm32_top_wr_node + +generic map ( + eba_reset => g_reset_vector, + sdb_address => g_sdb_address) +port map( + clk_i => clk_sys_i, + rst_i => rst, + interrupt => irq_i, + -- Pass slave responses through unmodified + I_DAT_I => strip_undefined(iwb_i.DAT), + I_ACK_I => iwb_i.ACK, + I_ERR_I => iwb_i.ERR, + I_RTY_I => iwb_i.RTY, + D_DAT_I => strip_undefined(dwb_i.DAT), + D_ACK_I => dwb_i.ACK, + D_ERR_I => dwb_i.ERR, + D_RTY_I => dwb_i.RTY, + -- Writes can only happen as a single cycle + I_DAT_O => iwb_o.DAT, + D_DAT_O => dwb_o.DAT, + I_WE_O => iwb_o.WE, + D_WE_O => dwb_o.WE, + -- SEL /= 1111 only for single cycles + I_SEL_O => iwb_o.SEL, + D_SEL_O => dwb_o.SEL, + -- We can ignore BTE as we know it's always linear burst mode + I_BTE_O => open, + D_BTE_O => open, + -- Lock is never flagged by LM32. Besides, WBv4 locks intercon on CYC. + I_LOCK_O => open, + D_LOCK_O => open, + -- The LM32 has STB=CYC always + I_STB_O => open, + D_STB_O => open, + -- We monitor these pins to direct the adapter's logic + I_ADR_O => I_ADR, + I_CYC_O => I_CYC, + I_CTI_O => I_CTI, + D_ADR_O => D_ADR, + D_CYC_O => D_CYC, + D_CTI_O => D_CTI); +end generate gen_profile_wr_node; -- Cycle durations always match in our adapter iwb_o.CYC <= I_CYC; diff --git a/modules/wishbone/wb_lm32/lm32.profiles b/modules/wishbone/wb_lm32/lm32.profiles index 8e9d0ea8..6ca30051 100644 --- a/modules/wishbone/wb_lm32/lm32.profiles +++ b/modules/wishbone/wb_lm32/lm32.profiles @@ -4,4 +4,5 @@ medium_icache CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEN medium_debug CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_ICACHE_ENABLED CFG_WITH_DEBUG CFG_INTERRUPTS_ENABLED medium_icache_debug CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_ICACHE_ENABLED CFG_WITH_DEBUG CFG_INTERRUPTS_ENABLED full CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_INTERRUPTS_ENABLED CFG_MC_DIVIDE_ENABLED CFG_FAST_UNCONDITIONAL_BRANCH CFG_ICACHE_ENABLED CFG_DCACHE_ENABLED CFG_BUS_ERRORS_ENABLED -full_debug CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_INTERRUPTS_ENABLED CFG_MC_DIVIDE_ENABLED CFG_FAST_UNCONDITIONAL_BRANCH CFG_ICACHE_ENABLED CFG_DCACHE_ENABLED CFG_BUS_ERRORS_ENABLED CFG_WITH_DEBUG \ No newline at end of file +full_debug CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_INTERRUPTS_ENABLED CFG_MC_DIVIDE_ENABLED CFG_FAST_UNCONDITIONAL_BRANCH CFG_ICACHE_ENABLED CFG_DCACHE_ENABLED CFG_BUS_ERRORS_ENABLED CFG_WITH_DEBUG +wr_node CFG_PL_MULTIPLY_ENABLED CFG_PL_BARREL_SHIFT_ENABLED CFG_SIGN_EXTEND_ENABLED CFG_INTERRUPTS_ENABLED CFG_MC_DIVIDE_ENABLED CFG_IRAM_ENABLED \ No newline at end of file diff --git a/modules/wishbone/wb_lm32/src/lm32_cpu.v b/modules/wishbone/wb_lm32/src/lm32_cpu.v index 4cd3f375..1e1eaac7 100644 --- a/modules/wishbone/wb_lm32/src/lm32_cpu.v +++ b/modules/wishbone/wb_lm32/src/lm32_cpu.v @@ -137,16 +137,15 @@ module lm32_cpu ( I_BTE_O, `endif // `ifdef CFG_IWB_ENABLED `ifdef CFG_IRAM_ENABLED - iram_data_f, - iram_address_f, - iram_select_f, - - iram_data_m, - iram_store_data_m, - iram_address_m, - iram_we_m, - iram_byte_enable_m, - iram_enable_m + iram_i_adr_o, + iram_i_dat_i, + iram_i_en_o, + iram_d_adr_o, + iram_d_dat_o, + iram_d_dat_i, + iram_d_sel_o, + iram_d_we_o, + iram_d_en_o, `endif @@ -336,22 +335,14 @@ wire D_LOCK_O; output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type wire [`LM32_BTYPE_RNG] D_BTE_O; -`ifdef LM32_IRAM_ENABLED - input [`LM32_WORD_RNG] iram_data_f; - output [`LM32_PC_RNG] iram_address_f; - output iram_enable_f; - - input [`LM32_WORD_RNG] iram_data_m; // Data from Instruction-ROM - output [`LM32_WORD_RNG] iram_store_data_m; // Store data to Instruction ROM - output [`LM32_WORD_RNG] iram_address_m; // Load/store address to Instroutput iram_we_m; // Write-enable of 2nd port of Instruction ROM - output iram_we_m; - output [3:0 ] iram_byte_enable_m; - - - +`ifdef CFG_IRAM_ENABLED + output [31:0] iram_i_adr_o, iram_d_adr_o; + output [31:0] iram_d_dat_o; + input [31:0] iram_i_dat_i, iram_d_dat_i; + output [3:0] iram_d_sel_o; + output iram_d_en_o, iram_i_en_o, iram_d_we_o; `endif - ///////////////////////////////////////////////////// // Internal nets and registers ///////////////////////////////////////////////////// @@ -761,6 +752,11 @@ wire system_call_exception; // Indicates if a system call ex reg data_bus_error_seen; // Indicates if a data bus error was seen `endif +`ifdef CFG_IRAM_ENABLED + wire iram_stall_request_x; +`endif + + ///////////////////////////////////////////////////// // Functions ///////////////////////////////////////////////////// @@ -848,13 +844,13 @@ lm32_instruction_unit #( .i_lock_o (I_LOCK_O), .i_bte_o (I_BTE_O), `endif // `ifdef CFG_IWB_ENABLED + `ifdef CFG_IRAM_ENABLED - .iram_data_f(iram_data_f), - .iram_address_f(iram_address_f), - .iram_select_f(iram_select_f), + .iram_i_adr_o(iram_i_adr_o), + .iram_i_dat_i(iram_i_dat_i), + .iram_i_en_o(iram_i_en_o), `endif - - + `ifdef CFG_HW_DEBUG_ENABLED .jtag_read_data (jtag_read_data), .jtag_access_complete (jtag_access_complete), @@ -987,12 +983,13 @@ lm32_load_store_unit #( `endif `ifdef CFG_IRAM_ENABLED - .iram_data_m(iram_data_m), - .iram_store_data_m(iram_store_data_m), - .iram_address_m(iram_address_m), - .iram_we_m(iram_we_m), - .iram_byte_enable_m(iram_byte_enable_m), - .iram_enable_m(iram_enable_m), + .iram_d_adr_o(iram_d_adr_o), + .iram_d_dat_o(iram_d_dat_o), + .iram_d_dat_i(iram_d_dat_i), + .iram_d_sel_o(iram_d_sel_o), + .iram_d_we_o(iram_d_we_o), + .iram_d_en_o(iram_d_en_o), + .iram_stall_request_x(iram_stall_request_x), `endif // From Wishbone @@ -1858,6 +1855,15 @@ assign stall_d = (stall_x == `TRUE) || ( (csr_write_enable_d == `TRUE) && (load_q_x == `TRUE) ) +`ifdef CFG_IRAM_ENABLED + // Stall load/store instruction in D stage if there is an ongoing store + // operation to instruction ROM in M stage + || ( (iram_stall_request_x == `TRUE) + && ( (load_d == `TRUE) + //|| (store_d == `TRUE) + ) + ) +`endif ; assign stall_x = (stall_m == `TRUE) @@ -1866,6 +1872,8 @@ assign stall_x = (stall_m == `TRUE) && (kill_x == `FALSE) ) `endif + + ; assign stall_m = (stall_wb_load == `TRUE) diff --git a/modules/wishbone/wb_lm32/src/lm32_include.v b/modules/wishbone/wb_lm32/src/lm32_include.v index 5594d31c..03202c0b 100644 --- a/modules/wishbone/wb_lm32/src/lm32_include.v +++ b/modules/wishbone/wb_lm32/src/lm32_include.v @@ -45,7 +45,10 @@ `endif // Wishbone configuration +`ifndef CFG_IRAM_ENABLED `define CFG_IWB_ENABLED +`endif + `define CFG_DWB_ENABLED // Data-path width @@ -73,7 +76,8 @@ `ifdef CFG_IWB_ENABLED `define LM32_PC_WIDTH (`LM32_WORD_WIDTH-2) `else -`define LM32_PC_WIDTH `LM32_IROM_ADDRESS_WIDTH +`define LM32_IRAM_ADDRESS_WIDTH 32 +`define LM32_PC_WIDTH (`LM32_IRAM_ADDRESS_WIDTH-2) `endif `endif `define LM32_PC_RNG (`LM32_PC_WIDTH+2-1):2 diff --git a/modules/wishbone/wb_lm32/src/lm32_instruction_unit.v b/modules/wishbone/wb_lm32/src/lm32_instruction_unit.v index 239131d1..694ecfc9 100644 --- a/modules/wishbone/wb_lm32/src/lm32_instruction_unit.v +++ b/modules/wishbone/wb_lm32/src/lm32_instruction_unit.v @@ -107,11 +107,6 @@ module lm32_instruction_unit ( icache_refill_request, icache_refilling, `endif -`ifdef CFG_IRAM_ENABLED - iram_address_f, - iram_enable_f, - iram_data_f, -`endif `ifdef CFG_IWB_ENABLED // To Wishbone i_dat_o, @@ -124,6 +119,11 @@ module lm32_instruction_unit ( i_lock_o, i_bte_o, `endif +`ifdef CFG_IRAM_ENABLED + iram_i_adr_o, + iram_i_dat_i, + iram_i_en_o, +`endif `ifdef CFG_HW_DEBUG_ENABLED jtag_read_data, jtag_access_complete, @@ -157,6 +157,12 @@ localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); ///////////////////////////////////////////////////// // Inputs ///////////////////////////////////////////////////// +`ifdef CFG_IRAM_ENABLED +output [31:0] iram_i_adr_o; +input [31:0] iram_i_dat_i; + output iram_i_en_o; + +`endif input clk_i; // Clock input rst_i; // Reset @@ -191,9 +197,6 @@ input dcache_refill_request; // Request to refill dat input dcache_refilling; `endif -`ifdef CFG_IRAM_ENABLED - input [`LM32_WORD_RNG] iram_data_f; -`endif `ifdef CFG_IWB_ENABLED input [`LM32_WORD_RNG] i_dat_i; // Instruction Wishbone interface read data @@ -235,16 +238,6 @@ output icache_refilling; // Indicates the icache wire icache_refilling; `endif -`ifdef CFG_IRAM_ENABLED - output [`LM32_PC_RNG] iram_address_f; // Data to load-store unit on load - wire [`LM32_PC_RNG] iram_address_f; // Data to load-store unit on load - - output iram_enable_f; - wire iram_enable_f; - - -`endif - `ifdef CFG_IWB_ENABLED output [`LM32_WORD_RNG] i_dat_o; // Instruction Wishbone interface write data `ifdef CFG_HW_DEBUG_ENABLED @@ -323,8 +316,8 @@ reg [`LM32_INSTRUCTION_RNG] wb_data_f; // Instruction fetched f `endif `ifdef CFG_IRAM_ENABLED wire iram_select_a; // Indicates if A stage PC maps to a ROM address -reg iram_enable_f; // Indicates if F stage PC maps to a ROM address -wire [`LM32_INSTRUCTION_RNG] iram_data_f; // Instruction fetched from ROM + reg iram_select_f; + `endif `ifdef CFG_EBR_POSEDGE_REGISTER_FILE `else @@ -348,14 +341,7 @@ reg jtag_access; // Indicates if a JTAG W // Instantiations ///////////////////////////////////////////////////// -// Instruction ROM -`ifdef CFG_IRAM_ENABLED - - assign iram_address_f = pc_a; - assign iram_enable_f = !stall_a; -`endif - `ifdef CFG_ICACHE_ENABLED // Instruction cache lm32_icache #( @@ -438,27 +424,41 @@ end // Select where instruction should be fetched from `ifdef CFG_IRAM_ENABLED assign iram_select_a = 1'b1; + assign iram_i_en_o = !stall_a; + assign iram_i_adr_o = {pc_a, 2'b00}; `endif + +`ifdef CFG_IRAM_ENABLED + + reg [31:0] prev_instruction_f; + reg iram_i_en_d0; + + always@(posedge clk_i) + if(rst_i) begin + iram_i_en_d0 <= 0; + end else begin + iram_i_en_d0 <= !stall_a; + if(iram_i_en_d0) + prev_instruction_f <= iram_i_dat_i; + end + + + assign instruction_f = (!iram_i_en_d0) ? prev_instruction_f : iram_i_dat_i; + +// assign instruction_f = iram_i_dat_i; + + +`else // Select instruction from selected source `ifdef CFG_ICACHE_ENABLED -`ifdef CFG_IRAM_ENABLED -assign instruction_f = iram_select_f == `TRUE ? iram_data_f : icache_data_f; -`else assign instruction_f = icache_data_f; -`endif -`else -`ifdef CFG_IRAM_ENABLED -`ifdef CFG_IWB_ENABLED -assign instruction_f = iram_select_f == `TRUE ? iram_data_f : wb_data_f; -`else -assign instruction_f = iram_data_f; -`endif `else assign instruction_f = wb_data_f; `endif -`endif +`endif // !`ifdef CFG_IRAM_ENABLED + // Unused/constant Wishbone signals `ifdef CFG_IWB_ENABLED `ifdef CFG_HW_DEBUG_ENABLED diff --git a/modules/wishbone/wb_lm32/src/lm32_load_store_unit.v b/modules/wishbone/wb_lm32/src/lm32_load_store_unit.v index 8a469e38..3f2cf12c 100644 --- a/modules/wishbone/wb_lm32/src/lm32_load_store_unit.v +++ b/modules/wishbone/wb_lm32/src/lm32_load_store_unit.v @@ -48,13 +48,13 @@ module lm32_load_store_unit ( // ----- Inputs ------- - clk_i, -`ifdef LM32_DOUBLE_CORE_CLOCK - clk_wb_i, + clk_i, +`ifdef CFG_DOUBLE_CORE_CLOCK + clk_wb_i, `endif - rst_i, + rst_i, // From pipeline - stall_a, + stall_a, stall_x, stall_m, kill_x, @@ -74,9 +74,6 @@ module lm32_load_store_unit size_x, `ifdef CFG_DCACHE_ENABLED dflush, -`endif -`ifdef CFG_IRAM_ENABLED - iram_data_m, `endif // From Wishbone d_dat_i, @@ -92,11 +89,13 @@ module lm32_load_store_unit dcache_refilling, `endif `ifdef CFG_IRAM_ENABLED - iram_store_data_m, - iram_address_m, - iram_we_m, - iram_byte_enable_m, - iram_enable_m, + iram_d_adr_o, + iram_d_dat_o, + iram_d_dat_i, + iram_d_sel_o, + iram_d_we_o, + iram_d_en_o, + iram_stall_request_x, `endif load_data_w, stall_wb_load, @@ -132,7 +131,6 @@ localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1); ///////////////////////////////////////////////////// input clk_i; // Clock - input clk_wb_i; // wishbone clock (1/2 CPU clock) input rst_i; // Reset @@ -161,9 +159,22 @@ input dflush; // Flush the data cache `endif `ifdef CFG_IRAM_ENABLED -input [`LM32_WORD_RNG] iram_data_m; // Data from Instruction-ROM + output [31:0] iram_d_adr_o; + output [31:0] iram_d_dat_o; + input [31:0] iram_d_dat_i; + output [3:0] iram_d_sel_o; + output iram_d_en_o, iram_d_we_o; + output iram_stall_request_x; + `endif + reg [31:0] iram_dat_d0; + reg iram_en_d0; + wire iram_en; + wire [31:0] iram_data; + + + input [`LM32_WORD_RNG] d_dat_i; // Data Wishbone interface read data input d_ack_i; // Data Wishbone interface acknowledgement input d_err_i; // Data Wishbone interface error @@ -184,18 +195,6 @@ output dcache_refilling; wire dcache_refilling; `endif -`ifdef CFG_IRAM_ENABLED -output iram_store_data_m; // Store data to Instruction ROM -wire [`LM32_WORD_RNG] iram_store_data_m; -output [`LM32_WORD_RNG] iram_address_m; // Load/store address to Instruction ROM -wire [`LM32_WORD_RNG] iram_address_m; -output iram_we_m; // Write-enable of 2nd port of Instruction ROM -wire iram_we_m; - output [3:0 ] iram_byte_enable_m; - wire [3:0] iram_byte_enable_m; - - -`endif output [`LM32_WORD_RNG] load_data_w; // Result of a load instruction reg [`LM32_WORD_RNG] load_data_w; @@ -261,8 +260,13 @@ wire [`LM32_WORD_RNG] dram_store_data_m; // Data to write to RAM `endif wire wb_select_x; // Select Wishbone to load from / store to `ifdef CFG_IRAM_ENABLED -wire iram_select_x; // Select instruction ROM to load from / store to +wire iram_select_x; // Select instruction ROM to load from / store +// to reg iram_enable_m; + reg iram_select_m; + reg iram_d_en_d0; + + `endif reg wb_select_m; reg [`LM32_WORD_RNG] wb_data_m; // Data read from Wishbone @@ -271,7 +275,10 @@ reg wb_load_complete; // Indicates when a Wish reg clk_div2, clk_div2_d0; reg wb_io_sync; - always(posedge clk_wb_i or posedge rst_i) + `ifdef CFG_DOUBLE_CORE_CLOCK + input clk_wb_i; + + always@(posedge clk_wb_i or posedge rst_i) if(rst_i) clk_div2 <= 0; else @@ -287,6 +294,11 @@ reg wb_load_complete; // Indicates when a Wish clk_div2_d0 <= clk_div2; wb_io_sync <= ~(clk_div2_d0 ^ clk_div2); end + `else // !`ifdef CFG_DOUBLE_CORE_CLOCK + always@(posedge clk_i) + wb_io_sync <= 1; + + `endif // !`ifdef CFG_DOUBLE_CORE_CLOCK @@ -301,89 +313,6 @@ reg wb_load_complete; // Indicates when a Wish // Instantiations ///////////////////////////////////////////////////// -`ifdef CFG_DRAM_ENABLED - // Data RAM - pmi_ram_dp_true - #( - // ----- Parameters ------- - .pmi_family (`LATTICE_FAMILY), - - //.pmi_addr_depth_a (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)), - //.pmi_addr_width_a ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)), - //.pmi_data_width_a (`LM32_WORD_WIDTH), - //.pmi_addr_depth_b (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)), - //.pmi_addr_width_b ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)), - //.pmi_data_width_b (`LM32_WORD_WIDTH), - - .pmi_addr_depth_a (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1), - .pmi_addr_width_a (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)), - .pmi_data_width_a (`LM32_WORD_WIDTH), - .pmi_addr_depth_b (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1), - .pmi_addr_width_b (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)), - .pmi_data_width_b (`LM32_WORD_WIDTH), - - .pmi_regmode_a ("noreg"), - .pmi_regmode_b ("noreg"), - .pmi_gsr ("enable"), - .pmi_resetmode ("sync"), - .pmi_init_file (`CFG_DRAM_INIT_FILE), - .pmi_init_file_format (`CFG_DRAM_INIT_FILE_FORMAT), - .module_type ("pmi_ram_dp_true") - ) - ram ( - // ----- Inputs ------- - .ClockA (clk_i), - .ClockB (clk_i), - .ResetA (rst_i), - .ResetB (rst_i), - .DataInA ({32{1'b0}}), - .DataInB (dram_store_data_m), - .AddressA (load_store_address_x[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]), - .AddressB (load_store_address_m[(clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)+2-1:2]), - // .ClockEnA (!stall_x & (load_x | store_x)), - .ClockEnA (!stall_x), - .ClockEnB (!stall_m), - .WrA (`FALSE), - .WrB (store_q_m & dram_select_m), - // ----- Outputs ------- - .QA (dram_data_out), - .QB () - ); - - /*---------------------------------------------------------------------- - EBRs cannot perform reads from location 'written to' on the same clock - edge. Therefore bypass logic is required to latch the store'd value - and use it for the load (instead of value from memory). - ----------------------------------------------------------------------*/ - always @(posedge clk_i `CFG_RESET_SENSITIVITY) - if (rst_i == `TRUE) - begin - dram_bypass_en <= `FALSE; - dram_bypass_data <= 0; - end - else - begin - if (stall_x == `FALSE) - dram_bypass_data <= dram_store_data_m; - - if ( (stall_m == `FALSE) - && (stall_x == `FALSE) - && (store_q_m == `TRUE) - && ( (load_x == `TRUE) - || (store_x == `TRUE) - ) - && (load_store_address_x[(`LM32_WORD_WIDTH-1):2] == load_store_address_m[(`LM32_WORD_WIDTH-1):2]) - ) - dram_bypass_en <= `TRUE; - else - if ( (dram_bypass_en == `TRUE) - && (stall_x == `FALSE) - ) - dram_bypass_en <= `FALSE; - end - - assign dram_data_m = dram_bypass_en ? dram_bypass_data : dram_data_out; -`endif `ifdef CFG_DCACHE_ENABLED // Data cache @@ -433,7 +362,24 @@ lm32_dcache #( assign iram_select_x = (load_store_address_x >= `CFG_IRAM_BASE_ADDRESS) && (load_store_address_x <= `CFG_IRAM_LIMIT); - assign iram_byte_enable_m = byte_enable_m; + assign iram_d_sel_o = byte_enable_m; + assign iram_en = !stall_x || !stall_m; + + always@(posedge clk_i) + iram_en_d0 <= iram_en; + +/* -----\/----- EXCLUDED -----\/----- + + always@(posedge clk_i) + begin + iram_en_d0 <= iram_en; + if(iram_en_d0) + iram_dat_d0 <= iram_d_dat_i; + end + + assign iram_data = (!iram_en_d0) ? iram_dat_d0 : iram_d_dat_i; + -----/\----- EXCLUDED -----/\----- */ + `endif @@ -487,36 +433,16 @@ begin endcase end -`ifdef CFG_DRAM_ENABLED -// Only replace selected bytes -assign dram_store_data_m[`LM32_BYTE_0_RNG] = byte_enable_m[0] ? store_data_m[`LM32_BYTE_0_RNG] : dram_data_m[`LM32_BYTE_0_RNG]; -assign dram_store_data_m[`LM32_BYTE_1_RNG] = byte_enable_m[1] ? store_data_m[`LM32_BYTE_1_RNG] : dram_data_m[`LM32_BYTE_1_RNG]; -assign dram_store_data_m[`LM32_BYTE_2_RNG] = byte_enable_m[2] ? store_data_m[`LM32_BYTE_2_RNG] : dram_data_m[`LM32_BYTE_2_RNG]; -assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM32_BYTE_3_RNG] : dram_data_m[`LM32_BYTE_3_RNG]; -`endif - `ifdef CFG_IRAM_ENABLED -// Only replace selected bytes - assign iram_store_data_m = store_data_m; -`endif + assign iram_d_dat_o = store_data_m; + assign iram_d_adr_o = (iram_enable_m && store_q_m) ? load_store_address_m : load_store_address_x; -`ifdef CFG_IRAM_ENABLED - // Instead of implementing a byte-addressable instruction ROM (for store byte instruction), - // a load-and-store architecture is used wherein a 32-bit value is loaded, the requisite - // byte is replaced, and the whole 32-bit value is written back - - assign iram_address_m = load_store_address_m - + assign iram_stall_request_x = (iram_select_x == `TRUE) + && (store_q_x == `TRUE); // All store instructions perform a write operation in the M stage - assign iram_we_m = (iram_enable_m= `TRUE) - && (store_q_m == `TRUE); - - // A single port in instruction ROM is available to load-store unit for doing loads/stores. - // Since every store requires a load (in X stage) and then a store (in M stage), we cannot - // allow load (or store) instructions sequentially after the store instructions to proceed - // until the store instruction has vacated M stage (i.e., completed the store operation) - + assign iram_d_we_o = (iram_enable_m == `TRUE) && (store_q_m == `TRUE); + assign iram_d_en_o = !stall_m || !stall_x; `endif `ifdef CFG_DCACHE_ENABLED @@ -528,7 +454,7 @@ assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM : dram_select_m == `TRUE ? dram_data_m : iram_enable_m == `TRUE - ? iram_data_m + ? iram_d_dat_i : dcache_data_m; `else // WB + DC + DRAM @@ -573,7 +499,8 @@ assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM // WB + IRAM assign data_m = wb_select_m == `TRUE ? wb_data_m - : iram_data_m; + : iram_d_dat_i; + `else // WB assign data_m = wb_data_m; @@ -775,6 +702,7 @@ begin `endif `ifdef CFG_IRAM_ENABLED iram_enable_m <= `FALSE; + iram_select_m <= `FALSE; `endif wb_select_m <= `FALSE; end @@ -794,6 +722,7 @@ begin `endif `ifdef CFG_IRAM_ENABLED iram_enable_m <= iram_select_x; + iram_select_m <= iram_select_x; `endif wb_select_m <= wb_select_x; end @@ -812,7 +741,12 @@ begin else begin size_w <= size_m; + +`ifdef CFG_IRAM_ENABLED + if(!iram_select_m || iram_en_d0) +`endif data_w <= data_m; + sign_extend_w <= sign_extend_m; end end -- GitLab