OpenCores
URL https://opencores.org/ocsvn/zap/zap/trunk

Subversion Repositories zap

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 57 to Rev 58
    Reverse comparison

Rev 57 → Rev 58

/zap/trunk/src/testbench/External_IP/uart16550/doc/src/UART_spec.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
zap/trunk/src/testbench/External_IP/uart16550/doc/src/UART_spec.doc Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: zap/trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: zap/trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf =================================================================== --- zap/trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf (revision 57) +++ zap/trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf (nonexistent)
zap/trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: zap/trunk/src/rtl/cpu/zap_shifter_multiply.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_shifter_multiply.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_shifter_multiply.v (nonexistent) @@ -1,230 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This unit handles 32x32=32/64 multiplication using an FSM using -- -// -- a 17x17 signed array multiplier. -- -// -- -- -// ----------------------------------------------------------------------------- - - -`default_nettype none - -module zap_shifter_multiply -#( - parameter PHY_REGS = 46, - parameter ALU_OPS = 32 -) -( - input wire i_clk, - input wire i_reset, - - // Clear and stall signals. - input wire i_clear_from_writeback, - input wire i_data_stall, - input wire i_clear_from_alu, - - // ALU operation to perform. Activate if this is multiplication. - input wire [$clog2(ALU_OPS)-1:0] i_alu_operation_ff, - - // This is not used. - input wire i_cc_satisfied, - - // rm.rs + {rh,rn}. For non accumulate versions, rn = 0x0 and rh = 0x0. - input wire [31:0] i_rm, - input wire [31:0] i_rn, - input wire [31:0] i_rh, - input wire [31:0] i_rs, - - // - // Outputs. - // - - output reg [31:0] o_rd, // Result. - output reg o_busy, // Unit busy. - output reg o_nozero // Don't set zero flag. -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -// States -localparam IDLE = 0; -localparam S1 = 1; -localparam S2 = 2; -localparam S3 = 3; -localparam S4 = 4; -localparam S5 = 5; -localparam NUMBER_OF_STATES = 6; - -/////////////////////////////////////////////////////////////////////////////// - -reg [31:0] buffer_nxt, buffer_ff; -wire higher = i_alu_operation_ff[0]; -wire sign = (i_alu_operation_ff == SMLALL || i_alu_operation_ff == SMLALH); -wire signed [16:0] a; -wire signed [16:0] b; -wire signed [16:0] c; -wire signed [16:0] d; -reg signed [63:0] x_ff, x_nxt; -reg signed [16:0] in1; -reg signed [16:0] in2; -wire signed [63:0] prod; - -// State variable. -reg [$clog2(NUMBER_OF_STATES)-1:0] state_ff, state_nxt; - -/////////////////////////////////////////////////////////////////////////////// - -assign prod = in1 * in2; // 17x17 hard macro model. - -/////////////////////////////////////////////////////////////////////////////// - -assign a = sign ? {i_rm[31], i_rm[31:16]} : {1'd0, i_rm[31:16]}; -assign b = sign ? {i_rs[31], i_rs[31:16]} : {1'd0, i_rs[31:16]}; -assign c = {1'd0, i_rm[15:0]}; -assign d = {1'd0, i_rs[15:0]}; - -/////////////////////////////////////////////////////////////////////////////// - -always @* -begin - buffer_nxt = buffer_ff; - o_nozero = 1'd0; - o_busy = 1'd1; - o_rd = 32'd0; - state_nxt = state_ff; - x_nxt = x_ff; - in1 = 0; - in2 = 0; - - case ( state_ff ) - IDLE: - begin - o_busy = 1'd0; - x_nxt = 32'd0; - - // If we have the go signal. - if ( i_cc_satisfied && (i_alu_operation_ff == UMLALL || - i_alu_operation_ff == UMLALH || - i_alu_operation_ff == SMLALL || - i_alu_operation_ff == SMLALH) ) - begin - o_busy = 1'd1; - state_nxt = S1; - end - end - S1: - begin - in1 = c; - in2 = d; - x_nxt = x_ff + (prod << 0); - state_nxt = S2; - end - S2: - begin - in1 = b; - in2 = c; - state_nxt = S3; - x_nxt = x_ff + (prod << 16); - end - S3: - begin - in1 = a; - in2 = d; - state_nxt = S4; - x_nxt = x_ff + (prod << 16); - end - S4: - begin - in1 = a; - in2 = b; - state_nxt = S5; - x_nxt = x_ff + (prod << 32); - end - S5: - begin - state_nxt = IDLE; - x_nxt = x_ff + {i_rh, i_rn}; - o_rd = higher ? x_nxt[63:32] : x_nxt[31:0]; - - if ( !higher ) - begin - buffer_nxt = x_nxt[31:0]; - end - - o_busy = 1'd0; - - if ( higher && (buffer_ff != 32'd0) ) - begin - o_nozero = 1'd1; - end - end - endcase -end - -/////////////////////////////////////////////////////////////////////////////// - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - x_ff <= 63'd0; - state_ff <= IDLE; - buffer_ff<= 32'd0; - end - else if ( i_clear_from_writeback ) - begin - x_ff <= 63'd0; - state_ff <= IDLE; - buffer_ff <= 32'd0; - end - else if ( i_data_stall ) - begin - // Hold values - end - else if ( i_clear_from_alu ) - begin - x_ff <= 63'd0; - state_ff <= IDLE; - buffer_ff <= 32'd0; - end - else - begin - x_ff <= x_nxt; - state_ff <= state_nxt; - buffer_ff <= buffer_nxt; - end -end - -/////////////////////////////////////////////////////////////////////////////// - -endmodule // zap_multiply.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_cache.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_cache.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_cache.v (nonexistent) @@ -1,341 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This is the top level cache module that contains the MMU and cache. -- -// -- This will be instantiated twice in the processor TOP, once for -- -// -- instruction and the other for data. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_cache #( - -parameter [31:0] CACHE_SIZE = 1024, -parameter [31:0] SPAGE_TLB_ENTRIES = 8, -parameter [31:0] LPAGE_TLB_ENTRIES = 8, -parameter [31:0] SECTION_TLB_ENTRIES = 8 - -) /* Port List */ ( - -// Clock and reset. -input wire i_clk, -input wire i_reset, - -// Address from processor. -input wire [31:0] i_address, -input wire [31:0] i_address_nxt, - -// Other control signals from/to processor. -input wire i_rd, -input wire i_wr, -input wire [3:0] i_ben, -input wire [31:0] i_dat, -output wire [31:0] o_dat, -output wire o_ack, -output wire o_err, -output wire [7:0] o_fsr, -output wire [31:0] o_far, - -// MMU controls from/to processor. -input wire i_mmu_en, -input wire i_cache_en, -input wire i_cache_inv_req, -input wire i_cache_clean_req, -output wire o_cache_inv_done, -output wire o_cache_clean_done, -input wire [31:0] i_cpsr, -input wire [1:0] i_sr, -input wire [31:0] i_baddr, -input wire [31:0] i_dac_reg, -input wire i_tlb_inv, - -// Wishbone. Signals from all 4 modules are ORed. -output reg o_wb_stb, o_wb_stb_nxt, -output reg o_wb_cyc, o_wb_cyc_nxt, -output reg o_wb_wen, o_wb_wen_nxt, -output reg [3:0] o_wb_sel, o_wb_sel_nxt, -output reg [31:0] o_wb_dat, o_wb_dat_nxt, -output reg [31:0] o_wb_adr, o_wb_adr_nxt, -output reg [2:0] o_wb_cti, o_wb_cti_nxt, -input wire [31:0] i_wb_dat, -input wire i_wb_ack - -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -localparam S0=0; -localparam S1=1; -localparam S2=2; - -wire [2:0] wb_stb; -wire [2:0] wb_cyc; -wire [2:0] wb_wen; -wire [3:0] wb_sel [2:0]; -wire [31:0] wb_dat [2:0]; -wire [31:0] wb_adr [2:0]; -wire [2:0] wb_cti [2:0]; -wire [31:0] wb_dat0_cachefsm, wb_dat1_tagram, wb_dat2_tlb; -wire [31:0] tlb_phy_addr; -wire [7:0] tlb_fsr; -wire [31:0] tlb_far; -wire tlb_fault; -wire tlb_cacheable; -wire tlb_busy; -wire [127:0] tr_cache_line; -wire [127:0] cf_cache_line; -wire [15:0] cf_cache_line_ben; -wire cf_cache_tag_wr_en; -wire [`CACHE_TAG_WDT-1:0] tr_cache_tag, cf_cache_tag; -wire tr_cache_tag_valid; -wire tr_cache_tag_dirty, cf_cache_tag_dirty; -wire cf_cache_clean_req, cf_cache_inv_req; -wire tr_cache_inv_done, tr_cache_clean_done; -reg [2:0] wb_ack; -reg [1:0] state_ff, state_nxt; - -// Data from each Wishbone master. -assign wb_dat0_cachefsm = wb_dat[0]; -assign wb_dat1_tagram = wb_dat[1]; -assign wb_dat2_tlb = wb_dat[2]; - -// Bit 2 of Wishbone CTI is always on all CPU supported modes. -assign wb_cti[2] = 0; - -// Basic cache FSM - serves as Master 0. -zap_cache_fsm #(.CACHE_SIZE(CACHE_SIZE)) u_zap_cache_fsm ( - .i_clk (i_clk), - .i_reset (i_reset), - .i_address (i_address), - .i_rd (i_rd), - .i_wr (i_wr), - .i_din (i_dat), - .i_ben (i_ben), - .o_dat (o_dat), - .o_ack (o_ack), - .o_err (o_err), - .o_fsr (o_fsr), - .o_far (o_far), - .i_cache_en (i_cache_en), - .i_cache_inv (i_cache_inv_req), - .i_cache_clean (i_cache_clean_req), - .o_cache_inv_done (o_cache_inv_done), - .o_cache_clean_done (o_cache_clean_done), - .i_cache_line (tr_cache_line), - .i_cache_tag_dirty (tr_cache_tag_dirty), - .i_cache_tag (tr_cache_tag), - .i_cache_tag_valid (tr_cache_tag_valid), - .o_cache_tag (cf_cache_tag), - .o_cache_tag_dirty (cf_cache_tag_dirty), - .o_cache_tag_wr_en (cf_cache_tag_wr_en), - .o_cache_line (cf_cache_line), - .o_cache_line_ben (cf_cache_line_ben), - .o_cache_clean_req (cf_cache_clean_req), - .i_cache_clean_done (tr_cache_clean_done), - .o_cache_inv_req (cf_cache_inv_req), - .i_cache_inv_done (tr_cache_inv_done), - .i_phy_addr (tlb_phy_addr), - .i_fsr (tlb_fsr), - .i_far (tlb_far), - .i_fault (tlb_fault), - .i_cacheable (tlb_cacheable), - .i_busy (tlb_busy), - .o_wb_cyc_ff (), - .o_wb_cyc_nxt (wb_cyc[0]), - .o_wb_stb_ff (), - .o_wb_stb_nxt (wb_stb[0]), - .o_wb_adr_ff (), - .o_wb_adr_nxt (wb_adr[0]), - .o_wb_dat_ff (), - .o_wb_dat_nxt (wb_dat[0]), - .o_wb_sel_ff (), - .o_wb_sel_nxt (wb_sel[0]), - .o_wb_wen_ff (), - .o_wb_wen_nxt (wb_wen[0]), - .o_wb_cti_ff (), - .o_wb_cti_nxt (wb_cti[0]), - .i_wb_dat (i_wb_dat), - .i_wb_ack (wb_ack[0]) -); - -// Cache Tag RAM - As a master - this performs cache clean - Master 1. -zap_cache_tag_ram #(.CACHE_SIZE(CACHE_SIZE)) u_zap_cache_tag_ram ( - .i_clk (i_clk), - .i_reset (i_reset), - .i_address_nxt (i_address_nxt), - .i_address (i_address), - .i_cache_en (i_cache_en), - .i_cache_line (cf_cache_line), - .o_cache_line (tr_cache_line), - .i_cache_line_ben (cf_cache_line_ben), - .i_cache_tag_wr_en (cf_cache_tag_wr_en), - .i_cache_tag (cf_cache_tag), - .i_cache_tag_dirty (cf_cache_tag_dirty), - .o_cache_tag (tr_cache_tag), - .o_cache_tag_valid (tr_cache_tag_valid), - .o_cache_tag_dirty (tr_cache_tag_dirty), - .i_cache_inv_req (cf_cache_inv_req), - .o_cache_inv_done (tr_cache_inv_done), - .i_cache_clean_req (cf_cache_clean_req), - .o_cache_clean_done (tr_cache_clean_done), - .o_wb_cyc_ff (), - .o_wb_cyc_nxt (wb_cyc[1]), - .o_wb_stb_ff (), - .o_wb_stb_nxt (wb_stb[1]), - .o_wb_adr_ff (), - .o_wb_adr_nxt (wb_adr[1]), - .o_wb_dat_ff (), - .o_wb_dat_nxt (wb_dat[1]), - .o_wb_sel_ff (), - .o_wb_sel_nxt (wb_sel[1]), - .o_wb_wen_ff (), - .o_wb_wen_nxt (wb_wen[1]), - .o_wb_cti_ff (), - .o_wb_cti_nxt (wb_cti[1]), - .i_wb_dat (i_wb_dat), - .i_wb_ack (wb_ack[1]) -); - -// ZAP TLB control module. Includes TLB RAM inside. -zap_tlb #( - .LPAGE_TLB_ENTRIES (LPAGE_TLB_ENTRIES), - .SPAGE_TLB_ENTRIES (SPAGE_TLB_ENTRIES), - .SECTION_TLB_ENTRIES (SECTION_TLB_ENTRIES)) -u_zap_tlb ( - .i_clk (i_clk), - .i_reset (i_reset), - .i_address (i_address), - .i_address_nxt (i_address_nxt), - .i_rd (i_rd), - .i_wr (i_wr), - .i_cpsr (i_cpsr), - .i_sr (i_sr), - .i_dac_reg (i_dac_reg), - .i_baddr (i_baddr), - .i_mmu_en (i_mmu_en), - .i_inv (i_tlb_inv), - .o_phy_addr (tlb_phy_addr), - .o_fsr (tlb_fsr), - .o_far (tlb_far), - .o_fault (tlb_fault), - .o_cacheable (tlb_cacheable), - .o_busy (tlb_busy), - .o_wb_stb_nxt (wb_stb[2]), - .o_wb_cyc_nxt (wb_cyc[2]), - .o_wb_adr_nxt (wb_adr[2]), - .o_wb_wen_nxt (wb_wen[2]), - .o_wb_sel_nxt (wb_sel[2]), - .o_wb_dat_nxt (wb_dat[2]), - .i_wb_dat (i_wb_dat), - .i_wb_ack (wb_ack[2]) -); - -// Sequential Block -always @ ( posedge i_clk ) -begin - if ( i_reset ) - begin - state_ff <= S0; - o_wb_stb <= 1'd0; - o_wb_cyc <= 1'd0; - o_wb_adr <= 32'd0; - o_wb_cti <= CTI_CLASSIC; - o_wb_sel <= 4'd0; - o_wb_dat <= 32'd0; - o_wb_wen <= 1'd0; - end - else - begin - state_ff <= state_nxt; - o_wb_stb <= o_wb_stb_nxt; - o_wb_cyc <= o_wb_cyc_nxt; - o_wb_adr <= o_wb_adr_nxt; - o_wb_cti <= o_wb_cti_nxt; - o_wb_sel <= o_wb_sel_nxt; - o_wb_dat <= o_wb_dat_nxt; - o_wb_wen <= o_wb_wen_nxt; - end -end - -// Next state logic. -always @* -begin - state_nxt = state_ff; - - // Change state only if strobe is inactive or strobe has just completed. - if ( !o_wb_stb || (o_wb_stb && i_wb_ack) ) - begin - casez({wb_cyc[2],wb_cyc[1],wb_cyc[0]}) - 3'b1?? : state_nxt = S2; // TLB. - 3'b01? : state_nxt = S1; // Tag. - 3'b001 : state_nxt = S0; // Cache. - default: state_nxt = state_ff; - endcase - end -end - -// Route ACKs to respective masters. -always @* -begin - wb_ack = 0; - - case(state_ff) - S0: wb_ack[0] = i_wb_ack; - S1: wb_ack[1] = i_wb_ack; - S2: wb_ack[2] = i_wb_ack; - endcase -end - -// Combo signals for external MUXing. -always @* -begin - o_wb_stb_nxt = wb_stb[state_nxt]; - o_wb_cyc_nxt = wb_cyc[state_nxt]; - o_wb_adr_nxt = wb_adr[state_nxt]; - o_wb_dat_nxt = wb_dat[state_nxt]; - o_wb_cti_nxt = wb_cti[state_nxt]; - o_wb_sel_nxt = wb_sel[state_nxt]; - o_wb_wen_nxt = wb_wen[state_nxt]; -end - -// synopsys translate_off - reg xerr = 0; - - always @ (posedge i_clk) - begin - // Check if data delivered to processor is 'x'. - if ( o_dat[0] === 1'dx && o_ack && i_rd ) - begin - xerr = xerr + 1; - $display($time, "Error : %m Data went to x when giving data to core."); - $stop; - end - end -// synopsys translate_on - -endmodule // zap_cache - -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_mem_inv_block.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_mem_inv_block.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_mem_inv_block.v (nonexistent) @@ -1,105 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////// -// // -// Copyright (C) 2016 - 2018 Revanth Kamaraj // -// // -// This program is free software; you can redistribute it and/or // -// modify it under the terms of the GNU General Public License // -// as published by the Free Software Foundation; either version 2 // -// of the License, or (at your option) any later version. // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program; if not, write to the Free Software // -// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, // -// USA. // -// // -////////////////////////////////////////////////////////////////////////////////// -// // -// Tag RAMs with single cycle clear. Finds the greatest use in TLBs. // -// // -////////////////////////////////////////////////////////////////////////////////// - -`default_nettype none - - -module zap_mem_inv_block #( - parameter DEPTH = 32, - parameter WIDTH = 32 // Not including valid bit. -)( - - - input wire i_clk, - input wire i_reset, - - // Write data. - input wire [WIDTH-1:0] i_wdata, - - // Write and read enable. - input wire i_wen, - input wire i_ren, - - // Invalidate entries in 1 cycle. - input wire i_inv, - - // Read and write address. - input wire [$clog2(DEPTH)-1:0] i_raddr, - input wire [$clog2(DEPTH)-1:0] i_waddr, - - // Read data and valid. - output wire [WIDTH-1:0] o_rdata, - output reg o_rdav -); - - -// Flops -reg [DEPTH-1:0] dav_ff; - -// Nets -wire [$clog2(DEPTH)-1:0] addr_r; -wire en_r; - - -assign addr_r = i_raddr; -assign en_r = i_ren; - - -// Block RAM. -zap_ram_simple #(.WIDTH(WIDTH), .DEPTH(DEPTH)) u_ram_simple ( - .i_clk ( i_clk ), - - .i_wr_en ( i_wen ), - .i_rd_en ( en_r ), - - .i_wr_data ( i_wdata ), - .o_rd_data ( o_rdata ), - - .i_wr_addr ( i_waddr ), - .i_rd_addr ( addr_r ) -); - - -// DAV flip-flop implementation. -always @ (posedge i_clk) -begin: flip_flops - if ( i_reset | i_inv ) - begin - dav_ff <= {DEPTH{1'd0}}; - o_rdav <= 1'd0; - end - else - begin - if ( i_wen ) - dav_ff [ i_waddr ] <= 1'd1; - - if ( en_r ) - o_rdav <= dav_ff [ addr_r ]; - end -end - - -endmodule // mem_inv_block.v -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_predecode_compress.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_predecode_compress.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_predecode_compress.v (nonexistent) @@ -1,596 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Implements a 16-bit instruction decoder. The 16-bit instruction set is -- -// -- not logically organized so as to save on encoding and thus the functs -- -// -- seem a bit complex. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_predecode_compress ( - // Clock and reset. - input wire i_clk, - - // Input from I-cache. - // Instruction and valid qualifier. - input wire [31:0] i_instruction, - input wire i_instruction_valid, - - // Offset input. - input wire [11:0] i_offset, - - // Interrupts. Active high level sensitive signals. - input wire i_irq, - input wire i_fiq, - - // Ensure compressed mode is active (T bit). - input wire i_cpsr_ff_t, - - // - // Outputs to the ARM decoder. - // - - // Instruction, valid, undefined by this decoder and force 32-bit - // align signals (requires memory to keep lower 2 bits as 00). - output reg [34:0] o_instruction, - output reg o_instruction_valid, - output reg o_und, - output reg o_force32_align, - - // Interrupt status output. - output reg o_irq, - output reg o_fiq -); - -/////////////////////////////////////////////////////////////////////////////// - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -reg [11:0] offset_w; // Previous offset. - -/////////////////////////////////////////////////////////////////////////////// - -always @* - offset_w = i_offset; - -/////////////////////////////////////////////////////////////////////////////// - -always @* -begin - // If you are not in compressed mode, just pass stuff on. - o_instruction_valid = i_instruction_valid; - o_und = 0; - o_instruction = i_instruction; - o_irq = i_irq; - o_fiq = i_fiq; - o_force32_align = 0; - - if ( i_cpsr_ff_t && i_instruction_valid ) // compressed mode enable - begin - casez ( i_instruction[15:0] ) - T_BLX1 : decode_blx1; - T_BLX2 : decode_blx2; - T_ADD_SUB_LO : decode_add_sub_lo; - T_SWI : decode_swi; - T_BRANCH_COND : decode_conditional_branch; - T_BRANCH_NOCOND : decode_unconditional_branch; - T_BL : decode_bl; - T_BX : decode_bx; - T_SHIFT : decode_shift; - T_MCAS_IMM : decode_mcas_imm; // MOV,CMP,ADD,SUB IMM. - T_ALU_LO : decode_alu_lo; - T_ALU_HI : decode_alu_hi; - T_PC_REL_LOAD : decode_pc_rel_load; // LDR Rd, [PC, {#imm8,0,0}] - T_LDR_STR_5BIT_OFF : decode_ldr_str_5bit_off; - T_LDRH_STRH_5BIT_OFF : decode_ldrh_strh_5bit_off; - T_LDRH_STRH_REG : decode_ldrh_strh_reg; // Complex. - T_SP_REL_LDR_STR : decode_sp_rel_ldr_str; - T_LDMIA_STMIA : decode_ldmia_stmia; - T_POP_PUSH : decode_pop_push; - T_GET_ADDR : decode_get_addr; - T_MOD_SP : decode_mod_sp; - default: - begin - o_und = 1; // Will take UND trap. - end - endcase - end -end - -/////////////////////////////////////////////////////////////////////////////// - -task decode_get_addr; -begin: dcdGetAddr - reg [11:0] imm; - reg [3:0] rd; - - rd = i_instruction[10:8]; - imm[7:0] = i_instruction[7:0]; - imm[11:8] = 4'd15; // To achieve a left shift of 2 i.e., *4 - - o_instruction = 0; - - // ADD Rd, PC, imm - o_instruction[31:0] = {AL, 2'b00, 1'b1, ADD, 1'd0, 4'd15, rd, imm}; - - // ADD Rd, SP, imm - if ( i_instruction[11] ) // SP - begin - o_instruction[31:0] = {AL, 2'b00, 1'b1, ADD, 1'd0, 4'd13, rd, imm}; - end -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_mod_sp; -begin: dcdModSp - reg [11:0] imm; - - imm[7:0] = i_instruction[6:0]; - imm[11:8] = 4'd15; // To achieve a left shift of 2 i.e., *4 - - o_instruction = 0; - - o_instruction[31:0] = {AL, 2'b00, 1'b1, ADD, 1'd0, 4'd13, 4'd13, imm}; - - // SUB/ADD R13, R13, imm - if ( i_instruction[7] != 0 ) // SUB - begin - o_instruction[31:0] = {AL, 2'b00, 1'b1, SUB, 1'd0, 4'd13, 4'd13, imm}; - end -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_pop_push; -begin: decodePopPush - // - // Uses an FD stack. Thus it is DA type i.e., post index down by 4. - // Writeback is implicit so make W = 0. - // - - reg [3:0] base; - reg [15:0] reglist; - - o_instruction = 0; - base = 13; - - reglist = i_instruction[7:0]; - - if ( i_instruction[8] == 1 && i_instruction[11] ) // Pop. - begin - reglist[15] = 1'd1; - end - else if ( i_instruction[8] == 1 && !i_instruction[11] ) // Push. - begin - reglist[14] = 1'd1; - end - - o_instruction = {AL, 3'b100, 1'd0, 1'd0, 1'd0, 1'd1, i_instruction[11], - base, reglist}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_ldmia_stmia; -begin: dcdLdmiaStmia - // Implicit IA type i.e., post index up by 4. Make WB = 1. - - reg [3:0] base; - reg [15:0] reglist; - - base = i_instruction[10:8]; - reglist = i_instruction[7:0]; - - o_instruction = 0; - o_instruction = {AL, 3'b100, 1'd0, 1'd1, 1'd0, 1'd1, i_instruction[11], - base, reglist}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_sp_rel_ldr_str; -begin: dcdLdrRelStr - reg [3:0] srcdest; - reg [3:0] base; - reg [11:0] imm; - - srcdest = i_instruction[10:8]; - base = ARCH_SP; - imm = i_instruction[7:0] << 2; - - o_instruction = 0; - o_instruction = {AL, 3'b010, 1'd1, 1'd0, 1'd0, 1'd0, i_instruction[11], - base, srcdest, imm}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_ldrh_strh_reg; -begin: dcdLdrhStrh - // Use different load store format, instead of 3'b010, use 3'b011 - - reg X,S,H; - reg [3:0] srcdest, base; - reg [11:0] offset; - - X = i_instruction[9]; - S = i_instruction[10]; - H = i_instruction[11]; - srcdest = i_instruction[2:0]; - base = i_instruction[5:3]; - offset = i_instruction[8:6]; - - o_instruction = 0; - - if ( X == 0 ) - begin - case({H,S}) - 0: o_instruction = {AL, 3'b011, 1'd1, 1'd0, 1'd0, 1'd0, 1'd0, base, srcdest, offset};// STR - 1: o_instruction = {AL, 3'b011, 1'd1, 1'd0, 1'd1, 1'd0, 1'd0, base, srcdest, offset};// STRB - 2: o_instruction = {AL, 3'b011, 1'd1, 1'd0, 1'd0, 1'd0, 1'd1, base, srcdest, offset};// LDR - 3: o_instruction = {AL, 3'b011, 1'd1, 1'd0, 1'd1, 1'd0, 1'd1, base, srcdest, offset};// LDRB - endcase - end - else - begin - case({S,H}) - 0: o_instruction = {AL, 3'b000, 1'd1, 1'd0, 1'd0, 1'd0, 1'd0, base, srcdest, 4'd0, 2'b01,offset[3:0]};// STRH - 1: o_instruction = {AL, 3'b000, 1'd1, 1'd0, 1'd0, 1'd0, 1'd1, base, srcdest, 4'd0, 2'b01,offset[3:0]};// LDRH - 2: o_instruction = {AL, 3'b000, 1'd1, 1'd0, 1'd0, 1'd0, 1'd1, base, srcdest, 4'd0, 2'b10,offset[3:0]};// LDSB - 3: o_instruction = {AL, 3'b000, 1'd1, 1'd0, 1'd0, 1'd0, 1'd1, base, srcdest, 4'd0, 2'b11,offset[3:0]};// LDSH - endcase - end -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_ldrh_strh_5bit_off; -begin: dcdLdrhStrh5BitOff - - reg [3:0] rn; - reg [3:0] rd; - reg [7:0] imm; - - o_instruction = 0; - - rn = i_instruction[5:3]; - rd = i_instruction[2:0]; - imm[7:0] = i_instruction[10:6] << 1; - - // Unsigned halfword transfer - o_instruction = {AL, 3'b000, 1'd1, 1'd0, 1'd1, 1'd0, i_instruction[11], - rn, rd, imm[7:4], 2'b01,imm[3:0]}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_ldr_str_5bit_off; -begin: dcLdrStr5BitOff - reg [3:0] rn; - reg [3:0] rd; - reg [11:0] imm; - - o_instruction = 0; - - rn = i_instruction[5:3]; - rd = i_instruction[2:0]; - - if ( i_instruction[12] == 1'd0 ) - imm[11:0] = i_instruction[10:6] << 2; - else - imm[11:0] = i_instruction[10:6]; - - o_instruction = {AL, 3'b010, 1'd1, 1'd0, i_instruction[12], 1'd0, - i_instruction[11], rn, rd, imm}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_pc_rel_load; -begin: dcPcRelLoad - reg [3:0] rd; - reg [11:0] imm; - - rd = i_instruction[10:8]; - imm = i_instruction[7:0] << 2; - - o_force32_align = 1'd1; - o_instruction = 0; - o_instruction = {AL, 3'b010, 1'd1, 1'd0, 1'd0, 1'd0, - 1'd1, 4'b1111, rd, imm}; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_alu_hi; -begin:dcAluHi - // Performs operations on HI registers (atleast some of them). - reg [1:0] op; - reg [3:0] rd; - reg [3:0] rs; - - o_instruction = 0; - - op = i_instruction[9:8]; - rd = {i_instruction[7], i_instruction[2:0]}; - rs = {i_instruction[6], i_instruction[5:3]}; - - case(op) - 0: o_instruction[31:0] = {AL, 2'b00, 1'b0, ADD, 1'b0, rd, rd, 8'd0, rs}; // ADD Rd, Rd, Rs - 1: o_instruction[31:0] = {AL, 2'b00, 1'b0, CMP, 1'b1, rd, rd, 8'd0, rs}; // CMP Rd, Rs - 2: o_instruction[31:0] = {AL, 2'b00, 1'b0, MOV, 1'b0, rd, rd, 8'd0, rs}; // MOV Rd, Rs - 3: - begin - $display($time, "%m: Error: This should never happen, should be taken by BX...!"); - $finish; - end - endcase -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_alu_lo; -begin: tskDecAluLo - reg [3:0] op; - reg [3:0] rs, rd; - reg [3:0] rn; - - op = i_instruction[9:6]; - rs = i_instruction[5:3]; - rd = i_instruction[2:0]; - - o_instruction = 0; - - case(op) - 0: o_instruction[31:0] = {AL, 2'b00, 1'b0, AND, 1'd1, rd, rd, 8'd0, rs}; // ANDS Rd, Rd, Rs - 1: o_instruction[31:0] = {AL, 2'b00, 1'b0, EOR, 1'd1, rd, rd, 8'd0, rs}; // EORS Rd, Rd, Rs - 2: o_instruction[31:0] = {AL, 2'b00, 1'b0, MOV, 1'd1, rd, rd, rs, 1'd0, LSL, 1'd1, rd}; // MOVS Rd, Rd, LSL Rs - 3: o_instruction[31:0] = {AL, 2'b00, 1'b0, MOV, 1'd1, rd, rd, rs, 1'd0, LSR, 1'd1, rd}; // MOVS Rd, Rd, LSR Rs - 4: o_instruction[31:0] = {AL, 2'b00, 1'b0, MOV, 1'd1, rd, rd, rs, 1'd0, ASR, 1'd1, rd}; // MOVS Rd, Rd, ASR Rs - 5: o_instruction[31:0] = {AL, 2'b00, 1'b0, ADC, 1'd1, rd, rd, 8'd0, rs}; // ADCS Rd, Rd, Rs - 6: o_instruction[31:0] = {AL, 2'b00, 1'b0, SBC, 1'd1, rd, rd, 8'd0, rs}; // SBCS Rd, Rs, Rs - 7: o_instruction[31:0] = {AL, 2'b00, 1'b0, MOV, 1'd1, rd, rd, rs, 1'd0, ROR, 1'd1, rd}; // MOVS Rd, Rd, ROR Rs. - 8: o_instruction[31:0] = {AL, 2'b00, 1'b0, TST, 1'd1, rd, rd, 8'd0, rs}; // TST Rd, Rs - 9: o_instruction[31:0] = {AL, 2'b00, 1'b1, RSB, 1'd1, rs, rd, 12'd0}; // Rd = 0 - Rs - 10: o_instruction[31:0] = {AL, 2'b00, 1'b1, CMP, 1'd1, rd, rd, 8'd0, rs}; // CMP Rd, Rs - 11: o_instruction[31:0] = {AL, 2'b00, 1'b1, CMN, 1'd1, rd, rd, 8'd0, rs}; // CMN Rd, Rs - 12: o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd1, rd, rd, 8'd0, rs}; // ORRS Rd, Rd, rs - 13: o_instruction[31:0] = {AL, 4'b0000, 3'b000, 1'd1, rd, 4'd0, rd, 4'b1001, rs}; // MULS Rd, Rs, Rd - 14: o_instruction[31:0] = {AL, 2'b00, 1'b1, BIC, 1'd1, rd, rd, 8'd0, rs}; // BICS rd, rd, rs - 15: o_instruction[31:0] = {AL, 2'b00, 1'b1, MVN, 1'd1, rd, rd, 8'd0, rs}; // MVNS rd, rd, rs - endcase -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_mcas_imm; -begin: tskDecodeMcasImm - reg [1:0] op; - reg [3:0] rd; - reg [11:0] imm; - - o_instruction = 0; - - op = i_instruction[12:11]; - rd = i_instruction[10:8]; - imm =i_instruction[7:0]; - - case (op) - 0: - begin - // MOV Rd, Offset8 - o_instruction[31:0] = {AL, 2'b00, 1'b1, MOV, 1'd1, rd, rd, imm}; - end - 1: - begin - // CMP Rd, Offset8 - o_instruction[31:0] = {AL, 2'b00, 1'b1, CMP, 1'd1, rd, rd, imm}; - end - 2: - begin - // ADDS Rd, Rd, Offset8 - o_instruction[31:0] = {AL, 2'b00, 1'b1, ADD, 1'd1, rd, rd, imm}; - end - 3: - begin - // SUBS Rd, Rd, Offset8 - o_instruction[31:0] = {AL, 2'b00, 1'b1, SUB, 1'd1, rd, rd, imm}; - end - endcase -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_add_sub_lo; -begin: tskDecodeAddSubLo - reg [3:0] rn, rd, rs; - reg [11:0] imm; - - o_instruction = 0; - - rn = i_instruction[8:6]; - rd = i_instruction[2:0]; - rs = i_instruction[5:3]; - imm = rn; - - case({i_instruction[9], i_instruction[10]}) - 0: - begin - // Add Rd, Rs, Rn - Instr spec shift. - o_instruction[31:0] = {AL, 2'b00, 1'b0, ADD, 1'd1, rs, rd, 8'd0, rn}; - end - 1: - begin - // Adds Rd, Rs, #Offset3 - Immediate. - o_instruction[31:0] = {AL, 2'b00, 1'b1, ADD, 1'd1, rn, rd, imm}; - end - 2: - begin - // SUBS Rd, Rs, Rn - Instr spec shift. - o_instruction[31:0] = {AL, 2'b00, 1'b0, SUB, 1'd1, rs, rd, 8'd0, rn}; - end - 3: - begin - // SUBS Rd, Rs, #Offset3 - Immediate. - o_instruction[31:0] = {AL, 2'b00, 1'b1, SUB, 1'd1, rn, rd, imm}; - end - endcase -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_conditional_branch; -begin - // An MSB of 1 indicates a left shift of 1. - o_instruction = {1'd1, 2'b0, i_instruction[11:8], 3'b101, 1'b0, 24'd0}; - o_instruction[23:0] = $signed(i_instruction[7:0]); -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_unconditional_branch; -begin - // An MSB of 1 indicates a left shift of 1. - o_instruction = {1'd1, 2'b0, AL, 3'b101, 1'b0, 24'd0}; - o_instruction[23:0] = $signed(i_instruction[10:0]); -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_blx1; -begin - o_instruction = 0; // Default value. - - // Generate a BLX1. - o_instruction[31:25] = 7'b1111_101; // BLX1 identifier. - o_instruction[24] = 1'd0; // H - bit. - o_instruction[23:0] = ($signed(offset_w) << 12) | (i_instruction[10:0] << 1); // Corrected. - o_irq = 1'd0; - o_fiq = 1'd0; -end -endtask - -//////////////////////////////////////////////////////////////////////////////// - -task decode_blx2; -begin - o_instruction = {4'b1110,4'b0001,4'b0010,4'b1111,4'b1111,4'b1111,4'b0011, i_instruction[6:3]}; - o_irq = 1'd0; - o_fiq = 1'd0; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_bl; -begin - case ( i_instruction[11] ) - 1'd0: - begin - // Send out a dummy instruction. Preserve lower - // 12-bits though to serve as offset. Set condition - // code to NV. - o_instruction = i_instruction[11:0]; - o_instruction[31:28] = 4'b1111; - o_irq = 1'd0; - o_fiq = 1'd0; - end - 1'd1: - begin - // Generate a full jump. - o_instruction = {1'd1, 2'b0, AL, 3'b101, 1'b1, 24'd0}; - o_instruction[23:0] = ($signed(offset_w) << 12) | (i_instruction[10:0] << 1); // Corrected. - o_irq = 1'd0; - o_fiq = 1'd0; - end - endcase -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_bx; -begin - // Generate a BX Rm. - o_instruction = 32'b0000_0001_0010_1111_1111_1111_0001_0000; - o_instruction[31:28] = AL; - o_instruction[3:0] = i_instruction[6:3]; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_swi; -begin - // Generate a SWI. - o_instruction = 32'b0000_1111_0000_0000_0000_0000_0000_0000; - o_instruction[31:28] = AL; - o_instruction[7:0] = i_instruction[7:0]; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -task decode_shift; -begin - // Compressed shift instructions. Decompress to ARM with instruction specified shift. - o_instruction = 32'd0; // Extension -> 0. - o_instruction[31:28] = AL; // Always execute. - o_instruction[27:26] = 2'b00; // Data processing. - o_instruction[25] = 1'd0; // Immediate is ZERO. - o_instruction[24:21] = MOV; // Operation is MOV. - o_instruction[20] = 1'd1; // Do update flags. - o_instruction[19:16] = 4'd0; // ALU source. Doesn't matter. - o_instruction[15:12] = i_instruction[2:0] ; // Destination. - o_instruction[11:7] = i_instruction[10:6]; // Shamt. - o_instruction[6:5] = i_instruction[12:11]; // Shtype. - o_instruction[3:0] = i_instruction[5:3]; // Shifter source. -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -endmodule -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_writeback.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_writeback.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_writeback.v (nonexistent) @@ -1,445 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_writeback #( - parameter FLAG_WDT = 32, // Flags width a.k.a CPSR. - parameter PHY_REGS = 46 // Number of physical registers. -) -( - // Decompile. - input wire [64*8-1:0] i_decompile, - output reg [64*8-1:0] o_decompile, - - // Shelve output. - output wire o_shelve, - - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // Inputs from memory unit valid signal. - input wire i_valid, - - // The PC can either be frozen in place or changed based on signals - // from other units. If a unit clears the PC, it must provide the - // appropriate new value. - input wire i_code_stall, - input wire i_data_stall, - input wire i_clear_from_alu, - input wire [31:0] i_pc_from_alu, - input wire i_stall_from_decode, - input wire i_stall_from_issue, - input wire i_stall_from_shifter, - input wire i_clear_from_decode, - input wire [31:0] i_pc_from_decode, - - // 4 read ports for high performance. - input wire [$clog2(PHY_REGS)-1:0] i_rd_index_0, - input wire [$clog2(PHY_REGS)-1:0] i_rd_index_1, - input wire [$clog2(PHY_REGS)-1:0] i_rd_index_2, - input wire [$clog2(PHY_REGS)-1:0] i_rd_index_3, - - // Memory load indicator. - input wire i_mem_load_ff, - - // Write index and data and flag updates. - input wire [$clog2(PHY_REGS)-1:0] i_wr_index, - input wire [31:0] i_wr_data, - input wire [FLAG_WDT-1:0] i_flags, - input wire i_thumb, - input wire [$clog2(PHY_REGS)-1:0] i_wr_index_1, - input wire [31:0] i_wr_data_1, - - // Interrupt indicators. - input wire i_irq, - input wire i_fiq, - input wire i_instr_abt, - input wire i_data_abt, - input wire i_swi, - input wire i_und, - - // Program counter, PC + 8. This value is captured in the fetch - // stage and is buffered all the way through. - input wire [31:0] i_pc_buf_ff, - - // Coprocessor. - input wire i_copro_reg_en, - input wire [$clog2(PHY_REGS)-1:0] i_copro_reg_wr_index, - input wire [$clog2(PHY_REGS)-1:0] i_copro_reg_rd_index, - input wire [31:0] i_copro_reg_wr_data, - output reg [31:0] o_copro_reg_rd_data_ff, - - // Read data from the register file. - output wire [31:0] o_rd_data_0, - output wire [31:0] o_rd_data_1, - output wire [31:0] o_rd_data_2, - output wire [31:0] o_rd_data_3, - - // Program counter (dedicated port). - output wire [31:0] o_pc, - output wire [31:0] o_pc_nxt, - - // CPSR output - output wire [31:0] o_cpsr_nxt, - - // Clear from writeback - output reg o_clear_from_writeback, - - // Hijack I/F - output reg [31:0] o_hijack_op1, - output reg [31:0] o_hijack_op2, - output reg o_hijack_cin, - output reg o_hijack, - input wire [31:0] i_hijack_sum -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -// ---------------------------------------------------------------------------- -// Localparams -// ---------------------------------------------------------------------------- - -`ifndef ARM_MODE - `define ARM_MODE (cpsr_ff[T] == 1'd0) -`endif - -localparam RST_VECTOR = 32'h00000000; -localparam UND_VECTOR = 32'h00000004; -localparam SWI_VECTOR = 32'h00000008; -localparam PABT_VECTOR = 32'h0000000C; -localparam DABT_VECTOR = 32'h00000010; -localparam IRQ_VECTOR = 32'h00000018; -localparam FIQ_VECTOR = 32'h0000001C; - -// ---------------------------------------------------------------------------- -// Variables -// ---------------------------------------------------------------------------- - -reg [31:0] cpsr_ff, cpsr_nxt; -reg [31:0] pc_ff, pc_nxt; -reg [$clog2(PHY_REGS)-1:0] wa1, wa2; -reg [31:0] wdata1, wdata2; -reg wen; -reg [31:0] pc_shelve_ff, pc_shelve_nxt; -reg shelve_ff, shelve_nxt; - -assign o_shelve = shelve_ff; // Shelve the PC until it is needed. -assign o_pc = pc_ff; -assign o_pc_nxt = pc_nxt & 32'hfffffffe; -assign o_cpsr_nxt = cpsr_nxt; - -// ---------------------------------------------------------------------------- -// Register file -// ---------------------------------------------------------------------------- - -zap_register_file u_zap_register_file -( -.i_clk(i_clk), - .i_reset ( i_reset ), - - .i_wr_addr_a ( wa1 ), - .i_wr_addr_b ( wa2 ), - - .i_wr_data_a ( wdata1 ), - .i_wr_data_b ( wdata2 ), - - .i_wen ( wen ), - - .i_rd_addr_a ( i_copro_reg_en ? i_copro_reg_rd_index : i_rd_index_0 ), - .i_rd_addr_b ( i_rd_index_1 ), - .i_rd_addr_c ( i_rd_index_2 ), - .i_rd_addr_d ( i_rd_index_3 ), - - .o_rd_data_a ( o_rd_data_0 ), - .o_rd_data_b ( o_rd_data_1 ), - .o_rd_data_c ( o_rd_data_2 ), - .o_rd_data_d ( o_rd_data_3 ) -); - -// ---------------------------------------------------------------------------- -// Combinational Logic -// ---------------------------------------------------------------------------- - -always @ (*) -begin: blk1 - - integer i; - - shelve_nxt = shelve_ff; - pc_shelve_nxt = pc_shelve_ff; - - o_hijack = 0; - o_hijack_op1 = 0; - o_hijack_op2 = 0; - o_hijack_cin = 0; - - wen = 1'd0; - wa1 = PHY_RAZ_REGISTER; - wa2 = PHY_RAZ_REGISTER; - wdata1 = 32'd0; - wdata2 = 32'd0; - - o_clear_from_writeback = 0; - - pc_nxt = pc_ff; - cpsr_nxt = cpsr_ff; - - - // Low priority PC control tree. - - if ( i_clear_from_alu ) - begin - pc_shelve(i_pc_from_alu); - end - - else if ( i_clear_from_decode ) - begin - pc_shelve(i_pc_from_decode); - end - - else if ( i_code_stall ) - begin - pc_nxt = pc_ff; - end - else if ( shelve_ff ) - begin - - pc_nxt = pc_shelve_ff; - shelve_nxt = 1'd0; - end - else - begin - pc_nxt = pc_ff + (i_thumb ? 32'd2 : 32'd4); - end - - - // The stuff below has more priority than the above. This means even in - // a global stall, interrupts can overtake execution. Further, writes to - // PC that reach writeback can cancel a global stall. On interrupts or - // jumps, all units are flushed effectively clearing any global stalls. - - if ( i_data_abt || - i_fiq || - i_irq || - i_instr_abt || - i_swi || - i_und ) - begin - o_clear_from_writeback = 1'd1; - cpsr_nxt[I] = 1'd1; // Mask interrupts. - cpsr_nxt[T] = 1'd0; // Go to ARM mode. - end - - if ( i_data_abt ) - begin - o_hijack = 1'd1; - o_hijack_op1 = i_pc_buf_ff; - o_hijack_op2 = 32'd4; - o_hijack_cin = 1'd0; - - // Returns do LR - 8 to get back to the same instruction. - pc_shelve( DABT_VECTOR ); - - wen = 1; - wdata1 = `ARM_MODE ? i_pc_buf_ff : i_hijack_sum[31:0]; - wa1 = PHY_ABT_R14; - wa2 = PHY_ABT_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = ABT; - end - else if ( i_fiq ) - begin - // Returns do LR - 4 to get back to the same instruction. - pc_shelve ( FIQ_VECTOR ); - - wen = 1; - wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ; - wa1 = PHY_FIQ_R14; - wa2 = PHY_FIQ_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = FIQ; - cpsr_nxt[F] = 1'd1; - end - else if ( i_irq ) - begin - pc_shelve (IRQ_VECTOR); - - wen = 1; - wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ; - wa1 = PHY_IRQ_R14; - wa2 = PHY_IRQ_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = IRQ; - // Returns do LR - 4 to get back to the same instruction. - end - else if ( i_instr_abt ) - begin - // Returns do LR - 4 to get back to the same instruction. - pc_shelve (PABT_VECTOR); - - wen = 1; - wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ; - wa1 = PHY_ABT_R14; - wa2 = PHY_ABT_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = ABT; - end - else if ( i_swi ) - begin - // Returns do LR to return to the next instruction. - pc_shelve(SWI_VECTOR); - - wen = 1; - wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ; - wa1 = PHY_SVC_R14; - wa2 = PHY_SVC_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = SVC; - end - else if ( i_und ) - begin - // Returns do LR to return to the next instruction. - pc_shelve(UND_VECTOR); - - wen = 1; - wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ; - wa1 = PHY_UND_R14; - wa2 = PHY_UND_SPSR; - wdata2 = cpsr_ff; - cpsr_nxt[`CPSR_MODE] = UND; - end - else if ( i_copro_reg_en ) - begin - // Write to register (Coprocessor command). - wen = 1; - wa1 = i_copro_reg_wr_index; - wdata1 = i_copro_reg_wr_data; - end - else if ( i_valid ) // If valid, - begin - // Only then execute the instruction at hand... - cpsr_nxt = i_flags; - - // Dual write port. - wen = 1; - - // Port from arithmetic side - wa1 = i_wr_index; - wdata1 = i_wr_data; - - // Port from memory side. - wa2 = i_mem_load_ff ? i_wr_index_1 : PHY_RAZ_REGISTER; - wdata2 = i_wr_data_1; - - // Load to PC will trigger from writeback. - if ( i_mem_load_ff && i_wr_index_1 == ARCH_PC) - begin - pc_shelve (i_wr_data_1); - o_clear_from_writeback = 1'd1; - end - end - - // Ensure lower 2 bits of PC are always tied to VSS. - pc_nxt = pc_nxt & 32'hffff_fffe; -end - -// ---------------------------------------------------------------------------- -// Sequential Logic -// ---------------------------------------------------------------------------- - -always @ ( posedge i_clk ) -begin - if ( i_reset ) - begin - // On reset, the CPU starts at 0 in - // supervisor mode. - shelve_ff <= 1'd0; - pc_ff <= 32'd0; - cpsr_ff <= SVC; - cpsr_ff[I] <= 1'd1; // Mask IRQ. - cpsr_ff[F] <= 1'd1; // Mask FIQ. - cpsr_ff[T] <= 1'd0; // Start CPU in ARM mode. - end - else - begin - shelve_ff <= shelve_nxt; - pc_shelve_ff <= pc_shelve_nxt; - pc_ff <= pc_nxt; - cpsr_ff <= cpsr_nxt; - o_decompile <= i_decompile; - o_copro_reg_rd_data_ff <= o_rd_data_0; - end -end - -// ---------------------------------------------------------------------------- -// Tasks -// ---------------------------------------------------------------------------- - -task pc_shelve (input [31:0] new_pc); -begin - if (!i_code_stall ) - begin - pc_nxt = new_pc; - shelve_nxt = 1'd0; // BUG FIX. - end - else - begin - shelve_nxt = 1'd1; - pc_shelve_nxt = new_pc; - pc_nxt = pc_ff; - end -end -endtask - -always @ (*) -if ( cpsr_nxt[`CPSR_MODE] != USR && cpsr_ff[`CPSR_MODE] == USR ) -begin - if ( - i_data_abt || - i_fiq || - i_irq || - i_instr_abt || - i_swi || - i_und - ) - begin - // OKAY... - end - else - begin - $display($time, "Error : %m CPU is changing out of USR mode without an exception..."); - $stop; - end -end - -endmodule // zap_register_file.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// END OF FILE -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_cp15_cb.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_cp15_cb.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_cp15_cb.v (nonexistent) @@ -1,542 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This RTL describes the CP15 register block. The ports go to the MMU and -- -// -- cache unit. This block connects to the CPU core. Coprocessor operations -- -// -- supported are read from coprocessor and write to CPU registers or vice -- -// -- versa. This is integrated within the processor. The MMU unit can easily -- -// -- interface with this block. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_cp15_cb #( - parameter PHY_REGS = 64 -) -( - // ---------------------------------------------------------------- - // Clock and reset. - // ---------------------------------------------------------------- - - input wire i_clk, - input wire i_reset, - - // ---------------------------------------------------------------- - // Coprocessor instruction and done signal. - // ---------------------------------------------------------------- - - input wire [31:0] i_cp_word, - input wire i_cp_dav, - output reg o_cp_done, - - // ---------------------------------------------------------------- - // CPSR from processor. - // ---------------------------------------------------------------- - - input wire [31:0] i_cpsr, - - // ---------------------------------------------------------------- - // Register file RW interface - // ---------------------------------------------------------------- - - // Asserted if we want to control of the register file. - // Controls a MUX that selects signals. - output reg o_reg_en, - - // Data to write to the register file. - output reg [31:0] o_reg_wr_data, - - // Data read from the register file. - input wire [31:0] i_reg_rd_data, - - // Write and read index for the register file. - output reg [$clog2(PHY_REGS)-1:0] o_reg_wr_index, - o_reg_rd_index, - - // ---------------------------------------------------------------- - // From MMU. - // ---------------------------------------------------------------- - - input wire [31:0] i_fsr, - input wire [31:0] i_far, - - // ----------------------------------------------------------------- - // MMU configuration signals. - // ----------------------------------------------------------------- - - // Domain Access Control Register. - output reg [31:0] o_dac, - - // Base address of page table. - output reg [31:0] o_baddr, - - // MMU enable. - output reg o_mmu_en, - - // SR register. - output reg [1:0] o_sr, - - // FCSE register. - output reg [7:0] o_pid, - - // ----------------------------------------------------------------- - // Invalidate and clean controls. - // ----------------------------------------------------------------- - - // Cache invalidate signal. - output reg o_dcache_inv, - output reg o_icache_inv, - - // Cache clean signal. - output reg o_dcache_clean, - output reg o_icache_clean, - - // TLB invalidate signal - single cycle. - output reg o_dtlb_inv, - output reg o_itlb_inv, - - // Cache enable. - output reg o_dcache_en, - output reg o_icache_en, - - // From MMU. Specify that cache invalidation is done. - input wire i_dcache_inv_done, - input wire i_icache_inv_done, - - // From MMU. Specify that cache clean is done. - input wire i_dcache_clean_done, - input wire i_icache_clean_done -); - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -// --------------------------------------------- -// Variables -// --------------------------------------------- - -reg [31:0] r [13:0];// Coprocessor registers. R7, R8 is write-only. -reg [3:0] state; // State variable. - -// --------------------------------------------- -// Localparams -// --------------------------------------------- - -// States. -localparam IDLE = 0; -localparam ACTIVE = 1; -localparam DONE = 2; -localparam READ = 3; -localparam READ_DLY = 4; -localparam TERM = 5; -localparam CLR_D_CACHE_AND = 6; -localparam CLR_D_CACHE = 7; -localparam CLR_I_CACHE = 8; -localparam CLEAN_D_CACHE = 9; -localparam CLEAN_ID_CACHE = 10; -localparam CLFLUSH_ID_CACHE = 11; -localparam CLFLUSH_D_CACHE = 12; - -// Register numbers. -localparam FSR_REG = 5; -localparam FAR_REG = 6; -localparam CACHE_REG = 7; -localparam TLB_REG = 8; -localparam FCSE_REG = 13; - -//{opcode_2, crm} values that are valid for this implementation. -localparam CASE_FLUSH_ID_CACHE = 7'b000_0111; -localparam CASE_FLUSH_I_CACHE = 7'b000_0101; -localparam CASE_FLUSH_D_CACHE = 7'b000_0110; -localparam CASE_CLEAN_ID_CACHE = 7'b000_1011; -localparam CASE_CLEAN_D_CACHE = 7'b000_1010; -localparam CASE_CLFLUSH_ID_CACHE = 7'b000_1111; -localparam CASE_CLFLUSH_D_CACHE = 7'b000_1110; -localparam CASE_FLUSH_ID_TLB = 7'b000_0111; -localparam CASE_FLUSH_I_TLB = 7'b000_0101; -localparam CASE_FLUSH_D_TLB = 7'b000_0110; - -// --------------------------------------------- -// Sequential Logic -// --------------------------------------------- - -// Ties registers to output ports via a register. -always @ ( posedge i_clk ) -begin - if ( i_reset ) - begin - o_dcache_en <= 1'd0; - o_icache_en <= 1'd0; - o_mmu_en <= 1'd0; - o_dac <= 32'dx; - o_baddr <= 32'dx; - o_sr <= 2'dx; - o_pid <= 8'd0; - end - else - begin - o_dcache_en <= r[1][2]; // Data cache enable. - o_icache_en <= r[1][12]; // Instruction cache enable. - o_mmu_en <= r[1][0]; // MMU enable. - o_dac <= r[3]; // DAC register. - o_baddr <= r[2]; // Base address. - o_sr <= {r[1][8],r[1][9]}; // SR register. - o_pid <= {1'd0, r[13][31:25]}; // PID register. - end -end - -// Core logic. -always @ ( posedge i_clk ) -begin - if ( i_reset ) - begin - state <= IDLE; - o_dcache_inv <= 1'd0; - o_icache_inv <= 1'd0; - o_dcache_clean <= 1'd0; - o_icache_clean <= 1'd0; - o_dtlb_inv <= 1'd0; - o_itlb_inv <= 1'd0; - o_reg_en <= 1'd0; - o_cp_done <= 1'd0; - o_reg_wr_data <= 0; - o_reg_wr_index <= 0; - o_reg_rd_index <= 0; - r[0] <= 32'h0; - r[1] <= 32'd0; - r[2] <= 32'd0; - r[3] <= 32'd0; - r[4] <= 32'd0; - r[5] <= 32'd0; - r[6] <= 32'd0; - r[13] <= 32'd0; //FCSE - - // R0 override. - generate_r0; - - // R1 override. - r[1][1] <= 1'd1; - r[1][3] <= 1'd1; - r[1][6:4] <= 3'b111; - r[1][11] <= 1'd1; - end - else - begin - // Default assignments. - o_itlb_inv <= 1'd0; - o_dtlb_inv <= 1'd0; - o_dcache_inv <= 1'd0; - o_icache_inv <= 1'd0; - o_icache_clean <= 1'd0; - o_dcache_clean <= 1'd0; - o_reg_en <= 1'd0; - o_cp_done <= 1'd0; - - case ( state ) - IDLE: // Idle state. - begin - o_cp_done <= 1'd0; - - // Keep monitoring FSR and FAR from MMU unit. If - // produced, clock them in. - if ( i_fsr[3:0] != 4'd0 ) - begin - r[FSR_REG] <= i_fsr; - r[FAR_REG] <= i_far; - end - - // Coprocessor instruction. - if ( i_cp_dav && i_cp_word[`cp_id] == 15 ) - begin - if ( i_cpsr[4:0] != USR ) - begin - // ACTIVATE this block. - state <= ACTIVE; - o_cp_done <= 1'd0; - end - else - begin - // No permissions in USR land. - // Pretend to be done and go ahead. - o_cp_done <= 1'd1; - end - end - end - - DONE: // Complete transaction. - begin - // Tell that we are done. - o_cp_done <= 1'd1; - state <= TERM; - end - - TERM: // Wait state before going to IDLE. - begin - state <= IDLE; - end - - READ_DLY: // Register data is clocked out in this stage. - begin - state <= READ; - end - - READ: // Write value read from CPU register to coprocessor. - begin - state <= DONE; - - r [ i_cp_word[`crn] ] <= i_reg_rd_data; - - if ( - i_cp_word[`crn] == TLB_REG // TLB control. - ) - begin - case({i_cp_word[`opcode_2], i_cp_word[`crm]}) - - CASE_FLUSH_ID_TLB: - begin - o_itlb_inv <= 1'd1; - o_dtlb_inv <= 1'd1; - end - - CASE_FLUSH_I_TLB: - begin - o_itlb_inv <= 1'd1; - end - - CASE_FLUSH_D_TLB: - begin - o_dtlb_inv <= 1'd1; - end - - default: - begin - o_itlb_inv <= 1'd1; - o_dtlb_inv <= 1'd1; - end - - endcase - end - else if ( i_cp_word[`crn] == CACHE_REG ) // Cache control. - begin - case({i_cp_word[`opcode_2], i_cp_word[`crm]}) - CASE_FLUSH_ID_CACHE: - begin - // Invalidate caches. - o_dcache_inv <= 1'd1; - state <= CLR_D_CACHE_AND; - end - - CASE_FLUSH_D_CACHE: - begin - - // Invalidate data cache. - o_dcache_inv <= 1'd1; - state <= CLR_D_CACHE; - end - - CASE_FLUSH_I_CACHE: - begin - - // Invalidate instruction cache. - o_icache_inv <= 1'd1; - state <= CLR_I_CACHE; - end - - CASE_CLEAN_ID_CACHE, CASE_CLEAN_D_CACHE: - begin - - o_dcache_clean <= 1'd1; - state <= CLEAN_D_CACHE; - end - - CASE_CLFLUSH_D_CACHE: - begin - - o_dcache_clean <= 1'd1; - state <= CLFLUSH_D_CACHE; - end - - CASE_CLFLUSH_ID_CACHE: - begin - - o_dcache_clean <= 1'd1; - state <= CLFLUSH_ID_CACHE; - end - - default: - begin - o_dcache_clean <= 1'd1; - state <= CLFLUSH_ID_CACHE; - end - - endcase - end - end - - // States. - CLEAN_D_CACHE, - CLFLUSH_ID_CACHE, - CLFLUSH_D_CACHE: - begin - o_dcache_clean <= 1'd1; - - if ( i_dcache_clean_done ) - begin - o_dcache_clean <= 1'd0; - - if ( state == CLFLUSH_D_CACHE ) - begin - o_dcache_inv <= 1'd1; - state <= CLR_D_CACHE; - end - else if ( state == CLFLUSH_ID_CACHE ) - begin - o_dcache_inv <= 1'd1; - state <= CLR_D_CACHE_AND; - end - else // CLEAN_D_CACHE - begin - state <= DONE; - end - end - end - - CLR_D_CACHE, CLR_D_CACHE_AND: // Clear data cache. - begin - o_dcache_inv <= 1'd1; - - // Wait for cache invalidation to complete. - if ( i_dcache_inv_done && state == CLR_D_CACHE ) - begin - o_dcache_inv <= 1'd0; - state <= DONE; - end - else if ( state == CLR_D_CACHE_AND && i_dcache_inv_done ) - begin - o_dcache_inv <= 1'd0; - o_icache_inv <= 1'd1; - state <= CLR_I_CACHE; - end - end - - CLR_I_CACHE: // Clear instruction cache. - begin - o_icache_inv <= 1'd1; - - if ( i_icache_inv_done ) - begin - o_icache_inv <= 1'd0; - state <= DONE; - end - end - - ACTIVE: // Access processor registers. - begin - if ( is_cc_satisfied ( i_cp_word[31:28], i_cpsr[31:28] ) ) - begin - if ( i_cp_word[20] ) // Load to CPU reg. - begin - // Generate CPU Register write command. CP read. - o_reg_en <= 1'd1; - o_reg_wr_index <= translate( i_cp_word[15:12], i_cpsr[4:0] ); - o_reg_wr_data <= r[ i_cp_word[19:16] ]; - state <= DONE; - end - else // Store to CPU register. - begin - // Generate CPU register read command. CP write. - o_reg_en <= 1'd1; - o_reg_rd_index <= translate(i_cp_word[15:12], i_cpsr[4:0]); - o_reg_wr_index <= 16; - state <= READ_DLY; - end - end - else - begin - state <= DONE; - end - - // Process unconditional words to CP15. - casez ( i_cp_word ) - MCR2, MRC2, LDC2, STC2: - begin - if ( i_cp_word[20] ) // Load to CPU reg. - begin - // Register write command. - o_reg_en <= 1'd1; - o_reg_wr_index <= translate( i_cp_word[15:12], i_cpsr[4:0] ); - o_reg_wr_data <= r[ i_cp_word[19:16] ]; - state <= DONE; - end - else // Store to CPU register. - begin - // Generate register read command. - o_reg_en <= 1'd1; - o_reg_rd_index <= translate(i_cp_word[15:12], i_cpsr[4:0]); - o_reg_wr_index <= 16; - state <= READ_DLY; - end - end - endcase - end - endcase - - // Default assignments. These bits are unchangeable. - generate_r0; - - r[1][1] <= 1'd1; - r[1][3] <= 1'd1; // Write buffer always enabled. - r[1][6:4] <= 3'b111; // 0 = Little Endian, 0 = 0, 1 = 32-bit address range, - // 1 = 32-bit handlers enabled. - r[1][11] <= 1'd1; - end -end - -// CPU info register. -task generate_r0; -begin - r[0][3:0] <= 4'd0; - r[0][15:4] <= 12'hAAA; - r[0][19:16] <= 4'h4; - r[0][23:20] <= 4'd0; - r[0][31:24] <= 8'd0; -end -endtask - -wire [31:0] r0 = r[0]; -wire [31:0] r1 = r[1]; -wire [31:0] r2 = r[2]; -wire [31:0] r3 = r[3]; -wire [31:0] r4 = r[4]; -wire [31:0] r5 = r[5]; -wire [31:0] r6 = r[6]; - -endmodule - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_tlb_check.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_tlb_check.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_tlb_check.v (nonexistent) @@ -1,262 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Examines TLB entries to authorize access. Purely combo logic. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_tlb_check ( // ZAP TLB Processing Logic. - -i_mmu_en, // MMU enable. - -// Dynamics -i_va, // Virtual address. -i_rd, // WB rd. -i_wr, // WB wr. - -// Static almost. -i_cpsr, -i_sr, -i_dac_reg, - -// Data from TLB dist RAMs. -i_sptlb_rdata, i_sptlb_rdav, -i_lptlb_rdata, i_lptlb_rdav, -i_setlb_rdata, i_setlb_rdav, - -// Outputs to other units. -o_walk, // Need to page walk. -o_fsr, // FSR. -o_far, // FAR. 0 means no fault. This is a 4-bit number. -o_cacheable, // Cacheable based on PTE. -o_phy_addr // Physical address. - -); - -// Pass this from top. -parameter LPAGE_TLB_ENTRIES = 8; -parameter SPAGE_TLB_ENTRIES = 8; -parameter SECTION_TLB_ENTRIES = 8; - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -input wire i_mmu_en; // MMU enable. - -input wire [31:0] i_va; // Virtual address. -input wire i_rd; // Read request. -input wire i_wr; // Write request. - -input wire [31:0] i_cpsr; // CPSR. -input wire [1:0] i_sr; // Status Register. -input wire [31:0] i_dac_reg; // Domain Access Control Register. - -input wire [`SPAGE_TLB_WDT -1:0] i_sptlb_rdata; // Small page TLB. -input wire i_sptlb_rdav; // TLB entry valid. - -input wire [`LPAGE_TLB_WDT -1:0] i_lptlb_rdata; // Large page TLB read data. -input wire i_lptlb_rdav; // Large page TLB valid. - -input wire [`SECTION_TLB_WDT-1:0] i_setlb_rdata; // Small page TLB read data. -input wire i_setlb_rdav; // Small page TLB valid. - -output reg o_walk; // Signal page walk. -output reg [7:0] o_fsr; // FSR. 0 means all OK. -output reg [31:0] o_far; // Fault Address Register. -output reg o_cacheable; // Cacheble stats of the PTE. -output reg [31:0] o_phy_addr; // Physical address. - -// ---------------------------------------------------------------------------- - -always @* -begin - // Default values. Taken for MMU disabled esp. - o_fsr = 0; // No fault. - o_far = i_va; // Fault address. - o_phy_addr = i_va; // VA = PA - o_walk = 0; // Walk disabled. - o_cacheable = 0; // Uncacheable. - - if ( i_mmu_en && (i_rd|i_wr) ) // MMU enabled. - begin - if ( (i_sptlb_rdata[`SPAGE_TLB__TAG] == i_va[`VA__SPAGE_TAG]) && i_sptlb_rdav ) - begin - // Entry found in small page TLB. - o_fsr = get_fsr - ( - 1'd0, 1'd1, 1'd0, // Small page. - i_va[`VA__SPAGE_AP_SEL], - i_cpsr[4:0] == USR, - i_rd, - i_wr, - i_sr, - i_dac_reg, - i_sptlb_rdata - ) ; - - o_phy_addr = {i_sptlb_rdata[`SPAGE_TLB__BASE], - i_va[11:0]}; - - o_cacheable = i_sptlb_rdata[`SECTION_TLB__CB] >> 1; - - end - else if ( (i_lptlb_rdata[`LPAGE_TLB__TAG] == i_va[`VA__LPAGE_TAG]) && i_lptlb_rdav ) - begin - // Entry found in large page TLB. - o_fsr = get_fsr - ( - 1'd0, 1'd0, 1'd1, // Large page. - i_va[`VA__LPAGE_AP_SEL], - i_cpsr[4:0] == USR, - i_rd, - i_wr, - i_sr, - i_dac_reg, - i_lptlb_rdata - ) ; - - o_phy_addr = {i_lptlb_rdata[`LPAGE_TLB__BASE], - i_va[15:0]}; - - o_cacheable = i_lptlb_rdata[`LPAGE_TLB__CB] >> 1; - end - else if ( (i_setlb_rdata[`SECTION_TLB__TAG] == i_va[`VA__SECTION_TAG]) && i_setlb_rdav ) - begin - // Entry found in section TLB. - o_fsr = get_fsr - ( - 1'd1, 1'd0, 1'd0, // Section. - 2'd0, // DONT CARE. Sections do not further divisions in AP SEL. - i_cpsr[4:0] == USR, - i_rd, - i_wr, - i_sr, - i_dac_reg, - i_setlb_rdata - ) ; - - o_phy_addr = {i_setlb_rdata[`SECTION_TLB__BASE], - i_va[19:0]}; - - o_cacheable = i_setlb_rdata[`SECTION_TLB__CB] >> 1; - end - else - begin - // Trigger TLB walk. - o_walk = 1'd1; - end - end // Else MMU disabled. -end - -// ---------------------------------------------------------------------------- - -function [7:0] get_fsr ( // Return 0 means OK to access else is a valid FSR. -input section, spage, lpage, // Select one. -input [1:0] ap_sel, // AP sel bits. dont care for sections. -input user, rd, wr, // Access properties. -input [1:0] sr, // S and R bits. -input [31:0] dac_reg, // DAC register. -input [63:0] tlb // TLB entry. -); - -reg [3:0] apsr; // Concat of AP and SR. -reg [1:0] dac; // DAC bits. - -begin - if ( section ) - begin - apsr = (tlb [ `SECTION_TLB__AP ]) >> (section ? 0 : (ap_sel << 1)); - dac = (dac_reg >> (tlb [ `SECTION_TLB__DAC_SEL ] << 1)); - end - else if ( spage ) - begin - apsr = (tlb [ `SPAGE_TLB__AP ]) >> (section ? 0 : (ap_sel << 1)); - dac = (dac_reg >> (tlb [ `SPAGE_TLB__DAC_SEL ] << 1)); - end - else // large page. - begin - apsr = (tlb [ `LPAGE_TLB__AP ]) >> (section ? 0 : (ap_sel << 1)); - dac = (dac_reg >> (tlb [ `LPAGE_TLB__DAC_SEL ] << 1)); - end - - case(dac) - DAC_MANAGER: get_fsr = 0; // No fault. - - DAC_CLIENT : get_fsr = is_apsr_ok ( user, rd, wr, apsr ) ? 0 : - ( - section ? {tlb[`SECTION_TLB__DAC_SEL], FSR_SECTION_PERMISSION_FAULT}: - spage ? {tlb[`SPAGE_TLB__DAC_SEL] , FSR_PAGE_PERMISSION_FAULT }: - {tlb[`LPAGE_TLB__DAC_SEL] , FSR_PAGE_PERMISSION_FAULT } - ); - - default : get_fsr = - section ? {tlb[`SECTION_TLB__DAC_SEL], FSR_SECTION_DOMAIN_FAULT} : - spage ? {tlb[`SPAGE_TLB__DAC_SEL], FSR_PAGE_DOMAIN_FAULT } : - {tlb[`LPAGE_TLB__DAC_SEL], FSR_PAGE_DOMAIN_FAULT } ; - endcase -end - -endfunction - -// ---------------------------------------------------------------------------- - -// -// Function to check APSR bits. -// -// Returns 0 for failure, 1 for okay. -// Checks AP and SR bits. -// - -localparam APSR_BAD = 1'd0; -localparam APSR_OK = 1'd1; - -function is_apsr_ok ( input user, input rd, input wr, input [3:0] apsr); -reg x; -begin - x = APSR_BAD; // Assume fail. - - casez (apsr) - APSR_NA_NA: x = APSR_BAD; // No access. - APSR_RO_RO: x = !wr; // Reads allowed for all. - APSR_RO_NA: x = !user && rd; // Only kernel reads. - APSR_RW_NA: x = !user; // Only kernel access. - APSR_RW_RO: x = !user | (user && rd); // User RO, Kernel RW. - APSR_RW_RW: x = APSR_OK; // Grant all the time. - default : x = APSR_BAD; // Deny all the time. - endcase - - // Assign to function. Return. - is_apsr_ok = x; -end -endfunction - -endmodule // zap_tlb_check.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_fifo.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_fifo.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_fifo.v (nonexistent) @@ -1,109 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_fifo #(parameter WDT = 32, DEPTH = 8) ( - -input wire i_clk, -input wire i_reset, - -input wire i_write_inhibit, - -input wire i_clear_from_writeback, -input wire i_data_stall, -input wire i_clear_from_alu, -input wire i_stall_from_shifter, -input wire i_stall_from_issue, -input wire i_stall_from_decode, -input wire i_clear_from_decode, - -input wire [WDT-1:0] i_instr, // Instruction + other bits. -input wire i_valid, // Above is valid. Write enable basically. - -output reg [WDT-1:0] o_instr, // Instruction output. -output reg o_valid, // Output valid. - -output wire o_wb_stb, o_wb_cyc, o_wb_stb_nxt // Wishbone request. -); - -reg clear, rd_en; -wire [WDT-1:0] instr; -wire valid; - -assign o_wb_cyc = o_wb_stb; - -always @* -begin - if ( i_clear_from_writeback) clear = 1'd1; - else if ( i_data_stall ) clear = 1'd0; - else if ( i_clear_from_alu ) clear = 1'd1; - else if ( i_stall_from_shifter ) clear = 1'd0; - else if ( i_stall_from_issue ) clear = 1'd0; - else if ( i_stall_from_decode ) clear = 1'd0; - else if ( i_clear_from_decode ) clear = 1'd1; - else clear = 1'd0; -end - -always @* -begin - if ( i_clear_from_writeback) rd_en = 1'd0; - else if ( i_data_stall ) rd_en = 1'd0; - else if ( i_clear_from_alu ) rd_en = 1'd0; - else if ( i_stall_from_shifter ) rd_en = 1'd0; - else if ( i_stall_from_issue ) rd_en = 1'd0; - else if ( i_stall_from_decode ) rd_en = 1'd0; - else if ( i_clear_from_decode ) rd_en = 1'd0; - else rd_en = 1'd1; -end - -zap_sync_fifo #(.WIDTH(WDT), .DEPTH(DEPTH), .FWFT(1)) USF ( - .i_clk (i_clk), - .i_reset (i_reset || clear), - .i_ack ( rd_en ), - .i_wr_en ( i_valid && !i_write_inhibit ), - .i_data (i_instr), - .o_data (instr), - .o_empty_n (valid), - .o_full_n (o_wb_stb), - .o_full_n_nxt (o_wb_stb_nxt), - .o_empty (), - .o_full () -); - -// Pipeline register. -always @ (posedge i_clk) -begin - if ( i_reset || clear ) - begin - o_valid <= 1'd0; - end - else if ( rd_en ) - begin - o_valid <= valid; - o_instr <= instr; - end -end - -endmodule -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_register_file.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_register_file.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_register_file.v (nonexistent) @@ -1,150 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- ZAP register file implemented using flip-flops which makes sense for an-- -// -- FPGA implementation where flip-flops are plentiful. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_register_file -( - input wire i_clk, - - input wire i_reset, - - input wire i_wen, - - input wire [5:0] i_wr_addr_a, - i_wr_addr_b, // 2 write addresses. - - input wire [31:0] i_wr_data_a, - i_wr_data_b, // 2 write data. - - input wire [5:0] i_rd_addr_a, - i_rd_addr_b, - i_rd_addr_c, - i_rd_addr_d, - - output reg [31:0] o_rd_data_a, - o_rd_data_b, - o_rd_data_c, - o_rd_data_d -); - -// Dual distributed RAM setup. -reg [31:0] mem [39:0]; -reg [31:0] MEM [39:0]; - -initial -begin: blk1 - integer i; - - for(i=0;i<40;i=i+1) - begin - mem[i] = 0; - MEM[i] = 0; - end -end - -reg [39:0] sel; - -wire [31:0] r0; assign r0 = sel[0] ? MEM[0] : mem[0]; -wire [31:0] r1; assign r1 = sel[1] ? MEM[1] : mem[1]; -wire [31:0] r2; assign r2 = sel[2] ? MEM[2] : mem[2]; -wire [31:0] r3; assign r3 = sel[3] ? MEM[3] : mem[3]; -wire [31:0] r4; assign r4 = sel[4] ? MEM[4] : mem[4]; -wire [31:0] r5; assign r5 = sel[5] ? MEM[5] : mem[5]; -wire [31:0] r6; assign r6 = sel[6] ? MEM[6] : mem[6]; -wire [31:0] r7; assign r7 = sel[7] ? MEM[7] : mem[7]; -wire [31:0] r8; assign r8 = sel[8] ? MEM[8] : mem[8]; -wire [31:0] r9; assign r9 = sel[9] ? MEM[9] : mem[9]; -wire [31:0] r10; assign r10 = sel[10] ? MEM[10] : mem[10]; -wire [31:0] r11; assign r11 = sel[11] ? MEM[11] : mem[11]; -wire [31:0] r12; assign r12 = sel[12] ? MEM[12] : mem[12]; -wire [31:0] r13; assign r13 = sel[13] ? MEM[13] : mem[13]; -wire [31:0] r14; assign r14 = sel[14] ? MEM[14] : mem[14]; -wire [31:0] r15; assign r15 = sel[15] ? MEM[15] : mem[15]; -wire [31:0] r16; assign r16 = sel[16] ? MEM[16] : mem[16]; -wire [31:0] r17; assign r17 = sel[17] ? MEM[17] : mem[17]; -wire [31:0] r18; assign r18 = sel[18] ? MEM[18] : mem[18]; -wire [31:0] r19; assign r19 = sel[19] ? MEM[19] : mem[19]; -wire [31:0] r20; assign r20 = sel[20] ? MEM[20] : mem[20]; -wire [31:0] r21; assign r21 = sel[21] ? MEM[21] : mem[21]; -wire [31:0] r22; assign r22 = sel[22] ? MEM[22] : mem[22]; -wire [31:0] r23; assign r23 = sel[23] ? MEM[23] : mem[23]; -wire [31:0] r24; assign r24 = sel[24] ? MEM[24] : mem[24]; -wire [31:0] r25; assign r25 = sel[25] ? MEM[25] : mem[25]; -wire [31:0] r26; assign r26 = sel[26] ? MEM[26] : mem[26]; -wire [31:0] r27; assign r27 = sel[27] ? MEM[27] : mem[27]; -wire [31:0] r28; assign r28 = sel[28] ? MEM[28] : mem[28]; -wire [31:0] r29; assign r29 = sel[29] ? MEM[29] : mem[29]; -wire [31:0] r30; assign r30 = sel[30] ? MEM[30] : mem[30]; -wire [31:0] r31; assign r31 = sel[31] ? MEM[31] : mem[31]; -wire [31:0] r32; assign r32 = sel[32] ? MEM[32] : mem[32]; -wire [31:0] r33; assign r33 = sel[33] ? MEM[33] : mem[33]; -wire [31:0] r34; assign r34 = sel[34] ? MEM[34] : mem[34]; -wire [31:0] r35; assign r35 = sel[35] ? MEM[35] : mem[35]; -wire [31:0] r36; assign r36 = sel[36] ? MEM[36] : mem[36]; -wire [31:0] r37; assign r37 = sel[37] ? MEM[37] : mem[37]; -wire [31:0] r38; assign r38 = sel[38] ? MEM[38] : mem[38]; -wire [31:0] r39; assign r39 = sel[39] ? MEM[39] : mem[39]; - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - sel <= 40'd0; - end - else - begin - sel [ i_wr_addr_a ] <= 1'd0; - sel [ i_wr_addr_b ] <= 1'd1; - end -end - -always @ (posedge i_clk) -begin - if ( i_wen ) - begin - mem [ i_wr_addr_a ] <= i_wr_data_a; - MEM [ i_wr_addr_b ] <= i_wr_data_b; - end -end - -always @* -begin - o_rd_data_a = sel[i_rd_addr_a] ? MEM [ i_rd_addr_a ] : mem [ i_rd_addr_a ]; - o_rd_data_b = sel[i_rd_addr_b] ? MEM [ i_rd_addr_b ] : mem [ i_rd_addr_b ]; - o_rd_data_c = sel[i_rd_addr_c] ? MEM [ i_rd_addr_c ] : mem [ i_rd_addr_c ]; - o_rd_data_d = sel[i_rd_addr_d] ? MEM [ i_rd_addr_d ] : mem [ i_rd_addr_d ]; -end - -endmodule // bram_wrapper.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_defines.vh =================================================================== --- zap/trunk/src/rtl/cpu/zap_defines.vh (revision 57) +++ zap/trunk/src/rtl/cpu/zap_defines.vh (nonexistent) @@ -1,133 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`ifndef _ZAP_DEFINES_VH_ -`define _ZAP_DEFINES_VH_ - -`define CPSR_MODE 4:0 - -`define BASE_EXTEND 33 // Base address register for MEMOPS. -`define BASE 19:16 // Base address extend. - -`define SRCDEST_EXTEND 32 // Data Src/Dest extend register for MEMOPS. -`define SRCDEST 15:12 // Data src/dest register MEMOPS. - -`define DP_RD_EXTEND 33 // Destination source extend. -`define DP_RD 15:12 // Destination source. - -`define DP_RB_EXTEND 32 // Shift source extend. -`define DP_RB 3:0 // Shift source. ARM refers to this as rm. - -`define DP_RA 19:16 // ALU source. ARM rn. -`define DP_RA_EXTEND 34 // ALU source extend. ARM rn. - -`define OPCODE_EXTEND 35 // To differentiate lower and higher -> - // 1 means higher, 0 lower. - -// Instruction fields in CP15 instruction. -`define opcode_2 7:5 -`define crm 3:0 -`define crn 19:16 -`define cp_id 11:8 - -// ---------------------------------------------------------------------------- - -// Generic defines. -`define ID 1:0 // Determine type of descriptor. - -// Virtual Address Breakup -`define VA__TABLE_INDEX 31:20 -`define VA__L2_TABLE_INDEX 19:12 -`define VA__4K_PAGE_INDEX 11:0 -`define VA__64K_PAGE_INDEX 15:0 -`define VA__1M_SECTION_INDEX 19:0 - -`define VA__TRANSLATION_BASE 31:14 - -`define VA__CACHE_INDEX 4+$clog2(CACHE_SIZE/16)-1:4 -`define VA__SECTION_INDEX 20+$clog2(SECTION_TLB_ENTRIES)-1:20 -`define VA__LPAGE_INDEX 16+$clog2(LPAGE_TLB_ENTRIES)-1:16 -`define VA__SPAGE_INDEX 12+$clog2(SPAGE_TLB_ENTRIES)-1:12 - -`define VA__CACHE_TAG 31:4+$clog2(CACHE_SIZE/16) - -`define VA__SPAGE_TAG 31:12+$clog2(SPAGE_TLB_ENTRIES) -`define VA__LPAGE_TAG 31:16+$clog2(LPAGE_TLB_ENTRIES) -`define VA__SECTION_TAG 31:20+$clog2(SECTION_TLB_ENTRIES) - -`define VA__SPAGE_AP_SEL 11:10 -`define VA__LPAGE_AP_SEL 15:14 - -// L1 Section Descriptior Breakup -`define L1_SECTION__BASE 31:20 -`define L1_SECTION__DAC_SEL 8:5 -`define L1_SECTION__AP 11:10 -`define L1_SECTION__CB 3:2 - -// L1 Page Descriptor Breakup -`define L1_PAGE__PTBR 31:10 -`define L1_PAGE__DAC_SEL 8:5 - -// L2 Page Descriptor Breakup -`define L2_SPAGE__BASE 31:12 -`define L2_SPAGE__AP 11:4 -`define L2_SPAGE__CB 3:2 - -`define L2_LPAGE__BASE 31:16 -`define L2_LPAGE__AP 11:4 -`define L2_LPAGE__CB 3:2 - -// Section TLB Structure - 1:0 is undefined. -`define SECTION_TLB__BASE 31:20 -`define SECTION_TLB__DAC_SEL 8:5 -`define SECTION_TLB__AP 11:10 -`define SECTION_TLB__CB 3:2 -`define SECTION_TLB__TAG 32+(32-$clog2(SECTION_TLB_ENTRIES)-20)-1:32 - -// Lpage TLB Structure - 1:0 is undefined -`define LPAGE_TLB__BASE 31:16 -`define LPAGE_TLB__DAC_SEL 15:12 // Squeezed in blank space. -`define LPAGE_TLB__AP 11:4 -`define LPAGE_TLB__CB 3:2 -`define LPAGE_TLB__TAG 32+(32-$clog2(LPAGE_TLB_ENTRIES)-16)-1:32 - -// Spage TLB Structure - 1:0 is undefined -`define SPAGE_TLB__BASE 31:12 -`define SPAGE_TLB__AP 11:4 -`define SPAGE_TLB__CB 3:2 -`define SPAGE_TLB__DAC_SEL 35:32 -`define SPAGE_TLB__TAG 36+(32-$clog2(SPAGE_TLB_ENTRIES)-12)-1:36 - -// Cache tag width. Tag consists of the tag and the physical address. valid and dirty are stored as flops. -`define CACHE_TAG__TAG (31 - 4 - $clog2(CACHE_SIZE/16) + 1) -1 : 0 -`define CACHE_TAG__PA 27 + (31 - 4 - $clog2(CACHE_SIZE/16) + 1) : 31 - 4 - $clog2(CACHE_SIZE/16) + 1 -`define CACHE_TAG_WDT 27 + (31 - 4 - $clog2(CACHE_SIZE/16) + 1) + 1 - -// TLB widths. -`define SECTION_TLB_WDT (32 + (32-$clog2(SECTION_TLB_ENTRIES)-20)) -`define LPAGE_TLB_WDT (32 + (32-$clog2(LPAGE_TLB_ENTRIES)-16)) -`define SPAGE_TLB_WDT (36 + (32-$clog2(SPAGE_TLB_ENTRIES)-12)) - -// ---------------------------------------------------------------------------- - -`endif Index: zap/trunk/src/rtl/cpu/zap_tlb_fsm.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_tlb_fsm.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_tlb_fsm.v (nonexistent) @@ -1,418 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- An automatic page fetching system. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -`include "zap_defines.vh" - -module zap_tlb_fsm #( - -// Pass from top. -parameter LPAGE_TLB_ENTRIES = 8, -parameter SPAGE_TLB_ENTRIES = 8, -parameter SECTION_TLB_ENTRIES = 8 - -)( - -/* Clock and Reset */ -input wire i_clk, -input wire i_reset, - -/* From CP15 */ -input wire i_mmu_en, -input wire [31:0] i_baddr, - -/* From cache FSM */ -input wire [31:0] i_address, - -/* From TLB check unit */ -input wire i_walk, -input wire [7:0] i_fsr, -input wire [31:0] i_far, -input wire i_cacheable, -input wire [31:0] i_phy_addr, - -/* To main cache FSM */ -output reg [7:0] o_fsr, -output reg [31:0] o_far, -output reg o_fault, -output reg [31:0] o_phy_addr, -output reg o_cacheable, -output reg o_busy, - -/* To TLBs */ -output reg [`SECTION_TLB_WDT-1:0] o_setlb_wdata, -output reg o_setlb_wen, -output reg [`SPAGE_TLB_WDT-1:0] o_sptlb_wdata, -output reg o_sptlb_wen, -output reg [`LPAGE_TLB_WDT-1:0] o_lptlb_wdata, -output reg o_lptlb_wen, - -/* Wishbone signals NXT */ -output wire o_wb_cyc_nxt, -output wire o_wb_stb_nxt, -output wire [31:0] o_wb_adr_nxt, - -/* Wishbone Signals */ -output wire o_wb_cyc, -output wire o_wb_stb, -output wire o_wb_wen, -output wire [3:0] o_wb_sel, o_wb_sel_nxt, -output wire [31:0] o_wb_adr, -input wire [31:0] i_wb_dat, -input wire i_wb_ack, - -// Unused. -output wire o_unused_ok - -); - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -// ---------------------------------------------------------------------------- - -/* States */ -localparam IDLE = 0; /* Idle State */ -localparam FETCH_L1_DESC = 1; /* Fetch L1 descriptor */ -localparam FETCH_L2_DESC = 2; /* Fetch L2 descriptor */ -localparam REFRESH_CYCLE = 3; /* Refresh TLBs and cache */ -localparam FETCH_L1_DESC_0 = 4; -localparam FETCH_L2_DESC_0 = 5; -localparam NUMBER_OF_STATES = 6; - -// ---------------------------------------------------------------------------- - -reg [3:0] dac_ff, dac_nxt; /* Scratchpad register */ -reg [$clog2(NUMBER_OF_STATES)-1:0] state_ff, state_nxt; /* State register */ - -/* Wishbone related */ -reg wb_stb_nxt, wb_stb_ff; -reg wb_cyc_nxt, wb_cyc_ff; -reg [31:0] wb_adr_nxt, wb_adr_ff; - -// ---------------------------------------------------------------------------- - -/* Tie output flops to ports. */ -assign o_wb_cyc = wb_cyc_ff; -assign o_wb_stb = wb_stb_ff; -assign o_wb_adr = wb_adr_ff; - -assign o_wb_cyc_nxt = wb_cyc_nxt; -assign o_wb_stb_nxt = wb_stb_nxt; -assign o_wb_adr_nxt = wb_adr_nxt; - -reg [3:0] wb_sel_nxt, wb_sel_ff; - -/* Tied PORTS */ -assign o_wb_wen = 1'd0; -assign o_wb_sel = wb_sel_ff; -assign o_wb_sel_nxt = wb_sel_nxt; - -assign o_unused_ok = 0 || i_baddr[13:0]; - -reg [31:0] dff, dnxt; /* Wishbone memory buffer. */ - -/* Combinational logic */ -always @* -begin: blk1 - - o_fsr = 0; - o_far = 0; - o_fault = 0; - o_busy = 0; - o_phy_addr = i_phy_addr; - o_cacheable = i_cacheable; - o_setlb_wen = 0; - o_lptlb_wen = 0; - o_sptlb_wen = 0; - o_setlb_wdata = 0; - o_sptlb_wdata = 0; - o_lptlb_wdata = 0; - - /* Kill wishbone access unless overridden */ - wb_stb_nxt = 0; - wb_cyc_nxt = 0; - wb_adr_nxt = 0; - wb_sel_nxt = 0; - - dac_nxt = dac_ff; - state_nxt = state_ff; - - dnxt = dff; - - case ( state_ff ) - IDLE: - begin - if ( i_mmu_en ) - begin - if ( i_walk ) - begin - o_busy = 1'd1; - - /* - * We need to page walk to get the page table. - * Call for access to L1 level page table. - */ - tsk_prpr_wb_rd({i_baddr[`VA__TRANSLATION_BASE], - i_address[`VA__TABLE_INDEX], 2'd0}); - - state_nxt = FETCH_L1_DESC_0; - end - else if ( i_fsr[3:0] != 4'b0000 ) /* Access Violation. */ - begin - o_fault = 1'd1; - o_busy = 1'd0; - o_fsr = i_fsr; - o_far = i_far; - end - end - end - - FETCH_L1_DESC_0: - begin - o_busy = 1; - - if ( i_wb_ack ) - begin - dnxt = i_wb_dat; - state_nxt = FETCH_L1_DESC; - end - else tsk_hold_wb_access; - end - - FETCH_L1_DESC: - begin - /* - * What we would have fetched is the L1 descriptor. - * Examine it. dff holds the L1 descriptor. - */ - - o_busy = 1'd1; - - if ( 1 ) - begin - case ( dff[`ID] ) - - SECTION_ID: - begin - /* - * It is a section itself so there is no need - * for another fetch. Simply reload the TLB - * and we are good. - */ - o_setlb_wen = 1'd1; - o_setlb_wdata = {i_address[`VA__SECTION_TAG], - dff}; - state_nxt = REFRESH_CYCLE; - - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: SECTION DESCRIPTOR DETAILS #"); - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: # BASE ADDRESS = 0x%x ", o_setlb_wdata[`SECTION_TLB__BASE]); - $display($time, " - %m :: # DAC = 0b%b", o_setlb_wdata[`SECTION_TLB__DAC_SEL]); - $display($time, " - %m :: # AP bits = 0b%b", o_setlb_wdata[`SECTION_TLB__AP]); - $display($time, " - %m :: # Cacheable = 0b%b", o_setlb_wdata[`SECTION_TLB__CB] >> 1); - $display($time, " - %m :: # Bufferable = 0b%b", o_setlb_wdata[`SECTION_TLB__CB] & 2'b01); - $display($time, " - %m :: #########################################################"); - end - - PAGE_ID: - begin - /* - * Page ID requires that DAC from current - * descriptor is remembered because when we - * reload the TLB, it would be useful. Anyway, - * we need to initiate another access. - */ - dac_nxt = dff[`L1_PAGE__DAC_SEL]; // dac register holds the dac sel for future use. - state_nxt = FETCH_L2_DESC_0; - - tsk_prpr_wb_rd({dff[`L1_PAGE__PTBR], - i_address[`VA__L2_TABLE_INDEX], 2'd0}); - end - - default: /* Generate section translation fault. Fault Class II */ - begin - o_fsr = FSR_SECTION_TRANSLATION_FAULT; - o_fsr = {dff[`L1_SECTION__DAC_SEL], o_fsr[3:0]}; - o_far = i_address; - o_fault = 1'd1; - o_busy = 1'd0; - state_nxt = IDLE; - end - - endcase - end - else tsk_hold_wb_access; - end - - FETCH_L2_DESC_0: - begin - o_busy = 1; - - if ( i_wb_ack ) - begin - dnxt = i_wb_dat; - state_nxt = FETCH_L2_DESC; - end - else - begin - tsk_hold_wb_access; - end - end - - FETCH_L2_DESC: - begin - o_busy = 1'd1; - - if ( 1 ) - begin - case ( dff[`ID] ) // dff holds L2 descriptor. dac_ff holds L1 descriptor DAC. - SPAGE_ID: - begin - /* Update TLB */ - o_sptlb_wen = 1'd1; - - /* Define TLB fields to write */ - o_sptlb_wdata[`SPAGE_TLB__TAG] = i_address[`VA__SPAGE_TAG]; - o_sptlb_wdata[`SPAGE_TLB__DAC_SEL] = dac_ff; /* DAC selector from L1. */ - o_sptlb_wdata[`SPAGE_TLB__AP] = dff[`L2_SPAGE__AP]; - o_sptlb_wdata[`SPAGE_TLB__CB] = dff[`L2_SPAGE__CB]; - o_sptlb_wdata[`SPAGE_TLB__BASE] = dff[`L2_SPAGE__BASE]; - - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: SPAGE DESCRIPTOR DETAILS #"); - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: # BASE ADDRESS = 0x%x ", o_sptlb_wdata[`SPAGE_TLB__BASE]); - $display($time, " - %m :: # DAC = 0b%b", o_sptlb_wdata[`SPAGE_TLB__DAC_SEL]); - $display($time, " - %m :: # AP bits = 0b%b", o_sptlb_wdata[`SPAGE_TLB__AP]); - $display($time, " - %m :: # Cacheable = 0b%b", o_sptlb_wdata[`SPAGE_TLB__CB] >> 1); - $display($time, " - %m :: # Bufferable = 0b%b", o_sptlb_wdata[`SPAGE_TLB__CB] & 2'b01); - $display($time, " - %m :: #########################################################"); - - /* Go to REFRESH */ - state_nxt = REFRESH_CYCLE; - end - - LPAGE_ID: - begin - /* Update TLB */ - o_lptlb_wen = 1'd1; - - /* DAC is inserted in between to save bits */ - o_lptlb_wdata = {i_address[`VA__LPAGE_TAG], dac_ff, dff}; - - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: LPAGE DESCRIPTOR DETAILS #"); - $display($time, " - %m :: #########################################################"); - $display($time, " - %m :: # BASE ADDRESS = 0x%x ", o_lptlb_wdata[`LPAGE_TLB__BASE]); - $display($time, " - %m :: # DAC = 0b%b", o_lptlb_wdata[`LPAGE_TLB__DAC_SEL]); - $display($time, " - %m :: # AP bits = 0b%b", o_lptlb_wdata[`LPAGE_TLB__AP]); - $display($time, " - %m :: # Cacheable = 0b%b", o_lptlb_wdata[`LPAGE_TLB__CB] >> 1); - $display($time, " - %m :: # Bufferable = 0b%b", o_lptlb_wdata[`LPAGE_TLB__CB] & 2'b01); - $display($time, " - %m :: #########################################################"); - - state_nxt = REFRESH_CYCLE; - end - - default: /* Fault Class II */ - begin - o_busy = 1'd0; - o_fault = 1'd1; - o_fsr = FSR_PAGE_TRANSLATION_FAULT; - o_fsr = {1'd0, dac_ff, o_fsr[3:0]}; - o_far = i_address; - state_nxt = IDLE; - end - endcase - end - else tsk_hold_wb_access; - end - - REFRESH_CYCLE: - begin - o_busy = 1'd1; - state_nxt = IDLE; - end - - endcase -end - -// ---------------------------------------------------------------------------- - -// Clocked Logic. -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - state_ff <= IDLE; - wb_stb_ff <= 0; - wb_cyc_ff <= 0; - wb_adr_ff <= 0; - wb_sel_ff <= 0; - end - else - begin - state_ff <= state_nxt; - wb_stb_ff <= wb_stb_nxt; - wb_cyc_ff <= wb_cyc_nxt; - wb_adr_ff <= wb_adr_nxt; - dac_ff <= dac_nxt; - wb_sel_ff <= wb_sel_nxt; - dff <= dnxt; - end -end - -// ---------------------------------------------------------------------------- - -task tsk_hold_wb_access; -begin - wb_stb_nxt = wb_stb_ff; - wb_cyc_nxt = wb_cyc_ff; - wb_adr_nxt = wb_adr_ff; - wb_sel_nxt = wb_sel_ff; -end -endtask - -task tsk_prpr_wb_rd ( input [31:0] adr ); -begin - wb_stb_nxt = 1'd1; - wb_cyc_nxt = 1'd1; - wb_adr_nxt = adr; - wb_sel_nxt[3:0] = 4'b1111; -end -endtask - -endmodule // zap_tlb_fsm.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// END OF FILE -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_predecode_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_predecode_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_predecode_main.v (nonexistent) @@ -1,359 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- The pre-decode block. Does partial instruction decoding and sequencing -- -// -- before passing the instruction onto the next stage. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none -module zap_predecode_main #( - // - // For several reasons, we need more architectural registers than - // what ARM specifies. We also need more physical registers. - // - parameter ARCH_REGS = 32, - - // - // Although ARM mentions only 16 ALU operations, the processor - // internally performs many more operations. - // - parameter ALU_OPS = 32, - - // - // Apart from the 4 specified by ARM, an undocumented RORI is present - // to help deal with immediate rotates. - // - parameter SHIFT_OPS = 5, - - // Number of physical registers. - parameter PHY_REGS = 46, - - // Coprocessor IF enable. - parameter COPROCESSOR_INTERFACE_ENABLE = 1, - - // Compressed ISA support. - parameter COMPRESSED_EN = 1 -) -/////////////////////////////////////////////////////////////////////////////// -( - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // Branch state. - input wire [1:0] i_taken, - input wire i_force32, - input wire i_und, - - // Clear and stall signals. From high to low priority. - input wire i_clear_from_writeback, // |Pri - input wire i_data_stall, // | - input wire i_clear_from_alu, // | - input wire i_stall_from_shifter, // | - input wire i_stall_from_issue, // V - - // Interrupt events. - input wire i_irq, - input wire i_fiq, - input wire i_abt, - - // Is 0 if all pipeline is invalid. Used for coprocessor. - input wire i_pipeline_dav, - - // Coprocessor done. - input wire i_copro_done, - - // PC input. - input wire [31:0] i_pc_ff, - input wire [31:0] i_pc_plus_8_ff, - - // CPU mode. Taken from CPSR in the ALU. - input wire i_cpu_mode_t, // T mode. - input wire [4:0] i_cpu_mode_mode, // CPU mode. - - // Instruction input. - input wire [34:0] i_instruction, - input wire i_instruction_valid, - - // Instruction output - output reg [35:0] o_instruction_ff, - output reg o_instruction_valid_ff, - - // Stall of PC and fetch. - output reg o_stall_from_decode, - - // PC output. - output reg [31:0] o_pc_plus_8_ff, - output reg [31:0] o_pc_ff, - - // Interrupts. - output reg o_irq_ff, - output reg o_fiq_ff, - output reg o_abt_ff, - output reg o_und_ff, - - // Force 32-bit alignment on memory accesses. - output reg o_force32align_ff, - - // Coprocessor interface. - output wire o_copro_dav_ff, - output wire [31:0] o_copro_word_ff, - - // Branch. - output reg [1:0] o_taken_ff, - - // Clear from decode. - output reg o_clear_from_decode, - output reg [31:0] o_pc_from_decode -); - - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -// Branch states. -localparam SNT = 0; // Strongly Not Taken. -localparam WNT = 1; // Weakly Not Taken. -localparam WT = 2; // Weakly Taken. -localparam ST = 3; // Strongly Taken. - -/////////////////////////////////////////////////////////////////////////////// - -wire [35:0] o_instruction_nxt; -wire o_instruction_valid_nxt; - -wire mem_fetch_stall; - -wire arm_irq; -wire arm_fiq; - -wire [34:0] arm_instruction; -wire arm_instruction_valid; - -wire cp_stall; -wire [34:0] cp_instruction; -wire cp_instruction_valid; -wire cp_irq; -wire cp_fiq; - -wire o_irq_nxt; -wire o_fiq_nxt; - -reg [1:0] taken_nxt; - -/////////////////////////////////////////////////////////////////////////////// - -// Flop the outputs to break the pipeline at this point. -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - clear; - end - else if ( i_clear_from_writeback ) - begin - clear; - end - else if ( i_data_stall ) - begin - // Preserve state. - end - else if ( i_clear_from_alu ) - begin - clear; - end - else if ( i_stall_from_shifter ) - begin - // Preserve state. - end - else if ( i_stall_from_issue ) - begin - // Preserve state. - end - // If no stall, only then update... - else - begin - // Do not pass IRQ and FIQ if mask is 1. - o_irq_ff <= i_irq; - o_fiq_ff <= i_fiq; - o_abt_ff <= i_abt; - o_und_ff <= i_und && i_instruction_valid; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_pc_ff <= i_pc_ff; - o_force32align_ff <= i_force32; - o_taken_ff <= taken_nxt; - o_instruction_ff <= o_instruction_nxt; - o_instruction_valid_ff <= o_instruction_valid_nxt; - end -end - -task clear; -begin - o_irq_ff <= 0; - o_fiq_ff <= 0; - o_abt_ff <= 0; - o_und_ff <= 0; - o_taken_ff <= 0; - o_instruction_valid_ff <= 0; -end -endtask - -always @* -begin - o_stall_from_decode = mem_fetch_stall || cp_stall; -end - -/////////////////////////////////////////////////////////////////////////////// - -// This unit handles coprocessor stuff. -zap_predecode_coproc -#( - .PHY_REGS(PHY_REGS) -) -u_zap_decode_coproc -( - // Inputs from outside world. - .i_clk(i_clk), - .i_reset(i_reset), - .i_irq(i_irq), - .i_fiq(i_fiq), - .i_instruction(i_instruction_valid ? i_instruction : 32'd0), - .i_valid(i_instruction_valid), - .i_cpsr_ff_t(i_cpu_mode_t), - .i_cpsr_ff_mode(i_cpu_mode_mode), - - // Clear and stall signals. - .i_clear_from_writeback(i_clear_from_writeback), - .i_data_stall(i_data_stall), - .i_clear_from_alu(i_clear_from_alu), - .i_stall_from_issue(i_stall_from_issue), - .i_stall_from_shifter(i_stall_from_shifter), - - // Valid signals. - .i_pipeline_dav (i_pipeline_dav), - - // Coprocessor - .i_copro_done(i_copro_done), - - // Output to next block. - .o_instruction(cp_instruction), - .o_valid(cp_instruction_valid), - .o_irq(cp_irq), - .o_fiq(cp_fiq), - - // Stall. - .o_stall_from_decode(cp_stall), - - // Coprocessor interface. - .o_copro_dav_ff(o_copro_dav_ff), - .o_copro_word_ff(o_copro_word_ff) -); - - - -/////////////////////////////////////////////////////////////////////////////// - - assign arm_instruction = cp_instruction; - assign arm_instruction_valid = cp_instruction_valid; - assign arm_irq = cp_irq; - assign arm_fiq = cp_fiq; - -/////////////////////////////////////////////////////////////////////////////// - -always @* -begin:bprblk1 - reg [31:0] addr; - reg [31:0] addr_final; - - o_clear_from_decode = 1'd0; - o_pc_from_decode = 32'd0; - taken_nxt = i_taken; - addr = $signed(arm_instruction[23:0]); - - if ( arm_instruction[34] ) // Indicates a shift of 1. - addr_final = addr << 1; - else - addr_final = addr << 2; - - // - // Perform actions as mentioned by the predictor unit in the fetch - // stage. - // - if ( arm_instruction[27:25] == 3'b101 && arm_instruction_valid ) - begin - if ( i_taken[1] || arm_instruction[31:28] == AL ) - // Taken or Strongly Taken or Always taken. - begin - // Take the branch. Clear pre-fetched instruction. - o_clear_from_decode = 1'd1; - - // Predict new PC. - o_pc_from_decode = i_pc_plus_8_ff + addr_final; - - if ( arm_instruction[31:28] == AL ) - taken_nxt = ST; - end - else // Not Taken or Weakly Not Taken. - begin - // Else dont take the branch since pre-fetched - // instruction is correct. - o_clear_from_decode = 1'd0; - o_pc_from_decode = 32'd0; - end - end -end - -/////////////////////////////////////////////////////////////////////////////// - -// This FSM handles LDM/STM/SWAP/SWAPB/BL/LMULT -zap_predecode_mem_fsm u_zap_mem_fsm ( - .i_clk(i_clk), - .i_reset(i_reset), - .i_instruction(arm_instruction), - .i_instruction_valid(arm_instruction_valid), - .i_fiq(arm_fiq), - .i_irq(arm_irq), - .i_cpsr_t(i_cpu_mode_t), - - - .i_clear_from_writeback(i_clear_from_writeback), - .i_data_stall(i_data_stall), - .i_clear_from_alu(i_clear_from_alu), - .i_issue_stall(i_stall_from_issue), - .i_stall_from_shifter(i_stall_from_shifter), - - .o_irq(o_irq_nxt), - .o_fiq(o_fiq_nxt), - .o_instruction(o_instruction_nxt), - .o_instruction_valid(o_instruction_valid_nxt), - .o_stall_from_decode(mem_fetch_stall) -); - -/////////////////////////////////////////////////////////////////////////////// - -endmodule -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_decompile.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_decompile.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_decompile.v (nonexistent) @@ -1,475 +0,0 @@ -// --------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- ------------------------------------------------------------------------ -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// --------------------------------------------------------------------------- -// -- -- -// -- When running in simulation mode, this module will decompile binary -- -// -- ARM instructions to assembler instructions for debug purposes. -- -// -- When running in synthesis mode, the output of this module is tied -- -// -- to a constant since this module really finds use only in debug. -- -// -- -- -// --------------------------------------------------------------------------- - -`default_nettype none - -module zap_decompile #(parameter INS_WDT = 36) ( - input wire [36-1:0] i_instruction, // 36-bit instruction into decode. - input wire i_dav, // Instruction valid. - output reg [64*8-1:0] o_decompile // 1024 bytes max of assembler string. - ); - -`ifndef SYNTHESIS - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -`ifndef ZAP_DECOMPILE_DEFINES - `define CCC cond_code(i_instruction[31:28]) - `define CRB arch_reg_num({i_instruction[`DP_RB_EXTEND], i_instruction[`DP_RB]}) - `define CRD arch_reg_num({i_instruction[`DP_RD_EXTEND], i_instruction[`DP_RD]}) - `define CRD1 arch_reg_num({i_instruction[`SRCDEST_EXTEND], i_instruction[`SRCDEST]}) - `define CRN arch_reg_num({i_instruction[`DP_RA_EXTEND], i_instruction[`DP_RA]}) - `define CRN1 arch_reg_num({i_instruction[`BASE_EXTEND], i_instruction[`BASE]}) - `define COPCODE get_opcode({i_instruction[`OPCODE_EXTEND], i_instruction[24:21]}) - `define CSHTYPE get_shtype(i_instruction[6:5]) - `define CRS arch_reg_num(i_instruction[11:8]); - `define CRM arch_reg_num({i_instruction[`DP_RB_EXTEND], i_instruction[`DP_RB]}); -`endif - -always @* -begin - if ( !i_dav ) - begin - o_decompile = "IGNORE"; - end - else if ( i_instruction[27:24] == 4'b1110 && i_instruction[4] ) - begin - if ( i_instruction[20] ) // R <- CPSR - $sformat(o_decompile, "MRC%s", `CCC); - else - $sformat(o_decompile, "MCR%s", `CCC); - end - else if ( i_instruction[27:25] == 3'b100 ) // LDMSTM - begin - if ( i_instruction[20] ) // Load - $sformat(o_decompile, "LDM%s %b %s %b", `CCC, i_instruction[24:20], i_instruction[19:16], i_instruction[15:0]); - else - $sformat(o_decompile, "STM%s %b %s %b", `CCC, i_instruction[24:20], i_instruction[19:16], i_instruction[15:0]); - end - else - casez ( i_instruction[31:0] ) - BX_INST: decode_bx ( i_instruction ); // - MRS: decode_mrs ( i_instruction ); // - MSR_IMMEDIATE: decode_msr_immed ( i_instruction ); // - MSR: decode_msr ( i_instruction ); // - DATA_PROCESSING_IMMEDIATE: decode_dp_immed ( i_instruction ); // - DATA_PROCESSING_REGISTER_SPECIFIED_SHIFT: decode_dp_rss ( i_instruction ); // - DATA_PROCESSING_INSTRUCTION_SPECIFIED_SHIFT: decode_dp_iss ( i_instruction ); // - BRANCH_INSTRUCTION: decode_branch ( i_instruction ); // - LS_INSTRUCTION_SPECIFIED_SHIFT: decode_ls_iss ( i_instruction ); // - LS_IMMEDIATE: decode_ls ( i_instruction ); // - MULT_INST: decode_mult ( i_instruction ); // - LMULT_INST: decode_lmult ( i_instruction ); // - HALFWORD_LS: decode_halfword_ls ( i_instruction ); // - SOFTWARE_INTERRUPT: decode_swi ( i_instruction ); // - - default: - begin - o_decompile = "UNRECOGNIZED INSTRUCTION!"; - end - endcase -end - -task decode_swi ( input [INS_WDT-1:0] i_instruction ); -begin - $sformat(o_decompile, "SWIAL %0d", $unsigned(i_instruction[24:0])); -end -endtask - -task decode_branch ( input [INS_WDT-1:0] i_instruction ); -begin - if ( !i_instruction[24] ) - $sformat(o_decompile, "B%s %0d", `CCC, $signed(i_instruction[23:0])); - else - $sformat(o_decompile, "BL%s %0d", `CCC, $signed(i_instruction[23:0])); -end -endtask - -task decode_bx ( input [INS_WDT-1:0] i_instruction ); -begin - $sformat(o_decompile, "BX%s %s", `CCC, `CRB ); -end -endtask - -task decode_dp_immed ( input [INS_WDT-1:0] i_instruction ); -begin:blk111 - reg [6*8-1:0] opcode; reg [4*8-1:0] cc, dest_reg, src_reg; - integer imm_amt, ror_amt; - - opcode = `COPCODE; - cc = `CCC; - dest_reg = `CRD; - src_reg = `CRN; - imm_amt = $unsigned(i_instruction[7:0]); - ror_amt = $unsigned(i_instruction[11:8]); - - $sformat(o_decompile, "%s%s %s,%s,%0d ROR %0d", opcode, cc, dest_reg, src_reg, imm_amt, ror_amt); -end -endtask - -task decode_dp_rss ( input [INS_WDT-1:0] i_instruction ); -begin:bk222 - reg [4*8-1:0] cc, dest_reg, src_reg, sh_src_reg, shamt_reg; - reg [6*8-1:0] opcode; - reg [5*8-1:0] shtype; - integer shamt; - - opcode = `COPCODE; - cc = `CCC; - dest_reg = `CRD; - src_reg = `CRN; - shtype = `CSHTYPE; - sh_src_reg = `CRM; - shamt_reg = `CRS; - - $sformat(o_decompile, "%s%s %s,%s,%s %s %s", opcode, cc, dest_reg, src_reg, sh_src_reg, shtype, shamt_reg); -end -endtask - -task decode_dp_iss ( input [INS_WDT-1:0] i_instruction ); -begin:blk333 - reg [4*8-1:0] cc, dest_reg, src_reg, sh_src_reg; - reg [6*8-1:0] opcode; - reg [4*8-1:0] shtype; - integer shamt; - - opcode = `COPCODE; - cc = `CCC; - dest_reg = `CRD; - src_reg = `CRN; - shtype = `CSHTYPE; - sh_src_reg = `CRM; - shamt = $unsigned(i_instruction[11:7]); - - $sformat(o_decompile, "%s%s %s,%s,%s %s %0d", opcode, cc, dest_reg, src_reg, sh_src_reg, shtype, shamt); -end -endtask - -task decode_mrs ( input [INS_WDT-1:0] i_instruction ); -begin - if ( i_instruction[22] ) // SPSR - $sformat(o_decompile, "MRS%s %s,SPSR",`CCC, `CRD); - else // CPSR - $sformat(o_decompile, "MRS%s %s,CPSR",`CCC, `CRD); -end -endtask - -task decode_msr ( input [INS_WDT-1:0] i_instruction ); -begin - if ( i_instruction[22] ) // SPSR - $sformat(o_decompile, "MSR%s SPSR,%s",`CCC, `CRB); - else - $sformat(o_decompile, "MSR%s CPSR,%s", `CCC, `CRB); -end -endtask - -task decode_msr_immed ( input [INS_WDT-1:0] i_instruction ); -begin - if ( i_instruction[22] ) // SPSR - $sformat(o_decompile, "MSR%s SPSR,%dROR%d",`CCC, $unsigned(i_instruction[7:0]), $unsigned(i_instruction[11:8])); - else - $sformat(o_decompile, "MSR%s CPSR,%dROR%d",`CCC, $unsigned(i_instruction[7:0]), $unsigned(i_instruction[11:8])); -end -endtask - -// LS ISS -task decode_ls_iss ( input [INS_WDT-1:0] i_instruction ); -begin:blk2323 - reg [32*8-1:0] ls_iss_offset; - - $sformat(ls_iss_offset, "%s%s%d", `CRB, `CSHTYPE, $unsigned(i_instruction[11:7])); - - // If word load - if ( i_instruction[20] ) - if ( !i_instruction[22] ) - begin - case ( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%s %s[%s,%s]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"LDR%s %s[%s,%s]" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"LDR%s %s[%s],%s" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%s T%s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - begin - case( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%sB %s[%s,%s]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"LDR%sB %s[%s,%s]" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"LDR%sB %s[%s],%s" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%sB T%s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - if ( !i_instruction[22] ) - begin - case ( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"STR%s %s[%s,%s]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"STR%s %s[%s,%s]", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"STR%s %s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"STR%s T%s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - begin - case( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"STR%sB %s[%s,%s]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"STR%sB %s[%s,%s]", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"STR%sB %s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"STR%sB T%s[%s],%s", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end -end -endtask - -// LS immediate -task decode_ls ( input [INS_WDT-1:0] i_instruction ); -begin:blk4343 - integer ls_iss_offset; // Forgive the naming convention... - - ls_iss_offset = i_instruction[11:0]; - - // If word load - if ( i_instruction[20] ) - if ( !i_instruction[22] ) - begin - case ( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%s %s[%s,%0d]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"LDR%s %s[%s,%0d]" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"LDR%s %s[%s],%0d" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%s T%s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - begin - case( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%sB %s[%s,%0d]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"LDR%sB %s[%s,%0d]" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"LDR%sB %s[%s],%0d" , `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"LDR%sB T%s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - if ( !i_instruction[22] ) - begin - case ( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"STR%s %s[%s,%0d]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"STR%s %s[%s,%0d]", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"STR%s %s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"STR%s T%s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - else - begin - case( {i_instruction[24], i_instruction[21]} ) - {1'd1, 1'd1}: $sformat(o_decompile,"STR%sB %s[%s,%0d]!", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex with writeback - {1'd1, 1'd0}: $sformat(o_decompile,"STR%sB %s[%s,%0d]", `CCC,`CRD1,`CRN1, ls_iss_offset); // Preindex without writeback - {1'd0, 1'd0}: $sformat(o_decompile,"STR%sB %s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset); // Post index - {1'd1, 1'd1}: $sformat(o_decompile,"STR%sB T%s[%s],%0d", `CCC,`CRD1,`CRN1, ls_iss_offset);// Force user view of memory. - endcase - end - -end -endtask - -// Mult. MUL, MLA -task decode_mult ( input [INS_WDT-1:0] i_instruction ); -begin - if ( i_instruction[21] == 1'd0 ) - $sformat(o_decompile, "MUL%s %s,%s,%s",`CCC,`CRN,`CRD,arch_reg_num(i_instruction[11:8])); - else - $sformat(o_decompile, "MLA%s %s,%s,%s,%s",`CCC,`CRN,`CRD,arch_reg_num(i_instruction[11:8]), arch_reg_num(i_instruction[3:0])); -end -endtask - -`ifndef XUMULL - - `define XUMULL 3'b100 - `define XUMLAL 3'b101 - `define XSMULL 3'b110 - `define XSMLAL 3'b111 - -`endif - -// Long Mult. UMULL, UMLAL, SMULL, SMLAL -task decode_lmult ( input [INS_WDT-1:0] i_instruction ); -begin - case(i_instruction[23:21]) - `XUMULL: $sformat(o_decompile, "UMULL %s:%s=%s*%s" ,i_instruction[19:16], i_instruction[15:12], i_instruction[3:0], i_instruction[11:8] ); - `XUMLAL: $sformat(o_decompile, "UMLAL %s:%s+=%s*%s",i_instruction[19:16], i_instruction[15:12], i_instruction[3:0], i_instruction[11:8] ); - `XSMULL: $sformat(o_decompile, "SMULL %s:%s=%s*%s" ,i_instruction[19:16], i_instruction[15:12], i_instruction[3:0], i_instruction[11:8] ); - `XSMLAL: $sformat(o_decompile, "SMLAL %s:%s+=%s*%s",i_instruction[19:16], i_instruction[15:12], i_instruction[3:0], i_instruction[11:8] ); - endcase -end -endtask - -task decode_halfword_ls ( input [INS_WDT-1:0] i_instruction ); -begin - o_decompile = "***HALFWORD LD/ST***"; -end -endtask - -// Returns shift type. -function [4*8-1:0] get_shtype ( input [2:0] x ); -begin - case(x) - 0: get_shtype = "LSL"; - 1: get_shtype = "LSR"; - 2: get_shtype = "ASR"; - 3: get_shtype = "ROR"; - 4: get_shtype = "RRC"; - 5: get_shtype = "RORI"; - 6: get_shtype = "ROR1"; - 7: get_shtype = "<-->"; - endcase -end -endfunction - -// Returns opcode in english. -function [6*8-1:0] get_opcode ( input [4:0] x ); -begin - case(x) - 0: get_opcode = "AND" ; //= 0; - 1: get_opcode = "EOR" ; //= 1; - 2: get_opcode = "SUB" ; //= 2; - 3: get_opcode = "RSB" ; //= 3; - 4: get_opcode = "ADD" ; //= 4; - 5: get_opcode = "ADC" ; //= 5; - 6: get_opcode = "SBC" ; //= 6; - 7: get_opcode = "RSC" ; //= 7; - 8: get_opcode = "TST" ; //= 8; - 9: get_opcode = "TEQ" ; //= 9; - 10:get_opcode = "CMP" ; //= 10; - 11:get_opcode = "CMN" ; //= 11; - 12:get_opcode = "ORR" ; //= 12; - 13:get_opcode = "MOV" ; //= 13; - 14:get_opcode = "BIC" ; //= 14; - 15:get_opcode = "MVN" ; //= 15; - 16:get_opcode = "MUL" ; //= 16; // Multiply ( 32 x 32 = 32 ) -> Translated to MAC. - 17:get_opcode = "MLA" ; //= 17; // Multiply-Accumulate ( 32 x 32 + 32 = 32 ). - 18:get_opcode = "FMOV" ; //= 18; - 19:get_opcode = "MMOV" ; //= 19; - 20:get_opcode = "UMLALL" ; //= 20; // Unsigned multiply accumulate (Write lower reg). - 21:get_opcode = "UMLALH" ; //= 21; - 22:get_opcode = "SMLALL" ; //= 22; // Signed multiply accumulate (Write lower reg). - 23:get_opcode = "SMLALH" ; //= 23; - 24:get_opcode = "CLZ" ; //= 24; // Count Leading zeros. - default: get_opcode = "<-->"; - endcase -end -endfunction - -// Returns arch reg number (5 bit number as input.) -function [4*8-1:0] arch_reg_num ( input [4:0] reg_num ); -begin:blk434234 - reg [4*8-1:0] x; - - case(reg_num) - 5'd0 : x = "R0 "; - 5'd1 : x = "R1 "; - 5'd2 : x = "R2 "; - 5'd3 : x = "R3 "; - 5'd4 : x = "R4 "; - 5'd5 : x = "R5 "; - 5'd6 : x = "R6 "; - 5'd7 : x = "R7 "; - 5'd8 : x = "R8 "; - 5'd9 : x = "R9 "; - 5'd10 : x = "R10 "; - 5'd11 : x = "R11 "; - 5'd12 : x = "R12 "; - 5'd13 : x = "SP "; - 5'd14 : x = "LR "; - 5'd15 : x = "PC "; - 5'd16 : x = "RAZ "; - 5'd17 : x = "CPSR"; - 5'd18 : x = "R8x "; - 5'd19 : x = "R9x "; - 5'd20 : x = "R10x"; - 5'd21 : x = "R11x"; - 5'd22 : x = "R12x"; - 5'd23 : x = "R13x"; - 5'd24 : x = "R14x"; - 5'd25 : x = "DMY0"; - 5'd26 : x = "DMY1"; - 5'd27 : x = "SPSR"; - 5'd28 : x = "<-->"; - 5'd29 : x = "<-->"; - 5'd30 : x = "<-->"; - 5'd31 : x = "<-->"; - endcase - - arch_reg_num = x; -end -endfunction - -// Returns a text version of the condition code. -function [2*8-1:0] cond_code ( input [3:0] cond ); -begin: blk49329483 - reg [2*8-1:0] ok; - - case(cond) - EQ: ok = "EQ"; - NE: ok = "NE"; - CS: ok = "CS"; - CC: ok = "CC"; - MI: ok = "MI"; - PL: ok = "PL"; - VS: ok = "VS"; - VC: ok = "VC"; - HI: ok = "HI"; - LS: ok = "LS"; - GE: ok = "GE"; - LT: ok = "LT"; - GT: ok = "GT"; - LE: ok = "LE"; - AL: ok = "AL"; - NV: ok = "NV"; - endcase - - cond_code = ok; -end -endfunction - -`else - -always @* - o_decompile = 0; // In synthesis mode. - -`endif - -endmodule // zap_decompile.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_shift_shifter.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_shift_shifter.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_shift_shifter.v (nonexistent) @@ -1,108 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_shift_shifter -#( - parameter SHIFT_OPS = 5 -) -( - // Source value. - input wire [31:0] i_source, - - // Shift amount. - input wire [7:0] i_amount, - - // Carry in. - input wire i_carry, - - // Shift type. - input wire [$clog2(SHIFT_OPS)-1:0] i_shift_type, - - // Output result and output carry. - output reg [31:0] o_result, - output reg o_carry -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -always @* -begin - // Prevent latch inference. - o_result = i_source; - o_carry = 0; - - case ( i_shift_type ) - - // Logical shift left, logical shift right and - // arithmetic shift right. - LSL: {o_carry, o_result} = {i_carry, i_source} << i_amount; - LSR: {o_result, o_carry} = {i_source, i_carry} >> i_amount; - ASR: - begin:blk1111 - reg signed [32:0] res, res1; - res = {i_source, i_carry}; - res1 = $signed(res) >>> i_amount; - {o_result, o_carry} = res1; - end - - ROR: // Rotate right. - begin - o_result = ( i_source >> i_amount[4:0] ) | - ( i_source << (32 - i_amount[4:0] ) ); - o_carry = ( i_amount[7:0] == 0) ? - i_carry : ( (i_amount[4:0] == 0) ? - i_source[31] : o_result[31] ); - end - - RORI, ROR_1: - begin - // ROR #n (ROR_1) - o_result = ( i_source >> i_amount[4:0] ) | - (i_source << (32 - i_amount[4:0] ) ); - o_carry = i_amount ? o_result[31] : i_carry; - end - - // ROR #0 becomes this. - RRC: {o_result, o_carry} = {i_carry, i_source}; - - default: // For lint. - begin - end - endcase -end - -/////////////////////////////////////////////////////////////////////////////// - -endmodule // zap_shift_shifter.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_top.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_top.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_top.v (nonexistent) @@ -1,414 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This is the top module of the ZAP processor. It contains instances of -- -// -- processor core and the memory management units. I and D WB busses -- -// -- are provided. -- -// -- -- -// ---------------------------------------------------------------------------- - -`default_nettype none - -module zap_top #( - -// ----------------------------------- -// BP entries, FIFO depths -// ----------------------------------- - -parameter BP_ENTRIES = 1024, // Predictor depth. -parameter FIFO_DEPTH = 4, // FIFO depth. -parameter STORE_BUFFER_DEPTH = 16, // Depth of the store buffer. - -// ---------------------------------- -// Data MMU/Cache configuration. -// ---------------------------------- -parameter [31:0] DATA_SECTION_TLB_ENTRIES = 32'd4, // Section TLB entries. -parameter [31:0] DATA_LPAGE_TLB_ENTRIES = 32'd8, // Large page TLB entries. -parameter [31:0] DATA_SPAGE_TLB_ENTRIES = 32'd16, // Small page TLB entries. -parameter [31:0] DATA_CACHE_SIZE = 32'd1024, // Cache size in bytes. - -// ---------------------------------- -// Code MMU/Cache configuration. -// ---------------------------------- -parameter [31:0] CODE_SECTION_TLB_ENTRIES = 32'd4, // Section TLB entries. -parameter [31:0] CODE_LPAGE_TLB_ENTRIES = 32'd8, // Large page TLB entries. -parameter [31:0] CODE_SPAGE_TLB_ENTRIES = 32'd16, // Small page TLB entries. -parameter [31:0] CODE_CACHE_SIZE = 32'd1024 // Cache size in bytes. - -)( - // -------------------------------------- - // Clock and reset - // -------------------------------------- - - input wire i_clk, - input wire i_reset, - - // --------------------------------------- - // Interrupts. - // Both of them are active high and level - // trigerred. - // --------------------------------------- - - input wire i_irq, - input wire i_fiq, - - // --------------------- - // Wishbone interface. - // --------------------- - - output wire o_wb_cyc, - output wire o_wb_stb, - output wire o_wb_stb_nxt, - output wire o_wb_cyc_nxt, - output wire [31:0] o_wb_adr_nxt, - output wire [31:0] o_wb_adr, - output wire o_wb_we, - output wire [31:0] o_wb_dat, - output wire [3:0] o_wb_sel, - output wire [2:0] o_wb_cti, - output wire [1:0] o_wb_bte, - input wire i_wb_ack, - input wire [31:0] i_wb_dat -); - -assign o_wb_bte = 2'b00; // Linear Burst. - -localparam COMPRESSED_EN = 1'd1; - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -wire wb_cyc, wb_stb, wb_we; -wire [3:0] wb_sel; -wire [31:0] wb_dat, wb_idat; -wire [31:0] wb_adr; -wire [2:0] wb_cti; -wire wb_ack; -reg reset; - -// Synchronous reset signal flopped. -always @ (posedge i_clk) - reset <= i_reset; - -wire cpu_mmu_en; -wire [31:0] cpu_cpsr; -wire cpu_mem_translate; - -wire [31:0] cpu_daddr, cpu_daddr_nxt; -wire [31:0] cpu_iaddr, cpu_iaddr_nxt; - -wire [7:0] dc_fsr; -wire [31:0] dc_far; - -wire cpu_dc_en, cpu_ic_en; - -wire [1:0] cpu_sr; -wire [7:0] cpu_pid; -wire [31:0] cpu_baddr, cpu_dac_reg; - -wire cpu_dc_inv, cpu_ic_inv; -wire cpu_dc_clean, cpu_ic_clean; - -wire dc_inv_done, ic_inv_done, dc_clean_done, ic_clean_done; - -wire cpu_dtlb_inv, cpu_itlb_inv; - -wire data_ack, data_err, instr_ack, instr_err; - -wire [31:0] ic_data, dc_data, cpu_dc_dat; -wire cpu_instr_stb; -wire cpu_dc_we, cpu_dc_stb; -wire [3:0] cpu_dc_sel; - -wire c_wb_stb; -wire c_wb_cyc; -wire c_wb_wen; -wire [3:0] c_wb_sel; -wire [31:0] c_wb_dat; -wire [31:0] c_wb_adr; -wire [2:0] c_wb_cti; -wire c_wb_ack; - -wire d_wb_stb; -wire d_wb_cyc; -wire d_wb_wen; -wire [3:0] d_wb_sel; -wire [31:0] d_wb_dat; -wire [31:0] d_wb_adr; -wire [2:0] d_wb_cti; -wire d_wb_ack; - -zap_core #( - .BP_ENTRIES(BP_ENTRIES), - .FIFO_DEPTH(FIFO_DEPTH) -) u_zap_core -( -// Clock and reset. -.i_clk (i_clk), -.i_reset (reset), - -// Code related. -.o_instr_wb_adr (cpu_iaddr), -.o_instr_wb_cyc (), -.o_instr_wb_stb (cpu_instr_stb), -.o_instr_wb_we (), -.o_instr_wb_sel (), - -// Code related. -.i_instr_wb_dat (ic_data), - -.i_instr_wb_ack (instr_ack), -.i_instr_wb_err (instr_err), - -// Data related. -.o_data_wb_we (cpu_dc_we), -.o_data_wb_adr (cpu_daddr), -.o_data_wb_sel (cpu_dc_sel), -.o_data_wb_dat (cpu_dc_dat), -.o_data_wb_cyc (), -.o_data_wb_stb (cpu_dc_stb), - -// Data related. -.i_data_wb_ack (data_ack), -.i_data_wb_err (data_err), -.i_data_wb_dat (dc_data), - -// Interrupts. -.i_fiq (i_fiq), -.i_irq (i_irq), - -// MMU/cache is present. -.o_mem_translate (cpu_mem_translate), -.i_fsr ({24'd0,dc_fsr}), -.i_far (dc_far), -.o_dac (cpu_dac_reg), -.o_baddr (cpu_baddr), -.o_mmu_en (cpu_mmu_en), -.o_sr (cpu_sr), -.o_pid (cpu_pid), -.o_dcache_inv (cpu_dc_inv), -.o_icache_inv (cpu_ic_inv), -.o_dcache_clean (cpu_dc_clean), -.o_icache_clean (cpu_ic_clean), -.o_dtlb_inv (cpu_dtlb_inv), -.o_itlb_inv (cpu_itlb_inv), -.i_dcache_inv_done (dc_inv_done), -.i_icache_inv_done (ic_inv_done), -.i_dcache_clean_done (dc_clean_done), -.i_icache_clean_done (ic_clean_done), -.o_dcache_en (cpu_dc_en), -.o_icache_en (cpu_ic_en), - -// Data IF nxt. -.o_data_wb_adr_nxt (cpu_daddr_nxt), // Data addr nxt. Used to drive address of data tag RAM. -.o_data_wb_we_nxt (), -.o_data_wb_cyc_nxt (), -.o_data_wb_stb_nxt (), -.o_data_wb_dat_nxt (), -.o_data_wb_sel_nxt (), - -// Code access prpr. -.o_instr_wb_adr_nxt (cpu_iaddr_nxt), // PC addr nxt. Drives read address of code tag RAM. -.o_instr_wb_stb_nxt (), - -.o_cpsr (cpu_cpsr) - -); - -zap_cache #( - .CACHE_SIZE(DATA_CACHE_SIZE), - .SPAGE_TLB_ENTRIES(DATA_SPAGE_TLB_ENTRIES), - .LPAGE_TLB_ENTRIES(DATA_LPAGE_TLB_ENTRIES), - .SECTION_TLB_ENTRIES(DATA_SECTION_TLB_ENTRIES)) -u_data_cache ( -.i_clk (i_clk), -.i_reset (reset), -.i_address (cpu_daddr + (cpu_pid << 25)), -.i_address_nxt (cpu_daddr_nxt + (cpu_pid << 25)), - -.i_rd (!cpu_dc_we && cpu_dc_stb), -.i_wr (cpu_dc_we), -.i_ben (cpu_dc_sel), -.i_dat (cpu_dc_dat), -.o_dat (dc_data), -.o_ack (data_ack), -.o_err (data_err), - -.o_fsr (dc_fsr), -.o_far (dc_far), -.i_mmu_en (cpu_mmu_en), -.i_cache_en (cpu_dc_en), -.i_cache_inv_req (cpu_dc_inv), -.i_cache_clean_req (cpu_dc_clean), -.o_cache_inv_done (dc_inv_done), -.o_cache_clean_done (dc_clean_done), -.i_cpsr (cpu_mem_translate ? USR : cpu_cpsr), -.i_sr (cpu_sr), -.i_baddr (cpu_baddr), -.i_dac_reg (cpu_dac_reg), -.i_tlb_inv (cpu_dtlb_inv), - -.o_wb_stb (), -.o_wb_cyc (), -.o_wb_wen (), -.o_wb_sel (), -.o_wb_dat (), -.o_wb_adr (), -.o_wb_cti (), - -.i_wb_dat (wb_dat), -.i_wb_ack (d_wb_ack), - -.o_wb_stb_nxt (d_wb_stb), -.o_wb_cyc_nxt (d_wb_cyc), -.o_wb_wen_nxt (d_wb_wen), -.o_wb_sel_nxt (d_wb_sel), -.o_wb_dat_nxt (d_wb_dat), -.o_wb_adr_nxt (d_wb_adr), -.o_wb_cti_nxt (d_wb_cti) -); - -zap_cache #( -.CACHE_SIZE(CODE_CACHE_SIZE), -.SPAGE_TLB_ENTRIES(CODE_SPAGE_TLB_ENTRIES), -.LPAGE_TLB_ENTRIES(CODE_LPAGE_TLB_ENTRIES), -.SECTION_TLB_ENTRIES(CODE_SECTION_TLB_ENTRIES)) -u_code_cache ( -.i_clk (i_clk), -.i_reset (reset), -.i_address ((cpu_iaddr & 32'hFFFF_FFFC) + (cpu_pid << 25)), // Cut off lower 2 bits. -.i_address_nxt ((cpu_iaddr_nxt & 32'hFFFF_FFFC) + (cpu_pid << 25)), // Cut off lower 2 bits. - -.i_rd (cpu_instr_stb), -.i_wr (1'd0), -.i_ben (4'b1111), -.i_dat (32'd0), -.o_dat (ic_data), -.o_ack (instr_ack), -.o_err (instr_err), - -.o_fsr (), -.o_far (), -.i_mmu_en (cpu_mmu_en), -.i_cache_en (cpu_ic_en), -.i_cache_inv_req (cpu_ic_inv), -.i_cache_clean_req (cpu_ic_clean), -.o_cache_inv_done (ic_inv_done), -.o_cache_clean_done(ic_clean_done), -.i_cpsr (cpu_mem_translate ? USR : cpu_cpsr), -.i_sr (cpu_sr), -.i_baddr (cpu_baddr), -.i_dac_reg (cpu_dac_reg), -.i_tlb_inv (cpu_itlb_inv), - -.o_wb_stb (), -.o_wb_cyc (), -.o_wb_wen (), -.o_wb_sel (), -.o_wb_dat (), -.o_wb_adr (), -.o_wb_cti (), - -.i_wb_dat (wb_dat), -.i_wb_ack (c_wb_ack), - -.o_wb_stb_nxt (c_wb_stb), -.o_wb_cyc_nxt (c_wb_cyc), -.o_wb_wen_nxt (c_wb_wen), -.o_wb_sel_nxt (c_wb_sel), -.o_wb_dat_nxt (c_wb_dat), -.o_wb_adr_nxt (c_wb_adr), -.o_wb_cti_nxt (c_wb_cti) -); - -zap_wb_merger u_zap_wb_merger ( - -.i_clk(i_clk), -.i_reset(i_reset), - -.i_c_wb_stb(c_wb_stb), -.i_c_wb_cyc(c_wb_cyc), -.i_c_wb_wen(c_wb_wen), -.i_c_wb_sel(c_wb_sel), -.i_c_wb_dat(c_wb_dat), -.i_c_wb_adr(c_wb_adr), -.i_c_wb_cti(c_wb_cti), -.o_c_wb_ack(c_wb_ack), - -.i_d_wb_stb(d_wb_stb), -.i_d_wb_cyc(d_wb_cyc), -.i_d_wb_wen(d_wb_wen), -.i_d_wb_sel(d_wb_sel), -.i_d_wb_dat(d_wb_dat), -.i_d_wb_adr(d_wb_adr), -.i_d_wb_cti(d_wb_cti), -.o_d_wb_ack(d_wb_ack), - -.o_wb_cyc(wb_cyc), -.o_wb_stb(wb_stb), -.o_wb_wen(wb_we), -.o_wb_sel(wb_sel), -.o_wb_dat(wb_idat), -.o_wb_adr(wb_adr), -.o_wb_cti(wb_cti), -.i_wb_ack(wb_ack) - -); - -zap_wb_adapter #(.DEPTH(STORE_BUFFER_DEPTH)) u_zap_wb_adapter ( -.i_clk(i_clk), -.i_reset(i_reset), - -.I_WB_CYC(wb_cyc), -.I_WB_STB(wb_stb), -.I_WB_WE(wb_we), -.I_WB_DAT(wb_idat), -.I_WB_SEL(wb_sel), -.I_WB_CTI(wb_cti), -.O_WB_ACK(wb_ack), -.O_WB_DAT(wb_dat), -.I_WB_ADR(wb_adr), - -.o_wb_cyc(o_wb_cyc), -.o_wb_stb(o_wb_stb), -.o_wb_we(o_wb_we), -.o_wb_sel(o_wb_sel), -.o_wb_dat(o_wb_dat), -.o_wb_adr(o_wb_adr), -.o_wb_cti(o_wb_cti), -.i_wb_dat(i_wb_dat), -.i_wb_ack(i_wb_ack), - -// CYC and STB nxt. -.o_wb_stb_nxt (o_wb_stb_nxt), -.o_wb_cyc_nxt (o_wb_cyc_nxt), -.o_wb_adr_nxt (o_wb_adr_nxt), -.o_wb_sel_nxt (), -.o_wb_dat_nxt (), -.o_wb_we_nxt () -); - -endmodule // zap_top.v - -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_thumb_decoder.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_thumb_decoder.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_thumb_decoder.v (nonexistent) @@ -1,189 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Implements a 16-bit instruction decoder. The 16-bit instruction set is -- -// -- not logically organized so as to save on encoding and thus the code -- -// -- seem a bit complex. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_thumb_decoder ( - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // Code stall. - input wire i_clear_from_writeback, - input wire i_data_stall, - input wire i_clear_from_alu, - input wire i_stall_from_shifter, - input wire i_stall_from_issue, - input wire i_stall_from_decode, - input wire i_clear_from_decode, - - // Predictor status. - input wire [1:0] i_taken, - - // Input from I-cache. - // Instruction and valid qualifier. - input wire [31:0] i_instruction, - input wire i_instruction_valid, - - // Interrupts. Active high level sensitive signals. - input wire i_irq, - input wire i_fiq, - - // Aborts. - input wire i_iabort, - output reg o_iabort, - - // Ensure compressed mode is active (T bit). - input wire i_cpsr_ff_t, - - // Program counter. - input wire [31:0] i_pc_ff, - input wire [31:0] i_pc_plus_8_ff, - - // - // Outputs to the ARM decoder. - // - - // Instruction, valid, undefined by this decoder and force 32-bit - // align signals (requires memory to keep lower 2 bits as 00). - output reg [34:0] o_instruction, - output reg o_instruction_valid, - output reg o_und, - output reg o_force32_align, - - // PCs. - output reg [31:0] o_pc_ff, - output reg [31:0] o_pc_plus_8_ff, - - // Interrupt status output. - output reg o_irq, - output reg o_fiq, - - // Taken - output reg [1:0] o_taken_ff -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -wire [34:0] instruction_nxt; -wire instruction_valid_nxt; -wire und_nxt; -wire force32_nxt; -wire irq_nxt; -wire fiq_nxt; -reg [1:0] taken_nxt; - -zap_predecode_compress u_zap_predecode_compress ( - .i_clk(i_clk), - .i_instruction(i_instruction), - .i_instruction_valid(i_instruction_valid), - .i_irq(i_irq), - .i_fiq(i_fiq), - .i_offset(o_instruction[11:0]), - .i_cpsr_ff_t(i_cpsr_ff_t), - .o_instruction(instruction_nxt), - .o_instruction_valid(instruction_valid_nxt), - .o_und(und_nxt), - .o_force32_align(force32_nxt), - .o_irq(irq_nxt), - .o_fiq(fiq_nxt) -); - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - o_instruction_valid <= 1'd0; - o_irq <= 0; - o_fiq <= 0; - o_und <= 0; - o_iabort <= 0; - end - else if ( i_clear_from_writeback ) - begin - o_instruction_valid <= 1'd0; - o_irq <= 0; - o_fiq <= 0; - o_und <= 0; - o_iabort <= 0; - end - else if ( i_data_stall ) - begin - end - else if ( i_clear_from_alu ) - begin - o_instruction_valid <= 1'd0; - o_irq <= 0; - o_fiq <= 0; - o_und <= 0; - o_iabort <= 0; - end - else if ( i_stall_from_shifter ) begin end - else if ( i_stall_from_issue ) begin end - else if ( i_stall_from_decode ) begin end - else if ( i_clear_from_decode ) - begin - o_instruction_valid <= 1'd0; - o_irq <= 0; - o_fiq <= 0; - o_und <= 0; - o_iabort <= 0; - end - else // BUG FIX. - begin - o_iabort <= i_iabort; - o_instruction_valid <= instruction_valid_nxt; - o_instruction <= instruction_nxt; - o_und <= und_nxt; - o_force32_align <= force32_nxt; - o_pc_ff <= i_pc_ff; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_irq <= irq_nxt; - o_fiq <= fiq_nxt; - o_taken_ff <= i_taken; - end -end - -// Helpful for debug. -zap_decompile u_zap_decompile ( - .i_instruction ({1'd0, o_instruction}), - .i_dav (o_instruction_valid), - .o_decompile () -); - - -endmodule // zap_thumb_decoder - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_localparams.vh =================================================================== --- zap/trunk/src/rtl/cpu/zap_localparams.vh (revision 57) +++ zap/trunk/src/rtl/cpu/zap_localparams.vh (nonexistent) @@ -1,367 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -// Identifier for L1 -localparam [1:0] SECTION_ID = 2'b10; -localparam [1:0] PAGE_ID = 2'b01; - -// Identifier for L2 -localparam [1:0] SPAGE_ID = 2'b10; -localparam [1:0] LPAGE_ID = 2'b01; - -// APSR bits. -// K U (kernel user) permissions. -localparam APSR_NA_NA = 4'b00_00; -localparam APSR_RO_RO = 4'b00_01; -localparam APSR_RO_NA = 4'b00_10; -localparam APSR_RW_NA = 4'b01_??; -localparam APSR_RW_RO = 4'b10_??; -localparam APSR_RW_RW = 4'b11_??; - -// DAC bits. -localparam DAC_MANAGER = 2'b11; -localparam DAC_CLIENT = 2'b01; - -// FSR related. -// These localparams relate to FSR values. Notice how -// only some FSR values make sense in this implementation. - -//Section. -localparam [3:0] FSR_SECTION_DOMAIN_FAULT = 4'b1001; -localparam [3:0] FSR_SECTION_TRANSLATION_FAULT = 4'b0101; -localparam [3:0] FSR_SECTION_PERMISSION_FAULT = 4'b1101; - -//Page. -localparam [3:0] FSR_PAGE_TRANSLATION_FAULT = 4'b0111; -localparam [3:0] FSR_PAGE_DOMAIN_FAULT = 4'b1011; -localparam [3:0] FSR_PAGE_PERMISSION_FAULT = 4'b1111; - - - -/////////////////////////////////////////////////////////////////////////////// - -// Standard opcodes. -// These map to the opcode map in the spec. -localparam [3:0] AND = 0; -localparam [3:0] EOR = 1; -localparam [3:0] SUB = 2; -localparam [3:0] RSB = 3; -localparam [3:0] ADD = 4; -localparam [3:0] ADC = 5; -localparam [3:0] SBC = 6; -localparam [3:0] RSC = 7; -localparam [3:0] TST = 8; -localparam [3:0] TEQ = 9; -localparam [3:0] CMP = 10; -localparam [3:0] CMN = 11; -localparam [3:0] ORR = 12; -localparam [3:0] MOV = 13; -localparam [3:0] BIC = 14; -localparam [3:0] MVN = 15; - -// Internal opcodes used to -// implement some instructions. -localparam [4:0] MUL = 16; // Multiply ( 32 x 32 = 32 ) -> Translated to MAC. -localparam [4:0] MLA = 17; // Multiply-Accumulate ( 32 x 32 + 32 = 32 ). - -// Flag MOV. Will write upper 4-bits to flags if mask bit [3] is set to 1. -// Also writes to target register similarly. -// Mask bit comes from non-shift operand. -localparam [4:0] FMOV = 18; - -// Same as FMOV but does not touch the flags in the ALU. This is MASK MOV. -// Set to 1 will update, 0 will not -// (0000 -> No updates, 0001 -> [7:0] update) and so on. -localparam [4:0] MMOV = 19; - -localparam [4:0] UMLALL = 20; // Unsigned multiply accumulate (Write lower reg). -localparam [4:0] UMLALH = 21; - -localparam [4:0] SMLALL = 22; // Signed multiply accumulate (Write lower reg). -localparam [4:0] SMLALH = 23; - -localparam [4:0] CLZ = 24; // Count Leading zeros. - -// Conditionals defined as per v5T spec. -localparam EQ = 4'h0; -localparam NE = 4'h1; -localparam CS = 4'h2; -localparam CC = 4'h3; -localparam MI = 4'h4; -localparam PL = 4'h5; -localparam VS = 4'h6; -localparam VC = 4'h7; -localparam HI = 4'h8; -localparam LS = 4'h9; -localparam GE = 4'hA; -localparam LT = 4'hB; -localparam GT = 4'hC; -localparam LE = 4'hD; -localparam AL = 4'hE; -localparam NV = 4'hF; // NeVer execute! - -// CPSR flags. -localparam N = 31; -localparam Z = 30; -localparam C = 29; -localparam V = 28; -localparam I = 7; -localparam F = 6; -localparam T = 5; - -// For transferring indices/immediates across stages. -localparam INDEX_EN = 1'd0; -localparam IMMED_EN = 1'd1; - -// Processor Modes -localparam FIQ = 5'b10_001; -localparam IRQ = 5'b10_010; -localparam ABT = 5'b10_111; -localparam SVC = 5'b10_011; -localparam USR = 5'b10_000; -localparam SYS = 5'b11_111; -localparam UND = 5'b11_011; - -// Instruction definitions. -/* ARM */ - -localparam [31:0] DATA_PROCESSING_IMMEDIATE = 32'b????_00_1_????_?_????_????_????????????; -localparam [31:0] DATA_PROCESSING_REGISTER_SPECIFIED_SHIFT = 32'b????_00_0_????_?_????_????_????0??1????; -localparam [31:0] DATA_PROCESSING_INSTRUCTION_SPECIFIED_SHIFT = 32'b????_00_0_????_?_????_????_???????0????; - -// BL never reaches the unit. -localparam [31:0] BRANCH_INSTRUCTION = 32'b????_101?_????_????_????_????_????_????; - -localparam [31:0] MRS = 32'b????_00010_?_001111_????_????_????_????; -localparam [31:0] MSR_IMMEDIATE = 32'b????_00_1_10?10_????_1111_????_????_????; - -localparam [31:0] MSR = 32'b????_00_0_10?10_????_1111_????_????_????; - -localparam [31:0] LS_INSTRUCTION_SPECIFIED_SHIFT = 32'b????_01_1_?????_????_????_????_????_????; -localparam [31:0] LS_IMMEDIATE = 32'b????_01_0_?????_????_????_????_????_????; - -localparam [31:0] BX_INST = 32'b????_0001_0010_1111_1111_1111_0001_????; - -localparam [31:0] MULT_INST = 32'b????_0000_00?_?_????_????_????_1001_????; - -// M MULT INST - UMULL, UMLAL, SMULL, SMLAL. -localparam [31:0] LMULT_INST = 32'b????_0000_1??_?_????_????_????_1001_????; - -// Halfword memory. -localparam [31:0] HALFWORD_LS = 32'b????_000_?????_????_????_????_1??1_????; - -// Software interrupt. -localparam [31:0] SOFTWARE_INTERRUPT = 32'b????_1111_????_????_????_????_????_????; - -// Swap. -localparam [31:0] SWAP = 32'b????_00010_?_00_????_????_00001001_????; - -// Write to coprocessor. -localparam [31:0] MCR = 32'b????_1110_???_0_????_????_1111_???_1_????; -localparam [31:0] MCR2 = 32'b1111_1110???0_????????????_???1_????; - -// Read from coprocessor. -localparam [31:0] MRC = 32'b????_1110_???_1_????_????_1111_???_1_????; -localparam [31:0] MRC2 = 32'b1111_1110???1_????????????_???1_????; - -// LDC, STC -localparam [31:0] LDC = 32'b????_110_????1_????_????_????_????????; -localparam [31:0] STC = 32'b????_110_????0_????_????_????_????????; - -// LDC2, STC2 -localparam [31:0] LDC2 = 32'b1111_110????1_????????????_????_????; -localparam [31:0] STC2 = 32'b1111_110????0_????????????_????_????; - -// CDP -localparam [31:0] CDP = 32'b????_1110_????????_????????_????????; - -// CLZ -localparam [31:0] CLZ_INSTRUCTION = 32'b????_00010110_1111_????_1111_0001_????; - -// BLX(1) -localparam [31:0] BLX1 = 32'b1111_101_?_????????_????????_????????; - -// BLX(2) -localparam [31:0] BLX2 = 32'b????_00010010_1111_1111_1111_0011_????; - -/* Thumb ISA */ - -//B -localparam [15:0] T_BRANCH_COND = 16'b1101_????_????????; -localparam [15:0] T_BRANCH_NOCOND = 16'b11100_???????????; -localparam [15:0] T_BL = 16'b1111_?_???????????; -localparam [15:0] T_BX = 16'b01000111_0_?_???_000; -localparam [15:0] T_BLX1 = 16'b11101_???????????; -localparam [15:0] T_BLX2 = 16'b010001111_?_???_000; - -// SWI -localparam [15:0] T_SWI = 16'b11011111_????????; - -// Shifts. -localparam [15:0] T_SHIFT = 16'b000_??_?????_???_???; - -// Add sub LO. -localparam [15:0] T_ADD_SUB_LO = 16'b00011_?_?_???_???_???; - -// MCAS Imm. -localparam [15:0] T_MCAS_IMM = 16'b001_??_???_????????; - -// ALU Lo. -localparam [15:0] T_ALU_LO = 16'b010000_????_???_???; - -// ALU hi. -localparam [15:0] T_ALU_HI = 16'b010001_??_?_?_???_???; - -// *Get address. -localparam [15:0] T_GET_ADDR = 16'b1010_?_???_????????; - -// *Add offset to SP. -localparam [15:0] T_MOD_SP = 16'b10110000_?_????_???; - -// PC relative load. -localparam [15:0] T_PC_REL_LOAD = 16'b01001_???_????????; - -// LDR_STR_5BIT_OFF -localparam [15:0] T_LDR_STR_5BIT_OFF = 16'b011_?_?_?????_???_???; - -// LDRH_STRH_5BIT_OFF -localparam [15:0] T_LDRH_STRH_5BIT_OFF = 16'b1000_?_?????_???_???; - -// Signed LDR/STR -localparam [15:0] T_LDRH_STRH_REG = 16'b0101_???_???_???_???; - -// SP relative LDR/STR -localparam [15:0] T_SP_REL_LDR_STR = 16'b1001_?_???_????????; - -// LDMIA/STMIA -localparam [15:0] T_LDMIA_STMIA = 16'b1100_?_???_????????; - -// PUSH POP -localparam [15:0] T_POP_PUSH = 16'b1011_?_10_?_????????; - -// -// Architectural Registers. -// Architectural registers are registered defined by the architecture plus -// a few more. Basically instructions index into architectural registers. -// -localparam [3:0] ARCH_SP = 13; -localparam [3:0] ARCH_LR = 14; -localparam [3:0] ARCH_PC = 15; -localparam RAZ_REGISTER = 16; // Serves as $0 does on MIPS. - -// These always point to user registers irrespective of mode. -localparam ARCH_USR2_R8 = 18; -localparam ARCH_USR2_R9 = 19; -localparam ARCH_USR2_R10 = 20; -localparam ARCH_USR2_R11 = 21; -localparam ARCH_USR2_R12 = 22; -localparam ARCH_USR2_R13 = 23; -localparam ARCH_USR2_R14 = 24; - -// Dummy architectural registers. -localparam ARCH_DUMMY_REG0 = 25; -localparam ARCH_DUMMY_REG1 = 26; - -// CPSR and SPSR. -localparam ARCH_CPSR = 17; -localparam ARCH_CURR_SPSR = 27; // Alias to real SPSR. - -// Total architectural registers. -localparam TOTAL_ARCH_REGS = 28; - -// -// Physical registers. -// Physical registers can be mapped directly into the internal -// register file. -// -localparam PHY_PC = 15; // DO NOT CHANGE! -localparam PHY_RAZ_REGISTER = 16; // DO NOT CHANGE! -localparam PHY_CPSR = 17; // DO NOT CHANGE! - -localparam PHY_USR_R0 = 0; -localparam PHY_USR_R1 = 1; -localparam PHY_USR_R2 = 2; -localparam PHY_USR_R3 = 3; -localparam PHY_USR_R4 = 4; -localparam PHY_USR_R5 = 5; -localparam PHY_USR_R6 = 6; -localparam PHY_USR_R7 = 7; -localparam PHY_USR_R8 = 8; -localparam PHY_USR_R9 = 9; -localparam PHY_USR_R10 = 10; -localparam PHY_USR_R11 = 11; -localparam PHY_USR_R12 = 12; -localparam PHY_USR_R13 = 13; -localparam PHY_USR_R14 = 14; - -localparam PHY_FIQ_R8 = 18; -localparam PHY_FIQ_R9 = 19; -localparam PHY_FIQ_R10 = 20; -localparam PHY_FIQ_R11 = 21; -localparam PHY_FIQ_R12 = 22; -localparam PHY_FIQ_R13 = 23; -localparam PHY_FIQ_R14 = 24; - -localparam PHY_IRQ_R13 = 25; -localparam PHY_IRQ_R14 = 26; - -localparam PHY_SVC_R13 = 27; -localparam PHY_SVC_R14 = 28; - -localparam PHY_UND_R13 = 29; -localparam PHY_UND_R14 = 30; - -localparam PHY_ABT_R13 = 31; -localparam PHY_ABT_R14 = 32; - -// Dummy registers for various purposes. -localparam PHY_DUMMY_REG0 = 33; -localparam PHY_DUMMY_REG1 = 34; - -// SPSRs. -localparam PHY_FIQ_SPSR = 35; -localparam PHY_IRQ_SPSR = 36; -localparam PHY_SVC_SPSR = 37; -localparam PHY_UND_SPSR = 38; -localparam PHY_ABT_SPSR = 39; - -// -// Count of total registers -// (Can go up to 64 with no problems). Used to set register index widths of -// the control signals. -// -localparam TOTAL_PHY_REGS = 40; - -// Shift type. -localparam [1:0] LSL = 0; -localparam [1:0] LSR = 1; -localparam [1:0] ASR = 2; -localparam [1:0] ROR = 3; -localparam [2:0] RRC = 4; // Encoded as ROR #0. -localparam [2:0] RORI = 5; -localparam [2:0] ROR_1= 6; // ROR with instruction specified shift. - -// Wishbone CTI. -localparam CTI_CLASSIC = 3'b000; -localparam CTI_BURST = 3'b010; -localparam CTI_EOB = 3'b111; Index: zap/trunk/src/rtl/cpu/zap_wb_adapter.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_wb_adapter.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_wb_adapter.v (nonexistent) @@ -1,307 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Implements store FIFO. Serves as a bridge between the processor core & -- -// -- the memory interface. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_wb_adapter #(parameter DEPTH = 32) ( - -// Clock. -input wire i_clk, -input wire i_reset, - -// Processor Wishbone interface. These come from the Wishbone registered -// interface. -input wire I_WB_CYC, -input wire I_WB_STB, -input wire [3:0] I_WB_SEL, -input wire [2:0] I_WB_CTI, -input wire [31:0] I_WB_ADR, -input wire [31:0] I_WB_DAT, -input wire I_WB_WE, -output reg [31:0] O_WB_DAT, -output reg O_WB_ACK, - -// Wishbone interface. -output reg o_wb_cyc, -output reg o_wb_stb, -output wire [31:0] o_wb_dat, -output wire [31:0] o_wb_adr, -output wire [3:0] o_wb_sel, -output wire [2:0] o_wb_cti, -output wire o_wb_we, -input wire [31:0] i_wb_dat, -input wire i_wb_ack, - -output reg o_wb_stb_nxt, -output reg o_wb_cyc_nxt, -output wire [3:0] o_wb_sel_nxt, -output wire [31:0] o_wb_dat_nxt, -output wire [31:0] o_wb_adr_nxt, -output wire o_wb_we_nxt - -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" - -reg fsm_write_en; -reg [69:0] fsm_write_data; -wire w_eob; -wire w_full; -wire w_eob_nxt; - -assign o_wb_cti = {w_eob, 1'd1, w_eob}; - -wire w_emp; - -// {SEL, DATA, ADDR, EOB, WEN} = 4 + 64 + 1 + 1 = 70 bit. -zap_sync_fifo #(.WIDTH(70), .DEPTH(DEPTH), .FWFT(1'd0), .PROVIDE_NXT_DATA(1)) U_STORE_FIFO ( -.i_clk (i_clk), -.i_reset (i_reset), -.i_ack ((i_wb_ack && o_wb_stb) || emp_ff), -.i_wr_en (fsm_write_en), -.i_data (fsm_write_data), -.o_data ({o_wb_sel, o_wb_dat, o_wb_adr, w_eob, o_wb_we}), -.o_data_nxt ({o_wb_sel_nxt, o_wb_dat_nxt, o_wb_adr_nxt, w_eob_nxt, o_wb_we_nxt}), -.o_empty (w_emp), -.o_full (w_full), -.o_empty_n (), -.o_full_n (), -.o_full_n_nxt () -); - -reg emp_nxt; -reg emp_ff; -reg [31:0] ctr_nxt, ctr_ff; -reg [31:0] dff, dnxt; -reg ack; // ACK write channel. -reg ack_ff; // Read channel. - -localparam IDLE = 0; -localparam PRPR_RD_SINGLE = 1; -localparam PRPR_RD_BURST = 2; -localparam WRITE = 3; -localparam WAIT1 = 5; -localparam WAIT2 = 6; -localparam NUMBER_OF_STATES = 7; - -reg [$clog2(NUMBER_OF_STATES)-1:0] state_ff, state_nxt; - -// FIFO pipeline register and nxt state logic. -always @ (*) -begin - emp_nxt = emp_ff; - o_wb_stb_nxt = o_wb_stb; - o_wb_cyc_nxt = o_wb_cyc; - - if ( i_reset ) - begin - emp_nxt = 1'd1; - o_wb_stb_nxt = 1'd0; - o_wb_cyc_nxt = 1'd0; - end - else if ( emp_ff || (i_wb_ack && o_wb_stb) ) - begin - emp_nxt = w_emp; - o_wb_stb_nxt = !w_emp; - o_wb_cyc_nxt = !w_emp; - end -end - -always @ (posedge i_clk) -begin - emp_ff <= emp_nxt; - o_wb_stb <= o_wb_stb_nxt; - o_wb_cyc <= o_wb_cyc_nxt; -end - -// Flip flop clocking block. -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - state_ff <= IDLE; - ctr_ff <= 0; - dff <= 0; - end - else - begin - state_ff <= state_nxt; - ctr_ff <= ctr_nxt; - dff <= dnxt; - end -end - -// Reads from the Wishbone bus are flopped. -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - ack_ff <= 1'd0; - end - else if ( !o_wb_we && o_wb_cyc && o_wb_stb && i_wb_ack ) - begin - ack_ff <= 1'd1; - O_WB_DAT <= i_wb_dat; - end - else - begin - ack_ff <= 1'd0; - end -end - -localparam BURST_LEN = 4; - -// OR from flop and mealy FSM output. -always @* O_WB_ACK = ack_ff | ack; - -// State machine. -always @* -begin - state_nxt = state_ff; - ctr_nxt = ctr_ff; - ack = 0; - dnxt = dff; - fsm_write_en = 0; - fsm_write_data = 0; - - case(state_ff) - IDLE: - begin - ctr_nxt = 0; - dnxt = 0; - - if ( I_WB_STB && I_WB_WE && !o_wb_stb ) // Wishbone write request - begin - // Simply buffer stores into the FIFO. - state_nxt = WRITE; - end - else if ( I_WB_STB && !I_WB_WE && !o_wb_stb ) // Wishbone read request - begin - // Write a set of reads into the FIFO. - if ( I_WB_CTI == CTI_BURST ) // Burst of 4 words. Each word is 4 byte. - begin - state_nxt = PRPR_RD_BURST; - end - else // Single. - begin - state_nxt = PRPR_RD_SINGLE; - end - end - end - - PRPR_RD_SINGLE: // Write a single read token into the FIFO. - begin - if ( !w_full ) - begin - state_nxt = WAIT1; - fsm_write_en = 1'd1; - fsm_write_data = { I_WB_SEL, - I_WB_DAT, - I_WB_ADR, - I_WB_CTI != CTI_BURST ? 1'd1 : 1'd0, - 1'd0}; - end - end - - PRPR_RD_BURST: // Write burst read requests into the FIFO. - begin - if ( O_WB_ACK ) - begin - dnxt = dff + 1'd1; - end - - if ( ctr_ff == BURST_LEN * 4 ) - begin - ctr_nxt = 0; - state_nxt = WAIT2; // FIFO prep done. - end - else if ( !w_full ) - begin: blk1 - reg [31:0] adr; - adr = {I_WB_ADR[31:4], 4'd0} + ctr_ff; // Ignore lower 4-bits. - - fsm_write_en = 1'd1; - fsm_write_data = { I_WB_SEL, - I_WB_DAT, - adr, - ctr_ff == 12 ? 1'd1 : 1'd0, - 1'd0 }; - ctr_nxt = ctr_ff + 4; - end - end - - WRITE: - begin - // As long as requests exist, write them out to the FIFO. - if ( I_WB_STB && I_WB_WE ) - begin - if ( !w_full ) - begin - fsm_write_en = 1'd1; - fsm_write_data = {I_WB_SEL, I_WB_DAT, I_WB_ADR, I_WB_CTI != CTI_BURST ? 1'd1 : 1'd0, 1'd1}; - ack = 1'd1; - end - end - else // Writes done! - begin - state_nxt = IDLE; - end - end - - WAIT1: // Wait for single read to complete. - begin - if ( O_WB_ACK ) - begin - state_nxt = IDLE; - end - end - - WAIT2: // Wait for burst reads to complete. - begin - if ( O_WB_ACK ) - begin - dnxt = dff + 1; - end - - if ( dff == BURST_LEN && !o_wb_stb ) - begin - state_nxt = IDLE; - end - end - - endcase -end - -endmodule - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_cache_fsm.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_cache_fsm.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_cache_fsm.v (nonexistent) @@ -1,578 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This is the core state machine for the memory subsystem. Talks to both -- -// -- processor and the TLB controller. Cache uploads and downloads are done -- -// -- using an incrementing burst on the Wishbone bus for maximum efficiency -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -`include "zap_defines.vh" - -module zap_cache_fsm #( - parameter CACHE_SIZE = 1024 // Bytes. -) - -// ---------------------------------------------- -// Port List -// ---------------------------------------------- - -( - -/* Clock and reset */ -input wire i_clk, -input wire i_reset, - -/* From/to processor */ -input wire [31:0] i_address, -input wire i_rd, -input wire i_wr, -input wire [31:0] i_din, -input wire [3:0] i_ben, /* Valid only for writes. */ -output reg [31:0] o_dat, -output reg o_ack, -output reg o_err, -output reg [7:0] o_fsr, -output reg [31:0] o_far, - -/* From/To CP15 unit */ -input wire i_cache_en, -input wire i_cache_inv, -input wire i_cache_clean, -output reg o_cache_inv_done, -output reg o_cache_clean_done, - -/* From/to cache. */ -input wire [127:0] i_cache_line, - -input wire i_cache_tag_dirty, -input wire [`CACHE_TAG_WDT-1:0] i_cache_tag, // Tag -input wire i_cache_tag_valid, - -output reg [`CACHE_TAG_WDT-1:0] o_cache_tag, -output reg o_cache_tag_dirty, -output reg o_cache_tag_wr_en, - -output reg [127:0] o_cache_line, -output reg [15:0] o_cache_line_ben, /* Write + Byte enable */ - -output reg o_cache_clean_req, -input wire i_cache_clean_done, - -output reg o_cache_inv_req, -input wire i_cache_inv_done, - -/* From/to TLB unit */ -input wire [31:0] i_phy_addr, -input wire [7:0] i_fsr, -input wire [31:0] i_far, -input wire i_fault, -input wire i_cacheable, -input wire i_busy, - -/* Memory access ports, both NXT and FF. Usually you'll be connecting NXT ports */ -output reg o_wb_cyc_ff, o_wb_cyc_nxt, -output reg o_wb_stb_ff, o_wb_stb_nxt, -output reg [31:0] o_wb_adr_ff, o_wb_adr_nxt, -output reg [31:0] o_wb_dat_ff, o_wb_dat_nxt, -output reg [3:0] o_wb_sel_ff, o_wb_sel_nxt, -output reg o_wb_wen_ff, o_wb_wen_nxt, -output reg [2:0] o_wb_cti_ff, o_wb_cti_nxt,/* Cycle Type Indicator - 010, 111 */ -input wire i_wb_ack, -input wire [31:0] i_wb_dat - -); - -// ---------------------------------------------------------------------------- -// Includes and Localparams -// ---------------------------------------------------------------------------- - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -/* States */ -localparam IDLE = 0; /* Resting state. */ -localparam UNCACHEABLE = 1; /* Uncacheable access. */ -localparam REFRESH_1 = 2; /* Cache write hit state. Unused. */ -localparam CLEAN_SINGLE = 3; /* Ultimately cleans up cache line. Parent state */ -localparam FETCH_SINGLE = 4; /* Ultimately validates cache line. Parent state */ -localparam REFRESH = 5; /* Cache refresh parent state */ -localparam INVALIDATE = 6; /* Cache invalidate parent state */ -localparam CLEAN = 7; /* Cache clean parent state */ -localparam NUMBER_OF_STATES = 8; - -// ---------------------------------------------------------------------------- -// Signal aliases -// ---------------------------------------------------------------------------- - -wire cache_cmp = (i_cache_tag[`CACHE_TAG__TAG] == i_address[`VA__CACHE_TAG]); -wire cache_dirty = i_cache_tag_dirty; - -// ---------------------------------------------------------------------------- -// Variables -// ---------------------------------------------------------------------------- - -reg [$clog2(NUMBER_OF_STATES)-1:0] state_ff, state_nxt; -reg [31:0] buf_ff [3:0]; -reg [31:0] buf_nxt[3:0]; -reg cache_clean_req_nxt, - cache_clean_req_ff; -reg cache_inv_req_nxt, - cache_inv_req_ff; -reg [2:0] adr_ctr_ff, adr_ctr_nxt; // Needs to take on 0,1,2,3 AND 4(nxt). -reg hit; // For debug only. - -// ---------------------------------------------------------------------------- -// Logic -// ---------------------------------------------------------------------------- - -/* Tie flops to the output */ -always @* o_cache_clean_req = cache_clean_req_ff; // Tie req flop to output. -always @* o_cache_inv_req = cache_inv_req_ff; // Tie inv flop to output. - -/* Sequential Block */ -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - o_wb_cyc_ff <= 0; - o_wb_stb_ff <= 0; - o_wb_wen_ff <= 0; - o_wb_sel_ff <= 0; - o_wb_dat_ff <= 0; - o_wb_cti_ff <= CTI_CLASSIC; - o_wb_adr_ff <= 0; - cache_clean_req_ff <= 0; - cache_inv_req_ff <= 0; - adr_ctr_ff <= 0; - state_ff <= IDLE; - end - else - begin - o_wb_cyc_ff <= o_wb_cyc_nxt; - o_wb_stb_ff <= o_wb_stb_nxt; - o_wb_wen_ff <= o_wb_wen_nxt; - o_wb_sel_ff <= o_wb_sel_nxt; - o_wb_dat_ff <= o_wb_dat_nxt; - o_wb_cti_ff <= o_wb_cti_nxt; - o_wb_adr_ff <= o_wb_adr_nxt; - cache_clean_req_ff <= cache_clean_req_nxt; - cache_inv_req_ff <= cache_inv_req_nxt; - adr_ctr_ff <= adr_ctr_nxt; - state_ff <= state_nxt; - buf_ff[0] <= buf_nxt[0]; - buf_ff[1] <= buf_nxt[1]; - buf_ff[2] <= buf_nxt[2]; - buf_ff[3] <= buf_nxt[3]; - end -end - -/* Combo block */ -always @* -begin - /* Default values */ - state_nxt = state_ff; - adr_ctr_nxt = adr_ctr_ff; - o_wb_cyc_nxt = o_wb_cyc_ff; - o_wb_stb_nxt = o_wb_stb_ff; - o_wb_adr_nxt = o_wb_adr_ff; - o_wb_dat_nxt = o_wb_dat_ff; - o_wb_cti_nxt = o_wb_cti_ff; - o_wb_wen_nxt = o_wb_wen_ff; - o_wb_sel_nxt = o_wb_sel_ff; - cache_clean_req_nxt = cache_clean_req_ff; - cache_inv_req_nxt = cache_clean_req_ff; - o_fsr = 0; - o_far = 0; - o_cache_tag = 0; - o_cache_inv_done = 0; - o_cache_clean_done = 0; - o_cache_tag_dirty = 0; - o_cache_tag_wr_en = 0; - o_cache_line = 0; - o_cache_line_ben = 0; - o_dat = 0; - o_ack = 0; - o_err = 0; - buf_nxt[0] = buf_ff[0]; - buf_nxt[1] = buf_ff[1]; - buf_nxt[2] = buf_ff[2]; - buf_nxt[3] = buf_ff[3]; - hit = 0; - - case(state_ff) - - IDLE: - begin - kill_access; - - if ( i_cache_inv ) - begin - o_ack = 1'd0; - state_nxt = INVALIDATE; - end - else if ( i_cache_clean ) - begin - o_ack = 1'd0; - state_nxt = CLEAN; - end - else if ( i_fault ) - begin - /* MMU access fault. */ - o_err = 1'd1; - o_ack = 1'd1; - o_fsr = i_fsr; - o_far = i_far; - end - else if ( i_busy ) - begin - /* Wait it out */ - end - else if ( i_rd || i_wr ) - begin - if ( i_cacheable && i_cache_en ) - begin - case ({cache_cmp,i_cache_tag_valid}) - - 2'b11: /* Cache hit */ - begin - if ( i_rd ) /* Read request. */ - begin - /* - * Accelerate performance - * Read throughput at 80MHz - * clock is 80M operations per - * second (Hit). - */ - o_dat = adapt_cache_data(i_address[3:2], i_cache_line); - hit = 1'd1; - o_ack = 1'd1; - end - else if ( i_wr ) /* Write request */ - begin - state_nxt = REFRESH_1; - o_ack = 1'd0; - - /* - * Each write to cache takes - * 3 cycles. Write throuput at - * 80MHz is 26.6M operations per - * second (Hit). - */ - o_cache_line = - {i_din,i_din,i_din,i_din}; - - o_cache_line_ben = ben_comp ( i_address[3:2], i_ben ); - - /* Write to tag and also write out physical address. */ - o_cache_tag_wr_en = 1'd1; - o_cache_tag[`CACHE_TAG__TAG] = i_address[`VA__CACHE_TAG]; - o_cache_tag_dirty = 1'd1; - o_cache_tag[`CACHE_TAG__PA] = i_phy_addr >> 4; - - - end - end - - 2'b01: /* Unrelated tag, possibly dirty. */ - begin - /* CPU should wait */ - o_ack = 1'd0; - - if ( cache_dirty ) - begin - /* Set up counter */ - adr_ctr_nxt = 0; - - /* Clean a single cache line */ - state_nxt = CLEAN_SINGLE; - end - else if ( i_rd | i_wr ) - begin - /* Set up counter */ - adr_ctr_nxt = 0; - - /* Fetch a single cache line */ - state_nxt = FETCH_SINGLE; - end - end - - default: /* Need to generate a new tag. */ - begin - /* CPU should wait. */ - o_ack = 1'd0; - - /* Set up counter */ - adr_ctr_nxt = 0; - - /* Fetch a single cache line */ - state_nxt = FETCH_SINGLE; - end - endcase - end - else /* Decidedly non cacheable. */ - begin - state_nxt = UNCACHEABLE; - o_ack = 1'd0; /* Wait...*/ - o_wb_stb_nxt = 1'd1; - o_wb_cyc_nxt = 1'd1; - o_wb_adr_nxt = i_phy_addr; - o_wb_dat_nxt = i_din; - o_wb_wen_nxt = i_wr; - o_wb_sel_nxt = i_ben; // Was i_wr ? i_ben : 4'b1111 - o_wb_cti_nxt = CTI_CLASSIC; - end - end - end - - UNCACHEABLE: /* Uncacheable reads and writes definitely go through this. */ - begin - if ( i_wb_ack ) - begin - o_dat = i_wb_dat; - o_ack = 1'd1; - state_nxt = IDLE; - kill_access; - end - end - - REFRESH_1: /* A single wait state is needed to handle B2B write-read */ - begin - kill_access; - state_nxt = REFRESH; - o_ack = 1'd0; - end - - CLEAN_SINGLE: /* Clean single cache line */ - begin - o_ack = 1'd0; - - /* Generate address */ - adr_ctr_nxt = adr_ctr_ff + (o_wb_stb_ff && i_wb_ack); - - if ( adr_ctr_nxt <= 3 ) - begin - /* Sync up with memory. Use PA in cache tag itself. */ - wb_prpr_write( clean_single_d (i_cache_line, adr_ctr_nxt), - {i_cache_tag[`CACHE_TAG__PA], 4'd0} + (adr_ctr_nxt << 2), - adr_ctr_nxt != 3 ? CTI_BURST : CTI_EOB, 4'b1111); - end - else - begin - /* Move to wait state */ - kill_access; - state_nxt = REFRESH_1; - - /* Update tag. Remove dirty bit. */ - o_cache_tag_wr_en = 1'd1; // Implicitly sets valid (redundant). - o_cache_tag[`CACHE_TAG__TAG] = i_cache_tag[`VA__CACHE_TAG]; // Preserve. - o_cache_tag_dirty = 1'd0; - o_cache_tag[`CACHE_TAG__PA] = i_cache_tag[`CACHE_TAG__PA]; // Preserve. - end - end - - FETCH_SINGLE: /* Fetch a single cache line */ - begin - - o_ack = 1'd0; - - /* Generate address */ - adr_ctr_nxt = adr_ctr_ff + (o_wb_stb_ff && i_wb_ack); - - /* Write to buffer */ - buf_nxt[adr_ctr_ff] = i_wb_ack ? i_wb_dat : buf_ff[adr_ctr_ff]; - - /* Manipulate buffer as needed */ - if ( i_wr ) - begin - buf_nxt[i_address[3:2]][7:0] = i_ben[0] ? i_din[7:0] : buf_nxt[i_address[3:2]][7:0]; - buf_nxt[i_address[3:2]][15:8] = i_ben[1] ? i_din[15:8] : buf_nxt[i_address[3:2]][15:8]; - buf_nxt[i_address[3:2]][23:16] = i_ben[2] ? i_din[23:16] : buf_nxt[i_address[3:2]][23:16]; - buf_nxt[i_address[3:2]][31:24] = i_ben[3] ? i_din[31:24] : buf_nxt[i_address[3:2]][31:24]; - end - - if ( adr_ctr_nxt <= 3 ) - begin - - /* Fetch line from memory */ - wb_prpr_read({i_phy_addr[31:4], 4'd0} + (adr_ctr_nxt << 2), - adr_ctr_nxt != 3 ? CTI_BURST : CTI_EOB); - end - else - begin - - /* Update cache */ - o_cache_line = {buf_nxt[3], buf_ff[2], buf_ff[1], buf_ff[0]}; - o_cache_line_ben = 16'b1111111111111111; - - /* Update tag. Remove dirty and set valid */ - o_cache_tag_wr_en = 1'd1; // Implicitly sets valid. - o_cache_tag[`CACHE_TAG__TAG] = i_address[`VA__CACHE_TAG]; - o_cache_tag[`CACHE_TAG__PA] = i_phy_addr >> 4; - o_cache_tag_dirty = !i_wr ? 1'd0 : 1'd1; // BUG FIX. - - /* Move to wait state */ - kill_access; - state_nxt = REFRESH_1; - end - end - - REFRESH: /* One extra cycle for cache and tag to update. */ - begin - kill_access; - o_ack = i_wr && cache_cmp; - state_nxt = IDLE; - end - - INVALIDATE: /* Invalidate the cache - Almost Single Cycle */ - begin - cache_inv_req_nxt = 1'd1; - cache_clean_req_nxt = 1'd0; - - if ( i_cache_inv_done ) - begin - cache_inv_req_nxt = 1'd0; - state_nxt = IDLE; - o_cache_inv_done = 1'd1; - end - end - - CLEAN: /* Force cache to clean itself */ - begin - cache_clean_req_nxt = 1'd1; - cache_inv_req_nxt = 1'd0; - - if ( i_cache_clean_done ) - begin - cache_clean_req_nxt = 1'd0; - state_nxt = IDLE; - o_cache_clean_done = 1'd1; - end - end - - endcase -end - -// ---------------------------------------------------------------------------- -// Tasks and functions. -// ---------------------------------------------------------------------------- - -function [31:0] adapt_cache_data -(input [1:0] shift, input [127:0] cd); -begin: blk1 - reg [31:0] shamt; - shamt = shift << 5; - adapt_cache_data = cd >> shamt; -end -endfunction - -function [15:0] ben_comp ( input [1:0] shift, input [3:0] bv ); -begin:fblk2 - reg [31:0] shamt; - shamt = shift << 2; - ben_comp = bv << shamt; -end -endfunction - -function [31:0] clean_single_d ( input [127:0] cl, input [31:0] sh ); -reg [31:0] shamt; -begin - shamt = sh << 5; - clean_single_d = cl >> shamt; // Select specific 32-bit. -end -endfunction - -/* Function to generate Wishbone read signals. */ -task wb_prpr_read; -input [31:0] i_address; -input [2:0] i_cti; -begin - o_wb_cyc_nxt = 1'd1; - o_wb_stb_nxt = 1'd1; - o_wb_wen_nxt = 1'd0; - o_wb_sel_nxt = 4'b1111; - o_wb_adr_nxt = i_address; - o_wb_cti_nxt = i_cti; - o_wb_dat_nxt = 0; -end -endtask - -/* Function to generate Wishbone write signals */ -task wb_prpr_write; -input [31:0] i_data; -input [31:0] i_address; -input [2:0] i_cti; -input [3:0] i_ben; -begin - o_wb_cyc_nxt = 1'd1; - o_wb_stb_nxt = 1'd1; - o_wb_wen_nxt = 1'd1; - o_wb_sel_nxt = i_ben; - o_wb_adr_nxt = i_address; - o_wb_cti_nxt = i_cti; - o_wb_dat_nxt = i_data; -end -endtask - -/* Disables Wishbone */ -task kill_access; -begin - o_wb_cyc_nxt = 0; - o_wb_stb_nxt = 0; - o_wb_wen_nxt = 0; - o_wb_adr_nxt = 0; - o_wb_dat_nxt = 0; - o_wb_sel_nxt = 0; - o_wb_cti_nxt = CTI_CLASSIC; -end -endtask - -// ---------------------------------------------------------------------------- - -wire [31:0] buf0_ff, buf1_ff, buf2_ff; - -assign buf0_ff = buf_ff[0]; -assign buf1_ff = buf_ff[1]; -assign buf2_ff = buf_ff[2]; - -wire [31:0] buf3_ff = buf_ff[3]; -wire [31:0] buf0_nxt = buf_nxt[0]; -wire [31:0] buf1_nxt = buf_nxt[1]; -wire [31:0] buf2_nxt = buf_nxt[2]; -wire [31:0] buf3_nxt = buf_nxt[3]; - -wire [31:0] dbg_addr_tag = i_address[`VA__CACHE_TAG]; -wire [31:0] dbg_addr_pa = i_phy_addr >> 4; -wire [31:0] dbg_ct_tag = o_cache_tag[`CACHE_TAG__TAG]; -wire [31:0] dbg_ct_pa = o_cache_tag[`CACHE_TAG__PA]; - -endmodule // zap_cache_fsm - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// END OF FILE -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_shifter_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_shifter_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_shifter_main.v (nonexistent) @@ -1,405 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -// -- The ZAP shift unit. Apart from shift, it does value restoration and -// -- multiplication. Value restoration is needed since the ALU (Shift+Op) is -// -- pipelined and we want back to back instructions to execute correctly without -// -- losing throughput. Note that there are 3 execution pathways in this unit -// -- but a given time, only one pathway may be active. The 3 execution pathways -// -- are: shifter, multiplier, value feedback network. -// -- -// ---------------------------------------------------------------------------- - - -`default_nettype none -module zap_shifter_main -#( - parameter PHY_REGS = 46, - parameter ALU_OPS = 32, - parameter SHIFT_OPS = 5 -) -( - // For debug - input wire [64*8-1:0] i_decompile, - output reg [64*8-1:0] o_decompile, - - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // PC - input wire [31:0] i_pc_ff, - output reg [31:0] o_pc_ff, - - // Taken. - input wire [1:0] i_taken_ff, - output reg [1:0] o_taken_ff, - - // Stall and clear. Hi to low priority. - input wire i_clear_from_writeback, // | High Priority. - input wire i_data_stall, // | - input wire i_clear_from_alu, // V Low Priority. - - // Next CPSR and FF CPSR. - input wire [31:0] i_cpsr_nxt, i_cpsr_ff, - - // - // Things from Issue. Please see issue stage for signal details. - // - - input wire [3:0] i_condition_code_ff, - input wire [$clog2(PHY_REGS )-1:0] i_destination_index_ff, - input wire [$clog2(ALU_OPS)-1:0] i_alu_operation_ff, - input wire [$clog2(SHIFT_OPS)-1:0] i_shift_operation_ff, - input wire i_flag_update_ff, - - input wire [$clog2(PHY_REGS )-1:0] i_mem_srcdest_index_ff, - input wire i_mem_load_ff, - input wire i_mem_store_ff, - input wire i_mem_pre_index_ff, - input wire i_mem_unsigned_byte_enable_ff, - input wire i_mem_signed_byte_enable_ff, - input wire i_mem_signed_halfword_enable_ff, - input wire i_mem_unsigned_halfword_enable_ff, - input wire i_mem_translate_ff, - - input wire i_irq_ff, - input wire i_fiq_ff, - input wire i_abt_ff, - input wire i_swi_ff, - - // Indices/immediates enter here. - input wire [32:0] i_alu_source_ff, - input wire i_alu_dav_nxt, - input wire [32:0] i_shift_source_ff, - - // Values are obtained here. - input wire [31:0] i_alu_source_value_ff, - input wire [31:0] i_shift_source_value_ff, - input wire [31:0] i_shift_length_value_ff, - input wire [31:0] i_mem_srcdest_value_ff, // This too has to be resolved. - // For stores. - - // The PC value. - input wire [31:0] i_pc_plus_8_ff, - - // Shifter disable indicator. In the next stage, the output - // will bypass the shifter. Not actually bypass it but will - // go to the ALU value corrector unit via a MUX. - input wire i_disable_shifter_ff, - - // undefined instr. - input wire i_und_ff, - output reg o_und_ff, - - // Value from ALU for resolver. - input wire [31:0] i_alu_value_nxt, - - // Force 32. - input wire i_force32align_ff, - output reg o_force32align_ff, - - // ARM <-> Compressed switch indicator. - input wire i_switch_ff, - output reg o_switch_ff, - - // - // Outputs. - // - - // Specific to this stage. - output reg [31:0] o_mem_srcdest_value_ff, - output reg [31:0] o_alu_source_value_ff, - output reg [31:0] o_shifted_source_value_ff, - output reg o_shift_carry_ff, - output reg o_nozero_ff, - - // Send all other outputs. - - // PC+8 - output reg [31:0] o_pc_plus_8_ff, - - // Interrupts. - output reg o_irq_ff, - output reg o_fiq_ff, - output reg o_abt_ff, - output reg o_swi_ff, - - // Memory related outputs. - output reg [$clog2(PHY_REGS )-1:0] o_mem_srcdest_index_ff, - output reg o_mem_load_ff, - output reg o_mem_store_ff, - output reg o_mem_pre_index_ff, - output reg o_mem_unsigned_byte_enable_ff, - output reg o_mem_signed_byte_enable_ff, - output reg o_mem_signed_halfword_enable_ff, - output reg o_mem_unsigned_halfword_enable_ff, - output reg o_mem_translate_ff, - - // Other stuff. - output reg [3:0] o_condition_code_ff, - output reg [$clog2(PHY_REGS )-1:0] o_destination_index_ff, - output reg [$clog2(ALU_OPS)-1:0] o_alu_operation_ff, - output reg o_flag_update_ff, - - // Stall from shifter. - output wire o_stall_from_shifter -); - -/////////////////////////////////////////////////////////////////////////////// - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -wire nozero_nxt; -wire [31:0] shout; -wire shcarry; -reg [31:0] mem_srcdest_value; -reg [31:0] rm, rn; -reg shift_carry_nxt; -wire shifter_enabled = !i_disable_shifter_ff; - -wire [31:0] mult_out; - -/////////////////////////////////////////////////////////////////////////////// - -// The MAC unit. -zap_shifter_multiply -#( - .PHY_REGS(PHY_REGS), - .ALU_OPS(ALU_OPS) -) -u_zap_multiply -( - .i_clk(i_clk), - .i_reset(i_reset), - - .i_data_stall(i_data_stall), - .i_clear_from_writeback(i_clear_from_writeback), - .i_clear_from_alu(i_clear_from_alu), - - .i_alu_operation_ff(i_alu_operation_ff), - - .i_cc_satisfied (i_condition_code_ff == 4'd15 ? 1'd0 : 1'd1), - // ( is_cc_satisfied ( i_condition_code_ff, i_cpsr_nxt[31:28] ) ) - // -- Causing timing issues in Xilinx ISE. - - .i_rm(i_alu_source_value_ff), - .i_rn(i_shift_length_value_ff), - .i_rs(i_shift_source_value_ff), // rm.rs + {rh,rn} - .i_rh(i_mem_srcdest_value_ff), - - .o_rd(mult_out), - .o_busy(o_stall_from_shifter), - .o_nozero(nozero_nxt) -); - -/////////////////////////////////////////////////////////////////////////////// - -task clear; // Clear the unit out. -begin - o_condition_code_ff <= NV; - o_irq_ff <= 0; - o_fiq_ff <= 0; - o_abt_ff <= 0; - o_swi_ff <= 0; - o_und_ff <= 0; -end -endtask - -/////////////////////////////////////////////////////////////////////////////// - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - clear; - end - else if ( i_clear_from_writeback ) - begin - clear; - end - else if ( i_data_stall ) - begin - // Preserve values. - end - else if ( i_clear_from_alu ) - begin - clear; - end - else - begin - o_condition_code_ff <= i_condition_code_ff; - o_destination_index_ff <= i_destination_index_ff; - o_alu_operation_ff <= (i_alu_operation_ff == UMLALL || - i_alu_operation_ff == UMLALH || - i_alu_operation_ff == SMLALL || - i_alu_operation_ff == SMLALH) ? - MOV : i_alu_operation_ff; - o_flag_update_ff <= i_flag_update_ff; - o_mem_srcdest_index_ff <= i_mem_srcdest_index_ff; - o_mem_load_ff <= i_mem_load_ff; - o_mem_store_ff <= i_mem_store_ff; - o_mem_pre_index_ff <= i_mem_pre_index_ff; - o_mem_unsigned_byte_enable_ff <= i_mem_unsigned_byte_enable_ff; - o_mem_signed_byte_enable_ff <= i_mem_signed_byte_enable_ff; - o_mem_signed_halfword_enable_ff <= i_mem_signed_halfword_enable_ff; - o_mem_unsigned_halfword_enable_ff <= i_mem_unsigned_halfword_enable_ff; - o_mem_translate_ff <= i_mem_translate_ff; - o_irq_ff <= i_irq_ff; - o_fiq_ff <= i_fiq_ff; - o_abt_ff <= i_abt_ff; - o_swi_ff <= i_swi_ff; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_mem_srcdest_value_ff <= mem_srcdest_value; - o_alu_source_value_ff <= rn; - o_shifted_source_value_ff <= rm; - o_shift_carry_ff <= shift_carry_nxt; - o_switch_ff <= i_switch_ff; - o_und_ff <= i_und_ff; - o_force32align_ff <= i_force32align_ff; - o_taken_ff <= i_taken_ff; - o_pc_ff <= i_pc_ff; - o_nozero_ff <= nozero_nxt; - - // For debug - o_decompile <= i_decompile; - end -end - -/////////////////////////////////////////////////////////////////////////////// - -// Barrel shifter. -zap_shift_shifter #( - .SHIFT_OPS(SHIFT_OPS) -) -U_SHIFT -( - .i_source ( i_shift_source_value_ff ), - .i_amount ( i_shift_length_value_ff[7:0] ), - .i_shift_type ( i_shift_operation_ff ), - .i_carry ( i_cpsr_ff[29] ), - .o_result ( shout ), - .o_carry ( shcarry ) -); - -/////////////////////////////////////////////////////////////////////////////// - -// Resolve conflict for ALU source value (rn) -always @* -begin - - rn = resolve_conflict ( i_alu_source_ff, i_alu_source_value_ff, - o_destination_index_ff, i_alu_value_nxt, i_alu_dav_nxt ); - - -end - -/////////////////////////////////////////////////////////////////////////////// - -// Resolve conflict for shifter source value. -always @* -begin - // If we issue a multiply. - if ( i_alu_operation_ff == UMLALL || i_alu_operation_ff == UMLALH || - i_alu_operation_ff == SMLALL || i_alu_operation_ff == SMLALH ) - begin - // Get result from multiplier. - rm = mult_out; - - // Carry is set to a MEANINGLESS value. Zero in this case. - shift_carry_nxt = 1'd0; - end - else if( shifter_enabled ) // Shifter enabled if valid shift is asked for. - begin - // Get result from shifter. - rm = shout; - - // Get carry from shifter - shift_carry_nxt = shcarry; - end - else - begin - // Resolve conflict. - rm = resolve_conflict ( i_shift_source_ff, i_shift_source_value_ff, - o_destination_index_ff, i_alu_value_nxt, i_alu_dav_nxt ); - - // Do not touch the carry. Get from _nxt for back2back execution. - shift_carry_nxt = i_cpsr_nxt[29]; - end -end - -/////////////////////////////////////////////////////////////////////////////// - -// Mem srcdest index. Used for -// stores. Resolve conflict. -always @* -begin - mem_srcdest_value = resolve_conflict ( i_mem_srcdest_index_ff, i_mem_srcdest_value_ff, - o_destination_index_ff, i_alu_value_nxt, i_alu_dav_nxt ); -end - -/////////////////////////////////////////////////////////////////////////////// - -// This will resolve conflicts for back to back instruction execution. -// The function entirely depends only on the inputs to the function. -function [31:0] resolve_conflict ( - input [32:0] index_from_issue, // Index from issue stage. Could have immed too. - input [31:0] value_from_issue, // Issue speculatively read value. - input [$clog2(PHY_REGS)-1:0] index_from_this_stage, // From shift (This) stage output flops. - input [31:0] result_from_alu, // From ALU output directly. - input result_from_alu_valid // Result from ALU is VALID. -); -begin - - if ( index_from_issue[32] == IMMED_EN ) - begin - resolve_conflict = index_from_issue[31:0]; - end - else if ( index_from_issue == PHY_PC ) - begin - resolve_conflict = i_pc_plus_8_ff; - end - else if ( index_from_this_stage == index_from_issue[$clog2(PHY_REGS)-1:0] && result_from_alu_valid ) - begin - resolve_conflict = result_from_alu; - end - else - begin - resolve_conflict = value_from_issue[31:0]; - end -end -endfunction - -/////////////////////////////////////////////////////////////////////////////// - -endmodule // zap_shifter_main.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_wb_merger.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_wb_merger.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_wb_merger.v (nonexistent) @@ -1,165 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Merges two Wishbone busses onto a single bus. One side can from the -- -// -- instruction cache while the other from data cache. This module can -- -// -- be used to connect any 2 generic Wishbone devices. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_wb_merger ( - -// Clock and reset -input wire i_clk, -input wire i_reset, - -// Wishbone bus 1 -input wire i_c_wb_stb, -input wire i_c_wb_cyc, -input wire i_c_wb_wen, -input wire [3:0] i_c_wb_sel, -input wire [31:0] i_c_wb_dat, -input wire [31:0] i_c_wb_adr, -input wire [2:0] i_c_wb_cti, -output reg o_c_wb_ack, - -// Wishbone bus 2 -input wire i_d_wb_stb, -input wire i_d_wb_cyc, -input wire i_d_wb_wen, -input wire [3:0] i_d_wb_sel, -input wire [31:0] i_d_wb_dat, -input wire [31:0] i_d_wb_adr, -input wire [2:0] i_d_wb_cti, -output reg o_d_wb_ack, - -// Common bus -output reg o_wb_cyc, -output reg o_wb_stb, -output reg o_wb_wen, -output reg [3:0] o_wb_sel, -output reg [31:0] o_wb_dat, -output reg [31:0] o_wb_adr, -output reg [2:0] o_wb_cti, -input wire i_wb_ack - -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" - -localparam CODE = 1'd0; -localparam DATA = 1'd1; - -reg sel_ff, sel_nxt; - -always @ (posedge i_clk) -begin - if ( i_reset ) - sel_ff <= CODE; - else - sel_ff <= sel_nxt; -end - -always @* -begin - if ( sel_ff == CODE ) - begin - o_c_wb_ack = i_wb_ack; - o_d_wb_ack = 1'd0; - end - else - begin - o_d_wb_ack = i_wb_ack; - o_c_wb_ack = 1'd0; - end -end - -always @* -begin - case(sel_ff) - CODE: - begin - if ( i_wb_ack && (o_wb_cti == CTI_CLASSIC || o_wb_cti == CTI_EOB) && i_d_wb_stb ) - sel_nxt = DATA; - else if ( !i_c_wb_stb && i_d_wb_stb ) - sel_nxt = DATA; - else - sel_nxt = sel_ff; - end - - DATA: - begin - if ( i_wb_ack && (o_wb_cti == CTI_CLASSIC || o_wb_cti == CTI_EOB) && i_c_wb_stb ) - sel_nxt = CODE; - else if ( i_c_wb_stb && !i_d_wb_stb ) - sel_nxt = CODE; - else - sel_nxt = sel_ff; - end - endcase -end - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - o_wb_cyc <= 0; - o_wb_stb <= 0; - o_wb_wen <= 0; - o_wb_sel <= 0; - o_wb_dat <= 0; - o_wb_adr <= 0; - o_wb_cti <= 0; - end - else if ( sel_nxt == CODE ) - begin - o_wb_cyc <= i_c_wb_cyc; - o_wb_stb <= i_c_wb_stb; - o_wb_wen <= i_c_wb_wen; - o_wb_sel <= i_c_wb_sel; - o_wb_dat <= i_c_wb_dat; - o_wb_adr <= i_c_wb_adr; - o_wb_cti <= i_c_wb_cti; - end - else - begin - o_wb_cyc <= i_d_wb_cyc; - o_wb_stb <= i_d_wb_stb; - o_wb_wen <= i_d_wb_wen; - o_wb_sel <= i_d_wb_sel; - o_wb_dat <= i_d_wb_dat; - o_wb_adr <= i_d_wb_adr; - o_wb_cti <= i_d_wb_cti; - end -end - -endmodule - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_memory_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_memory_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_memory_main.v (nonexistent) @@ -1,289 +0,0 @@ -// ------------------------------------------------------------------------------ -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- --------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ------------------------------------------------------------------------------ -// -- -- -// -- This stage merely acts as a buffer in between the ALU stage and the reg.-- -// -- file (i.e., writeback stage). 32-bit data received from the cache is -- -// -- is rotated appropriately here in case of byte reads or halfword reads. -- -// -- Otherwise, this stage is simply a buffer. -- -// -- -- -// ------------------------------------------------------------------------------ - -`default_nettype none -module zap_memory_main -#( - // Width of CPSR. - parameter FLAG_WDT = 32, - - // Number of physical registers. - parameter PHY_REGS = 46 -) -( - // Debug - input wire [64*8-1:0] i_decompile, - output reg [64*8-1:0] o_decompile, - - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // Pipeline control signals. - input wire i_clear_from_writeback, - input wire i_data_stall, - - // Memory stuff. - input wire i_mem_load_ff, - input wire [31:0] i_mem_address_ff, // Access Address. - - // Data read from memory. - input wire [31:0] i_mem_rd_data, - - // Memory fault transfer. i_mem_fault comes from the cache unit. - input wire i_mem_fault, // Fault in. - output reg o_mem_fault, // Fault out. - - // Data valid and buffered PC. - input wire i_dav_ff, - input wire [31:0] i_pc_plus_8_ff, - - // ALU value, flags,and where to write the value. - input wire [31:0] i_alu_result_ff, - input wire [FLAG_WDT-1:0] i_flags_ff, - input wire [$clog2(PHY_REGS)-1:0] i_destination_index_ff, - - // Interrupts. - input wire i_irq_ff, - input wire i_fiq_ff, - input wire i_instr_abort_ff, - input wire i_swi_ff, - - // Memory SRCDEST index. For loads, this tells the register file where - // to put the read data. Set to point to RAZ if invalid. - input wire [$clog2(PHY_REGS)-1:0] i_mem_srcdest_index_ff, - - // SRCDEST value. - input wire [31:0] i_mem_srcdest_value_ff, - - // Memory size and type. - input wire i_sbyte_ff, - i_ubyte_ff, - i_shalf_ff, - i_uhalf_ff, - - // Undefined instr. - input wire i_und_ff, - output reg o_und_ff, - - // ALU result and flags. - output reg [31:0] o_alu_result_ff, - output reg [FLAG_WDT-1:0] o_flags_ff, - - // Where to write ALU and memory read target register. - output reg [$clog2(PHY_REGS)-1:0] o_destination_index_ff, - - // Set to point to the RAZ register if invalid. - output reg [$clog2(PHY_REGS)-1:0] o_mem_srcdest_index_ff, - - // Outputs valid and PC buffer. - output reg o_dav_ff, - output reg [31:0] o_pc_plus_8_ff, - - // The whole interrupt signaling scheme. - output reg o_irq_ff, - output reg o_fiq_ff, - output reg o_swi_ff, - output reg o_instr_abort_ff, - - // Memory load information is passed down. - output reg o_mem_load_ff, - output reg [31:0] o_mem_rd_data -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -reg i_mem_load_ff2 ; -reg [31:0] i_mem_srcdest_value_ff2 ; -reg [31:0] i_mem_address_ff2 ; -reg i_sbyte_ff2 ; -reg i_ubyte_ff2 ; -reg i_shalf_ff2 ; -reg i_uhalf_ff2 ; -reg [31:0] mem_rd_data ; - -// Invalidates the outptus of this stage. -task clear; -begin - // Invalidate stage. - o_dav_ff <= 0; - - // Clear interrupts. - o_irq_ff <= 0; - o_fiq_ff <= 0; - o_swi_ff <= 0; - o_instr_abort_ff <= 0; - o_und_ff <= 0; - o_mem_fault <= 0; -end -endtask - -// On reset or on a clear from WB, we will disable the vectors -// in this unit. Else, we will just flop everything out. -always @ (posedge i_clk) -if ( i_reset ) -begin - clear; -end -else if ( i_clear_from_writeback ) -begin - clear; -end -else if ( i_data_stall ) -begin - // Stall unit. Outputs do not change. - o_dav_ff <= 1'd0; -end -else -begin - // Just flop everything out. - o_alu_result_ff <= i_alu_result_ff; - o_flags_ff <= i_flags_ff; - o_mem_srcdest_index_ff<= i_mem_srcdest_index_ff; - o_dav_ff <= i_dav_ff; - o_destination_index_ff<= i_destination_index_ff; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_irq_ff <= i_irq_ff; - o_fiq_ff <= i_fiq_ff; - o_swi_ff <= i_swi_ff; - o_instr_abort_ff <= i_instr_abort_ff; - o_mem_load_ff <= i_mem_load_ff; - o_und_ff <= i_und_ff; - o_mem_fault <= i_mem_fault; - mem_rd_data <= i_mem_rd_data; - - // Debug. - o_decompile <= i_decompile; -end - -// Manual Pipeline Retiming. -always @ (posedge i_clk) -begin - if ( !i_data_stall ) - begin - i_mem_load_ff2 <= i_mem_load_ff; - i_mem_srcdest_value_ff2 <= i_mem_srcdest_value_ff; - i_mem_address_ff2 <= i_mem_address_ff; - i_sbyte_ff2 <= i_sbyte_ff; - i_ubyte_ff2 <= i_ubyte_ff; - i_shalf_ff2 <= i_shalf_ff; - i_uhalf_ff2 <= i_uhalf_ff; - end -end - -always @* -o_mem_rd_data = transform((i_mem_load_ff2 ? mem_rd_data : - i_mem_srcdest_value_ff2), i_mem_address_ff2[1:0], - i_sbyte_ff2, i_ubyte_ff2, i_shalf_ff2, i_uhalf_ff2, - i_mem_load_ff2); - -// Memory always loads 32-bit to processor. -// We will rotate that here as we wish. - -function [31:0] transform ( - - // Data and address. - input [31:0] data, - input [1:0] address, - - // Memory access data type. - input sbyte, - input ubyte, - input shalf, - input uhalf, - - // Memory load. - input mem_load_ff -); -begin: transform_function - reg [31:0] d; // Data shorthand. - - transform = 32'd0; - d = data; - - // Unsigned byte. Take only lower byte. - if ( ubyte == 1'd1 ) - begin - case ( address[1:0] ) - 0: transform = (d >> 0) & 32'h000000ff; - 1: transform = (d >> 8) & 32'h000000ff; - 2: transform = (d >> 16) & 32'h000000ff; - 3: transform = (d >> 24) & 32'h000000ff; - endcase - end - // Signed byte. Sign extend lower byte. - else if ( sbyte == 1'd1 ) - begin - // Take lower byte. - case ( address[1:0] ) - 0: transform = (d >> 0) & 32'h000000ff; - 1: transform = (d >> 8) & 32'h000000ff; - 2: transform = (d >> 16) & 32'h000000ff; - 3: transform = (d >> 24) & 32'h000000ff; - endcase - - // Sign extend. - transform = $signed(transform[7:0]); - end - // Signed half word. Sign extend lower 16-bit. - else if ( shalf == 1'd1 ) - begin - case ( address[1] ) - 0: transform = (d >> 0) & 32'h0000ffff; - 1: transform = (d >> 16) & 32'h0000ffff; - endcase - - transform = $signed(transform[15:0]); - end - // Unsigned half word. Take only lower 16-bit. - else if ( uhalf == 1'd1 ) - begin - case ( address[1] ) - 0: transform = (d >> 0) & 32'h0000ffff; - 1: transform = (d >> 16) & 32'h0000ffff; - endcase - end - else // Default. Typically, a word. - begin - transform = data; - end - - // Override above computation if not a memory load. - if ( !mem_load_ff ) - begin - transform = data; // No memory load means pass data on. - end -end -endfunction - -endmodule -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_sync_fifo.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_sync_fifo.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_sync_fifo.v (nonexistent) @@ -1,163 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- This is a simple synchronous FIFO. -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -// FWFT means "First Word Fall Through". -module zap_sync_fifo #( - parameter WIDTH = 32, - parameter DEPTH = 32, - parameter FWFT = 1, - parameter PROVIDE_NXT_DATA = 0 -) -( - // Clock and reset - input wire i_clk, - input wire i_reset, - - // Flow control - input wire i_ack, - input wire i_wr_en, - - // Data busses - input wire [WIDTH-1:0] i_data, - output reg [WIDTH-1:0] o_data, - output reg [WIDTH-1:0] o_data_nxt, - - // Flags - output wire o_empty, - output wire o_full, - output wire o_empty_n, - output wire o_full_n, - output wire o_full_n_nxt -); - -// Xilinx ISE does not allow $CLOG2 in localparams. -parameter PTR_WDT = $clog2(DEPTH) + 32'd1; -parameter [PTR_WDT-1:0] DEFAULT = {PTR_WDT{1'd0}}; - -// Variables -reg [PTR_WDT-1:0] rptr_ff; -reg [PTR_WDT-1:0] rptr_nxt; -reg [PTR_WDT-1:0] wptr_ff; -reg empty, nempty; -reg full, nfull; -reg [PTR_WDT-1:0] wptr_nxt; -reg [WIDTH-1:0] mem [DEPTH-1:0]; -wire [WIDTH-1:0] dt; -reg [WIDTH-1:0] dt1; -reg sel_ff; -reg [WIDTH-1:0] bram_ff; -reg [WIDTH-1:0] dt_ff; - -// Assigns -assign o_empty = empty; -assign o_full = full; -assign o_empty_n = nempty; -assign o_full_n = nfull; -assign o_full_n_nxt = i_reset ? 1 : - !( ( wptr_nxt[PTR_WDT-2:0] == rptr_nxt[PTR_WDT-2:0] ) && - ( wptr_nxt != rptr_nxt ) ); - - -// FIFO write logic. -always @ (posedge i_clk) - if ( i_wr_en && !o_full ) - mem[wptr_ff[PTR_WDT-2:0]] <= i_data; - -// FIFO read logic -generate -begin:gb1 - if ( FWFT == 1 ) - begin:f1 - // Retimed output data compared to normal FIFO. - always @ (posedge i_clk) - begin - dt_ff <= i_data; - sel_ff <= ( i_wr_en && (wptr_ff == rptr_nxt) ); - bram_ff <= mem[rptr_nxt[PTR_WDT-2:0]]; - end - - // Output signal steering MUX. - always @* - begin - o_data = sel_ff ? dt_ff : bram_ff; - o_data_nxt = 0; // Tied off. - end - end - else - begin:f0 - always @ (posedge i_clk) - begin - if ( i_ack && nempty ) // Read request and not empty. - begin - o_data <= mem [ rptr_ff[PTR_WDT-2:0] ]; - end - end - - if ( PROVIDE_NXT_DATA ) - begin: f11 - always @ (*) - begin - if ( i_ack && nempty ) - o_data_nxt = mem [ rptr_ff[PTR_WDT-2:0] ]; - else - o_data_nxt = o_data; - end - end - else - begin: f22 - always @* o_data_nxt = 0; - end - end -end -endgenerate - -// Flip-flop update. -always @ (posedge i_clk) -begin - dt1 <= i_reset ? 0 : i_data; - rptr_ff <= i_reset ? 0 : rptr_nxt; - wptr_ff <= i_reset ? 0 : wptr_nxt; - empty <= i_reset ? 1 : ( wptr_nxt == rptr_nxt ); - nempty <= i_reset ? 0 : ( wptr_nxt != rptr_nxt ); - nfull <= o_full_n_nxt; - full <= !o_full_n_nxt; -end - -// Pointer updates. -always @* -begin - wptr_nxt = wptr_ff + (i_wr_en && !o_full); - rptr_nxt = rptr_ff + (i_ack && !o_empty); -end - -endmodule // zap_sync_fifo - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_functions.vh =================================================================== --- zap/trunk/src/rtl/cpu/zap_functions.vh (revision 57) +++ zap/trunk/src/rtl/cpu/zap_functions.vh (nonexistent) @@ -1,195 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- - -// -// Function to generate clog2. $clog2 used instead in most places. -// -function [31:0] zap_clog2 ( input [31:0] x ); - for(zap_clog2 = 0 ; 2**zap_clog2 < x ; zap_clog2 = zap_clog2 + 1) - begin - // Some compilers do not support empty loops. - end -endfunction - -// ---------------------------------------------------------------------------- - -// -// Function to check if condition is satisfied for instruction -// execution. Returns 1 if satisfied, 0 if not. -// - -function is_cc_satisfied -( - input [3:0] cc, // 31:28 of the instruction. - input [3:0] fl // CPSR flags. -); -reg ok,n,z,c,v; -begin: blk1 - {n,z,c,v} = fl; - - case(cc) - EQ: ok = z; - NE: ok = !z; - CS: ok = c; - CC: ok = !c; - MI: ok = n; - PL: ok = !n; - VS: ok = v; - VC: ok = !v; - HI: ok = c && !z; - LS: ok = !c || z; - GE: ok = (n == v); - LT: ok = (n != v); - GT: ok = (n == v) && !z; - LE: ok = (n != v) || z; - AL: ok = 1'd1; - NV: ok = 1'd0; - endcase - - is_cc_satisfied = ok; -end -endfunction - -// ---------------------------------------------------------------------------- - - -// ---------------------------------------------------------------------------- - -// -// Translate function. -// -// -// Used to implement ARM modes. The register file is basically a flat array -// of registers. Based on mode, we select some of those to implement banking. -// - -function [5:0] translate ( - - input [5:0] index, // Requested instruction index. - input [4:0] cpu_mode // Current CPU mode. - -); -begin - translate = index; // Avoid latch inference. - - // User/System mode assignments. - case ( index ) - 0: translate = PHY_USR_R0; - 1: translate = PHY_USR_R1; - 2: translate = PHY_USR_R2; - 3: translate = PHY_USR_R3; - 4: translate = PHY_USR_R4; - 5: translate = PHY_USR_R5; - 6: translate = PHY_USR_R6; - 7: translate = PHY_USR_R7; - 8: translate = PHY_USR_R8; - 9: translate = PHY_USR_R9; - 10: translate = PHY_USR_R10; - 11: translate = PHY_USR_R11; - 12: translate = PHY_USR_R12; - 13: translate = PHY_USR_R13; - 14: translate = PHY_USR_R14; - 15: translate = PHY_PC; - - RAZ_REGISTER: translate = PHY_RAZ_REGISTER; - ARCH_CPSR: translate = PHY_CPSR; - ARCH_CURR_SPSR: translate = PHY_CPSR; - - // USR2 registers are looped back to USER registers. - ARCH_USR2_R8: translate = PHY_USR_R8; - ARCH_USR2_R9: translate = PHY_USR_R9; - ARCH_USR2_R10: translate = PHY_USR_R10; - ARCH_USR2_R11: translate = PHY_USR_R11; - ARCH_USR2_R12: translate = PHY_USR_R12; - ARCH_USR2_R13: translate = PHY_USR_R13; - ARCH_USR2_R14: translate = PHY_USR_R14; - - ARCH_DUMMY_REG0:translate = PHY_DUMMY_REG0; - ARCH_DUMMY_REG1:translate = PHY_DUMMY_REG1; - endcase - - // Override per specific mode. - case ( cpu_mode ) - FIQ: - begin - case ( index ) - 8: translate = PHY_FIQ_R8; - 9: translate = PHY_FIQ_R9; - 10: translate = PHY_FIQ_R10; - 11: translate = PHY_FIQ_R11; - 12: translate = PHY_FIQ_R12; - 13: translate = PHY_FIQ_R13; - 14: translate = PHY_FIQ_R14; - ARCH_CURR_SPSR: translate = PHY_FIQ_SPSR; - endcase - end - - IRQ: - begin - case ( index ) - 13: translate = PHY_IRQ_R13; - 14: translate = PHY_IRQ_R14; - ARCH_CURR_SPSR: translate = PHY_IRQ_SPSR; - endcase - end - - ABT: - begin - case ( index ) - 13: translate = PHY_ABT_R13; - 14: translate = PHY_ABT_R14; - ARCH_CURR_SPSR: translate = PHY_ABT_SPSR; - endcase - end - - UND: - begin - case ( index ) - 13: translate = PHY_UND_R13; - 14: translate = PHY_UND_R14; - ARCH_CURR_SPSR: translate = PHY_UND_SPSR; - endcase - end - - SVC: - begin - case ( index ) - 13: translate = PHY_SVC_R13; - 14: translate = PHY_SVC_R14; - ARCH_CURR_SPSR: translate = PHY_SVC_SPSR; - endcase - end - - default: // To avoid lint warnings. - begin - end - endcase -end -endfunction - -// ---------------------------------------------------------------------------- - - - Index: zap/trunk/src/rtl/cpu/zap_tlb.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_tlb.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_tlb.v (nonexistent) @@ -1,243 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -// TLB management unit for the ZAP processor. The TLB units use single cycle -- -// clearing memories since TLBs are shallow. -- -// -- -// ----------------------------------------------------------------------------- - -`default_nettype none -module zap_tlb #( - -parameter LPAGE_TLB_ENTRIES = 8, -parameter SPAGE_TLB_ENTRIES = 8, -parameter SECTION_TLB_ENTRIES = 8 - -) ( - -// Clock and reset. -input wire i_clk, -input wire i_reset, - -// From cache FSM (processor) -input wire [31:0] i_address, -input wire [31:0] i_address_nxt, -input wire i_rd, -input wire i_wr, - -// CPSR, SR, DAC register. -input wire [31:0] i_cpsr, -input wire [1:0] i_sr, -input wire [31:0] i_dac_reg, -input wire [31:0] i_baddr, - -// From CP15. -input wire i_mmu_en, -input wire i_inv, - -// To cache FSM. -output wire [31:0] o_phy_addr, -output wire [7:0] o_fsr, -output wire [31:0] o_far, -output wire o_fault, -output wire o_cacheable, -output wire o_busy, - -// Wishbone memory interface - Needs to go through some OR gates. -output wire o_wb_stb_nxt, -output wire o_wb_cyc_nxt, -output wire [31:0] o_wb_adr_nxt, -output wire o_wb_wen_nxt, -output wire [3:0] o_wb_sel_nxt, -input wire [31:0] i_wb_dat, -output wire [31:0] o_wb_dat_nxt, -input wire i_wb_ack - -); - -// ---------------------------------------------------------------------------- - -assign o_wb_dat_nxt = 32'd0; - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -wire [`SECTION_TLB_WDT-1:0] setlb_wdata, setlb_rdata; -wire [`LPAGE_TLB_WDT-1:0] lptlb_wdata, lptlb_rdata; -wire [`SPAGE_TLB_WDT-1:0] sptlb_wdata, sptlb_rdata; -wire sptlb_wen, lptlb_wen, setlb_wen; -wire sptlb_ren, lptlb_ren, setlb_ren; -wire walk; -wire [7:0] fsr; -wire [31:0] far; -wire cacheable; -wire [31:0] phy_addr; - -// ---------------------------------------------------------------------------- - -zap_mem_inv_block #(.WIDTH(`SECTION_TLB_WDT), .DEPTH(SECTION_TLB_ENTRIES)) -u_section_tlb ( -.i_clk (i_clk), -.i_reset (i_reset), - -.i_wdata (setlb_wdata), -.i_wen (setlb_wen), -.i_ren (1'd1), - -.i_inv (i_inv | !i_mmu_en), - -.i_raddr (i_address_nxt[`VA__SECTION_INDEX]), -.i_waddr (i_address[`VA__SECTION_INDEX]), - -.o_rdata (setlb_rdata), -.o_rdav (setlb_ren) -); - -// ---------------------------------------------------------------------------- - -zap_mem_inv_block #(.WIDTH(`LPAGE_TLB_WDT), .DEPTH(LPAGE_TLB_ENTRIES)) -u_lpage_tlb ( -.i_clk (i_clk), -.i_reset (i_reset), - -.i_wdata (lptlb_wdata), -.i_wen (lptlb_wen), -.i_ren (1'd1), - -.i_inv (i_inv | !i_mmu_en), - -.i_raddr (i_address_nxt[`VA__LPAGE_INDEX]), -.i_waddr (i_address[`VA__LPAGE_INDEX]), - -.o_rdata (lptlb_rdata), -.o_rdav (lptlb_ren) -); - -// ---------------------------------------------------------------------------- - -zap_mem_inv_block #(.WIDTH(`SPAGE_TLB_WDT), .DEPTH(SPAGE_TLB_ENTRIES)) -u_spage_tlb ( -.i_clk (i_clk), -.i_reset (i_reset), - -.i_wdata (sptlb_wdata), -.i_wen (sptlb_wen), -.i_ren (1'd1), - -.i_inv (i_inv | !i_mmu_en), - -.i_raddr (i_address_nxt[`VA__SPAGE_INDEX]), -.i_waddr (i_address[`VA__SPAGE_INDEX]), - -.o_rdata (sptlb_rdata), -.o_rdav (sptlb_ren) -); - -// ---------------------------------------------------------------------------- - -zap_tlb_check #( -.LPAGE_TLB_ENTRIES(LPAGE_TLB_ENTRIES), -.SPAGE_TLB_ENTRIES(SPAGE_TLB_ENTRIES), -.SECTION_TLB_ENTRIES(SECTION_TLB_ENTRIES)) -u_zap_tlb_check ( - -.i_mmu_en (i_mmu_en), -.i_va (i_address), -.i_rd (i_rd), -.i_wr (i_wr), - -.i_cpsr (i_cpsr), -.i_sr (i_sr), -.i_dac_reg (i_dac_reg), - -.i_sptlb_rdata (sptlb_rdata), -.i_sptlb_rdav (sptlb_ren), - -.i_lptlb_rdata (lptlb_rdata), -.i_lptlb_rdav (lptlb_ren), - -.i_setlb_rdata (setlb_rdata), -.i_setlb_rdav (setlb_ren), - -.o_walk (walk), -.o_fsr (fsr), -.o_far (far), -.o_cacheable (cacheable), -.o_phy_addr (phy_addr) - -); - -// ---------------------------------------------------------------------------- - -zap_tlb_fsm #( -.LPAGE_TLB_ENTRIES (LPAGE_TLB_ENTRIES), -.SPAGE_TLB_ENTRIES (SPAGE_TLB_ENTRIES), -.SECTION_TLB_ENTRIES (SECTION_TLB_ENTRIES) -) u_zap_tlb_fsm ( -.o_unused_ok (), // UNCONNECTED. For lint. -.i_clk (i_clk), -.i_reset (i_reset), -.i_mmu_en (i_mmu_en), -.i_baddr (i_baddr), -.i_address (i_address), -.i_walk (walk), -.i_fsr (fsr), -.i_far (far), -.i_cacheable (cacheable), -.i_phy_addr (phy_addr), - -.o_fsr (o_fsr), -.o_far (o_far), -.o_fault (o_fault), -.o_phy_addr (o_phy_addr), -.o_cacheable (o_cacheable), -.o_busy (o_busy), - -.o_setlb_wdata (setlb_wdata), -.o_setlb_wen (setlb_wen), - -.o_sptlb_wdata (sptlb_wdata), -.o_sptlb_wen (sptlb_wen), - -.o_lptlb_wdata (lptlb_wdata), -.o_lptlb_wen (lptlb_wen), - -.o_wb_cyc (), -.o_wb_stb (), -.o_wb_wen (o_wb_wen_nxt), -.o_wb_sel (), -.o_wb_adr (), -.i_wb_dat (i_wb_dat), -.i_wb_ack (i_wb_ack), - -.o_wb_sel_nxt (o_wb_sel_nxt), -.o_wb_cyc_nxt (o_wb_cyc_nxt), -.o_wb_stb_nxt (o_wb_stb_nxt), -.o_wb_adr_nxt (o_wb_adr_nxt) -); - -// ---------------------------------------------------------------------------- - -endmodule -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_decode.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_decode.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_decode.v (nonexistent) @@ -1,694 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This module performs core ARM instruction decoding by translating ARM -- -// -- instructions into an internal long format that can be processed by core -- -// -- logic. Note that the predecode stage must change the 32-bit instr. to -- -// -- 36-bit before feeding it into this unit. -- -// -- -- -// ----------------------------------------------------------------------------- - - -`default_nettype none - -module zap_decode ( - -i_irq, // IRQ request from previous stage. -i_fiq, // FIQ request from previous stage. -i_abt, // Code abort flagged from previous stage. - -// Instruction input from pre-decode. -i_instruction, -i_instruction_valid, - -// -// CPU mode from active CPSR. Required to prevent CPSR change on MSR -// instruction in USR mode. -// -i_cpsr_ff_mode, - -// -// Bits related to decoded instruction... -// - -o_condition_code, // 4-bit CC. -o_destination_index, // Destination register. -o_alu_source, // ALU source register. -o_alu_operation, // ALU operation to be performed. -o_shift_source, // Register to be treated as input to shifter. -o_shift_operation, // Shift operation to perform. -o_shift_length, // Length of the shift operation. -o_flag_update, // 1 means flags must be updated. - -// Memory related. -o_mem_srcdest_index, // Data register. -o_mem_load, // Load operation. -o_mem_store, // Store operation. -o_mem_pre_index, // Pre-Index. -o_mem_unsigned_byte_enable, // Access treated as uint8_t. -o_mem_signed_byte_enable, // Access treated as int8_t. -o_mem_signed_halfword_enable, // Access treated as int16_t. -o_mem_unsigned_halfword_enable, // Access treated as uint16_t. -o_mem_translate, // Force user view of memory. - -o_und, // Declare as undecodable. -o_switch // Switch between ARM and Thumb may be needed if this is 1. - -); - -// ---------------------------------------------------------------------------- - - // Number of architectural registers. - parameter ARCH_REGS = 32; - - // Number of opcodes. - parameter ALU_OPS = 32; - - // Number of shift operations. - parameter SHIFT_OPS = 6; - - - // I/O Ports. - input wire i_irq, i_fiq, i_abt; - input wire [35:0] i_instruction; - input wire i_instruction_valid; - input wire [4:0] i_cpsr_ff_mode; - output reg [3:0] o_condition_code; - output reg [$clog2(ARCH_REGS)-1:0] o_destination_index; - output reg [32:0] o_alu_source; - output reg [$clog2(ALU_OPS)-1:0] o_alu_operation; - output reg [32:0] o_shift_source; - output reg [$clog2(SHIFT_OPS)-1:0] o_shift_operation; - output reg [32:0] o_shift_length; - output reg o_flag_update; - output reg [$clog2(ARCH_REGS)-1:0] o_mem_srcdest_index; - output reg o_mem_load; - output reg o_mem_store; - output reg o_mem_pre_index; - output reg o_mem_unsigned_byte_enable; - output reg o_mem_signed_byte_enable; - output reg o_mem_signed_halfword_enable; - output reg o_mem_unsigned_halfword_enable; - output reg o_mem_translate; - output reg o_und; - output reg o_switch; - -// ---------------------------------------------------------------------------- - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -// Related to memory operations. -localparam [1:0] SIGNED_BYTE = 2'd0; -localparam [1:0] UNSIGNED_HALF_WORD = 2'd1; -localparam [1:0] SIGNED_HALF_WORD = 2'd2; - -// ---------------------------------------------------------------------------- - -always @* -begin: mainBlk1 - // If an unrecognized instruction enters this, the output - // signals an NV state i.e., invalid. - o_condition_code = NV; - o_destination_index = 0; - o_alu_source = 0; - o_alu_operation = 0; - o_shift_source = 0; - o_shift_operation = 0; - o_shift_length = 0; - o_flag_update = 0; - o_mem_srcdest_index = RAZ_REGISTER; - o_mem_load = 0; - o_mem_store = 0; - o_mem_translate = 0; - o_mem_pre_index = 0; - o_mem_unsigned_byte_enable = 0; - o_mem_signed_byte_enable = 0; - o_mem_signed_halfword_enable = 0; - o_mem_unsigned_halfword_enable = 0; - o_mem_translate = 0; - o_und = 0; - o_switch = 0; - - - // Based on our pattern match, call the appropriate task - if ( i_fiq || i_irq || i_abt ) - begin - // Generate LR = PC - 4. - o_condition_code = AL; - o_alu_operation = SUB; - o_alu_source = ARCH_PC; - o_alu_source[32] = INDEX_EN; - o_destination_index = ARCH_LR; - o_shift_source = 4; - o_shift_source[32] = IMMED_EN; - o_shift_operation = LSL; - o_shift_length = 0; - o_shift_length[32] = IMMED_EN; - end - else if ( i_instruction_valid ) - casez ( i_instruction[31:0] ) - CLZ_INSTRUCTION: decode_clz ( i_instruction ); - BX_INST: decode_bx ( i_instruction ); - MRS: decode_mrs ( i_instruction ); - MSR,MSR_IMMEDIATE: decode_msr ( i_instruction ); - - DATA_PROCESSING_IMMEDIATE, - DATA_PROCESSING_REGISTER_SPECIFIED_SHIFT, - DATA_PROCESSING_INSTRUCTION_SPECIFIED_SHIFT: - decode_data_processing ( i_instruction ); - - BRANCH_INSTRUCTION: decode_branch ( i_instruction ); - - LS_INSTRUCTION_SPECIFIED_SHIFT, - LS_IMMEDIATE: decode_ls ( i_instruction ); - - MULT_INST: decode_mult ( i_instruction ); - LMULT_INST: decode_lmult( i_instruction ); - HALFWORD_LS: decode_halfword_ls ( i_instruction ); - SOFTWARE_INTERRUPT: decode_swi ( i_instruction ); - - default: - begin - decode_und ( i_instruction ); - end - endcase -end - -// ---------------------------------------------------------------------------- - -// ============================= -// Decode CLZ -// ============================= -task decode_clz ( input [35:0] i_instruction ); -begin: tskDecodeClz - o_condition_code = i_instruction[31:28]; - o_flag_update = 1'd0; // Instruction does not update any flags. - o_alu_operation = CLZ; // Added. - - // Rn = 0. - o_alu_source = 0; - o_alu_source[32] = IMMED_EN; - - // Rm = register whose CLZ must be found. - o_shift_source = {i_instruction[`DP_RB_EXTEND], i_instruction[`DP_RB]}; // Rm - o_shift_source[32] = INDEX_EN; - o_shift_operation = LSL; - o_shift_length = 0; - o_shift_length[32] = IMMED_EN; // Shift length is 0 of course. -end -endtask - -// ============================= -// Decode long multiplication. -// ============================= -task decode_lmult ( input [35:0] i_instruction ); // Uses bit 35. rm.rs + {rh, rn} -begin: tskLDecodeMult - - o_condition_code = i_instruction[31:28]; - o_flag_update = i_instruction[20]; - - // ARM rd. - o_destination_index = {i_instruction[`DP_RD_EXTEND], - i_instruction[19:16]}; - // For MUL, Rd and Rn are interchanged. - // For 64bit, this is normally high register. - - o_alu_source = i_instruction[11:8]; // ARM rs - o_alu_source[32] = INDEX_EN; - - o_shift_source = {i_instruction[`DP_RB_EXTEND], - i_instruction[`DP_RB]}; - o_shift_source[32] = INDEX_EN; // ARM rm - - // ARM rn - o_shift_length = i_instruction[24] ? - {i_instruction[`DP_RA_EXTEND], - i_instruction[`DP_RD]} : 32'd0; - - o_shift_length[32] = i_instruction[24] ? INDEX_EN:IMMED_EN; - - - // We need to generate output code. - case ( i_instruction[22:21] ) - 2'b00: - begin - // Unsigned MULT64 - o_alu_operation = UMLALH; - o_mem_srcdest_index = RAZ_REGISTER; // rh. - end - 2'b01: - begin - // Unsigned MAC64. Need mem_srcdest as source for RdHi. - o_alu_operation = UMLALH; - o_mem_srcdest_index = i_instruction[19:16]; - end - 2'b10: - begin - // Signed MULT64 - o_alu_operation = SMLALH; - o_mem_srcdest_index = RAZ_REGISTER; - end - 2'b11: - begin - // Signed MAC64. Need mem_srcdest as source of RdHi. - o_alu_operation = SMLALH; - o_mem_srcdest_index = i_instruction[19:16]; - end - endcase - - if ( i_instruction[`OPCODE_EXTEND] == 1'd0 ) // Low request. - begin - o_destination_index = i_instruction[15:12]; // Low register. - o_alu_operation[0] = 1'd0; // Request low operation. - end -end -endtask - -// ---------------------------------------------------------------------------- - -// =============================== -// Decode undefined instructions. -// =============================== -task decode_und( input [34:0] i_instruction ); -begin - // Say instruction is undefined. - o_und = 1; - - // Generate LR = PC - 4 - o_condition_code = AL; - o_alu_operation = SUB; - o_alu_source = ARCH_PC; - o_alu_source[32] = INDEX_EN; - o_destination_index = ARCH_LR; - o_shift_source = 4; - o_shift_source[32] = IMMED_EN; - o_shift_operation = LSL; - o_shift_length = 0; - o_shift_length[32] = IMMED_EN; -end -endtask - -// ---------------------------------------------------------------------------- - -// =========================================== -// Decode software interrupt instructions. -// =========================================== -task decode_swi( input [34:0] i_instruction ); -begin: tskDecodeSWI - - // Generate LR = PC - 4 - o_condition_code = AL; - o_alu_operation = SUB; - o_alu_source = ARCH_PC; - o_alu_source[32] = INDEX_EN; - o_destination_index = ARCH_LR; - o_shift_source = 4; - o_shift_source[32] = IMMED_EN; - o_shift_operation = LSL; - o_shift_length = 0; - o_shift_length[32] = IMMED_EN; -end -endtask - -// ---------------------------------------------------------------------------- - -// ============================ -// Decode halfword LOAD/STORE. -// ============================ -task decode_halfword_ls( input [34:0] i_instruction ); -begin: tskDecodeHalfWordLs - reg [11:0] temp, temp1; - - temp = i_instruction; - temp1 = i_instruction; - - o_condition_code = i_instruction[31:28]; - - temp[7:4] = temp[11:8]; - temp[11:8] = 0; - temp1[11:4] = 0; - - if ( i_instruction[22] ) // immediate - begin - process_immediate ( temp ); - end - else - begin - process_instruction_specified_shift ( temp1 ); - end - - o_alu_operation = i_instruction[23] ? ADD : SUB; - o_alu_source = { i_instruction[`BASE_EXTEND], - i_instruction[`BASE]}; // Pointer register. - o_alu_source[32] = INDEX_EN; - o_mem_load = i_instruction[20]; - o_mem_store = !o_mem_load; - o_mem_pre_index = i_instruction[24]; - - // If post-index is used or pre-index is used with writeback, - // take is as a request to update the base register. - o_destination_index = (i_instruction[21] || !o_mem_pre_index) ? - o_alu_source : - RAZ_REGISTER; // Pointer register already added. - - o_mem_srcdest_index = {i_instruction[`SRCDEST_EXTEND], - i_instruction[`SRCDEST]}; - - // Transfer size. - - o_mem_unsigned_byte_enable = 0; - o_mem_unsigned_halfword_enable = 0; - o_mem_signed_halfword_enable = 0; - - case ( i_instruction[6:5] ) - SIGNED_BYTE: o_mem_signed_byte_enable = 1; - UNSIGNED_HALF_WORD: o_mem_unsigned_halfword_enable = 1; - SIGNED_HALF_WORD: o_mem_signed_halfword_enable = 1; - default: - begin - o_mem_unsigned_byte_enable = 0; - o_mem_unsigned_halfword_enable = 0; - o_mem_signed_halfword_enable = 0; - end - endcase -end -endtask - -// ---------------------------------------------------------------------------- - -// ============================== -// Decode short multiplication. -// ============================== -task decode_mult( input [34:0] i_instruction ); -begin: tskDecodeMult - - - o_condition_code = i_instruction[31:28]; - o_flag_update = i_instruction[20]; - o_alu_operation = UMLALL; - o_destination_index = {i_instruction[`DP_RD_EXTEND], - i_instruction[19:16]}; - - // For MUL, Rd and Rn are interchanged. - o_alu_source = i_instruction[11:8]; // ARM rs - o_alu_source[32] = INDEX_EN; - - o_shift_source = {i_instruction[`DP_RB_EXTEND], - i_instruction[`DP_RB]}; - o_shift_source[32] = INDEX_EN; // ARM rm - - // ARM rn - Set for accumulate. - o_shift_length = i_instruction[21] ? - {i_instruction[`DP_RA_EXTEND], - i_instruction[`DP_RD]} : 32'd0; - - o_shift_length[32] = i_instruction[21] ? INDEX_EN : IMMED_EN; - - // Set rh = 0. - o_mem_srcdest_index = RAZ_REGISTER; -end -endtask - -// ---------------------------------------------------------------------------- - -// ============================= -// BX decode. -// ============================= -// Converted into a MOV to PC. The task of setting the T-bit in the CPSR is -// the job of the writeback stage. -task decode_bx( input [34:0] i_instruction ); -begin: tskDecodeBx - reg [34:0] temp; - - temp = i_instruction[31:0]; - temp[31:4] = 0; // Zero out stuff to avoid conflicts in the function. - - process_instruction_specified_shift(temp); - - // The RAW ALU source does not matter. - o_condition_code = i_instruction[31:28]; - o_alu_operation = MOV; - o_destination_index = ARCH_PC; - - // We will force an immediate in alu source to prevent unwanted locks. - o_alu_source = 0; - o_alu_source[32] = IMMED_EN; - - // Indicate switch. This is a primary differentiator. - o_switch = 1; -end -endtask - -// ---------------------------------------------------------------------------- - -// ============================================= -// Task for decoding load-store instructions. -// ============================================= -task decode_ls( input [34:0] i_instruction ); -begin: tskDecodeLs - - - o_condition_code = i_instruction[31:28]; - - if ( !i_instruction[25] ) // immediate - begin - o_shift_source = i_instruction[11:0]; - o_shift_source[32] = IMMED_EN; - o_shift_length = 0; - o_shift_length[32] = IMMED_EN; - o_shift_operation = LSL; - end - else - begin - process_instruction_specified_shift ( i_instruction[11:0] ); - end - - o_alu_operation = i_instruction[23] ? ADD : SUB; - - // Pointer register. - o_alu_source = {i_instruction[`BASE_EXTEND], i_instruction[`BASE]}; - o_alu_source[32] = INDEX_EN; - o_mem_load = i_instruction[20]; - o_mem_store = !o_mem_load; - o_mem_pre_index = i_instruction[24]; - - // If post-index is used or pre-index is used with writeback, - // take is as a request to update the base register. - o_destination_index = (i_instruction[21] || !o_mem_pre_index) ? - o_alu_source : - RAZ_REGISTER; // Pointer register already added. - o_mem_unsigned_byte_enable = i_instruction[22]; - - o_mem_srcdest_index = {i_instruction[`SRCDEST_EXTEND], i_instruction[`SRCDEST]}; - - if ( !o_mem_pre_index ) // Post-index, writeback has no meaning. - begin - if ( i_instruction[21] ) - begin - // Use it for force usr mode memory mappings. - o_mem_translate = 1'd1; - end - end -end -endtask - -// ---------------------------------------------------------------------------- - -task decode_mrs( input [34:0] i_instruction ); -begin - - process_immediate ( i_instruction[11:0] ); - - o_condition_code = i_instruction[31:28]; - o_destination_index = {i_instruction[`DP_RD_EXTEND], i_instruction[`DP_RD]}; - o_alu_source = i_instruction[22] ? ARCH_CURR_SPSR : ARCH_CPSR; - o_alu_source[32] = INDEX_EN; - o_alu_operation = ADD; -end -endtask - -// ---------------------------------------------------------------------------- - -task decode_msr( input [34:0] i_instruction ); -begin - - if ( i_instruction[25] ) // Immediate present. - begin - process_immediate ( i_instruction[11:0] ); - end - else - begin - process_instruction_specified_shift ( i_instruction[11:0] ); - end - - // Destination. - o_destination_index = i_instruction[22] ? ARCH_CURR_SPSR : ARCH_CPSR; - - o_condition_code = i_instruction[31:28]; - - // Make srcdest as SPSR. useful for MMOV. - o_mem_srcdest_index = ARCH_CURR_SPSR; - - // Select SPSR or CPSR. - o_alu_operation = i_instruction[22] ? MMOV : FMOV; - - o_alu_source = i_instruction[19:16]; - o_alu_source[32] = IMMED_EN; - - // Part of the instruction will silently fail when changing mode bits - // in user mode. This is as per the ARM spec. - if ( i_cpsr_ff_mode == USR ) - begin - o_alu_source[2:0] = 3'b0; - end -end -endtask - -// ---------------------------------------------------------------------------- - -// ======================== -// Decode B -// ======================== -task decode_branch( input [34:0] i_instruction ); -begin - // A branch is decayed into PC = PC + $signed(immed) - o_condition_code = i_instruction[31:28]; - o_alu_operation = ADD; - o_destination_index = ARCH_PC; - o_alu_source = ARCH_PC; - o_alu_source[32] = INDEX_EN; - o_shift_source = ($signed(i_instruction[23:0])); - o_shift_source[32] = IMMED_EN; - o_shift_operation = LSL; - o_shift_length = i_instruction[34] ? 1 : 2; // Thumb branches sometimes need only a shift of 1. - o_shift_length[32] = IMMED_EN; -end -endtask - -// ---------------------------------------------------------------------------- - -// -// Common data processing handles the common section of all 3 data processing -// formats. -// -task decode_data_processing( input [34:0] i_instruction ); -begin - o_condition_code = i_instruction[31:28]; - o_alu_operation = i_instruction[24:21]; - o_flag_update = i_instruction[20]; - o_destination_index = {i_instruction[`DP_RD_EXTEND], i_instruction[`DP_RD]}; - o_alu_source = i_instruction[`DP_RA]; - o_alu_source[32] = INDEX_EN; - o_mem_srcdest_index = ARCH_CURR_SPSR; - - if ( o_alu_operation == CMP || - o_alu_operation == CMN || - o_alu_operation == TST || - o_alu_operation == TEQ ) - begin - o_destination_index = RAZ_REGISTER; - end - - casez ( {i_instruction[25],i_instruction[7],i_instruction[4]} ) - 3'b1zz: process_immediate ( i_instruction ); - 3'b0z0: process_instruction_specified_shift ( i_instruction ); - 3'b001: process_register_specified_shift ( i_instruction ); - default: - begin - $display("Error : Decoder Error."); - $finish; - end - endcase -end -endtask - -// ---------------------------------------------------------------------------- - -// -// If an immediate value is to be rotated right by an -// immediate value, this mode is used. -// -task process_immediate ( input [34:0] instruction ); -begin - o_shift_length = instruction[11:8] << 1'd1; - o_shift_length[32] = IMMED_EN; - o_shift_source = instruction[7:0]; - o_shift_source[32] = IMMED_EN; - o_shift_operation = RORI; -end -endtask - -// ---------------------------------------------------------------------------- - -// -// The shifter source is a register but the -// amount to shift is in the instruction itself. -// -task process_instruction_specified_shift ( input [34:0] instruction ); -begin - // ROR #0 = RRC, ASR #0 = ASR #32, LSL #0 = LSL #0, LSR #0 = LSR #32 - // ROR #n = ROR_1 #n ( n > 0 ) - o_shift_length = instruction[11:7]; - o_shift_length[32] = IMMED_EN; - o_shift_source = {i_instruction[`DP_RB_EXTEND],instruction[`DP_RB]}; - o_shift_source[32] = INDEX_EN; - o_shift_operation = instruction[6:5]; - - case ( o_shift_operation ) - LSR: if ( !o_shift_length[31:0] ) o_shift_length[31:0] = 32; - ASR: if ( !o_shift_length[31:0] ) o_shift_length[31:0] = 32; - ROR: - begin - if ( !o_shift_length[31:0] ) - o_shift_operation = RRC; - else - o_shift_operation = ROR_1; - // Differs in carry generation behavior. - end - default: // For lint. - begin - end - endcase - - // Reinforce the fact. - o_shift_length[32] = IMMED_EN; -end -endtask - -// ---------------------------------------------------------------------------- - -// The source register and the amount of shift are both in registers. -task process_register_specified_shift ( input [34:0] instruction ); -begin - o_shift_length = instruction[11:8]; - o_shift_length[32] = INDEX_EN; - o_shift_source = {i_instruction[`DP_RB_EXTEND], instruction[`DP_RB]}; - o_shift_source[32] = INDEX_EN; - o_shift_operation = instruction[6:5]; -end -endtask - -endmodule // zap_decode.v -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_alu_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_alu_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_alu_main.v (nonexistent) @@ -1,981 +0,0 @@ -// --------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- ------------------------------------------------------------------------ -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// --------------------------------------------------------------------------- -// -- -- -// -- This is the main ZAP arithmetic and logic unit. Apart from shfits -- -// -- and multiplies, all other arithmetic and logic is performed here. -- -// -- Also data memory access signals are generated at the end of the clock -- -// -- cycle. Instructions that fail condition checks are invalidated here. -- -// -- -- -// --------------------------------------------------------------------------- - -`default_nettype none - -module zap_alu_main #( - - parameter [31:0] PHY_REGS = 32'd46, // Number of physical registers. - parameter [31:0] SHIFT_OPS = 32'd5, // Number of shift operations. - parameter [31:0] ALU_OPS = 32'd32, // Number of arithmetic operations. - parameter [31:0] FLAG_WDT = 32'd32 // Width of active CPSR. -) -( - // ------------------------------------------------------------------ - // Decompile Interface. Only for debug. - // ------------------------------------------------------------------ - - input wire [64*8-1:0] i_decompile, - output reg [64*8-1:0] o_decompile, - - // ------------------------------------------------------------------ - // ALU Hijack Interface. For Thumb Data Abort address calculation. - // ------------------------------------------------------------------ - - input wire i_hijack, // Enable hijack. - input wire [31:0] i_hijack_op1, // Hijack operand 1. - input wire [31:0] i_hijack_op2, // Hijack operand 2. - input wire i_hijack_cin, // Hijack carry in. - output wire [31:0] o_hijack_sum, // Hijack sum out. - - // ------------------------------------------------------------------ - // Clock and reset - // ------------------------------------------------------------------ - - input wire i_clk, // Clock. - input wire i_reset, // sync active high reset. - - // ------------------------------------------------------------------- - // Clear and Stall signals. - // ------------------------------------------------------------------- - - input wire i_clear_from_writeback, // Clear unit. - input wire i_data_stall, // DCACHE stall. - - // ------------------------------------------------------------------- - // Misc. signals - // ------------------------------------------------------------------- - - input wire [31:0] i_cpsr_nxt, // From passive CPSR. - input wire i_switch_ff, // Switch state. - input wire [1:0] i_taken_ff, // Branch prediction. - input wire [31:0] i_pc_ff, // Addr of instr. - input wire i_nozero_ff, // Zero flag will not be set. - - // ------------------------------------------------------------------ - // Source values - // ------------------------------------------------------------------ - - input wire [31:0] i_alu_source_value_ff, // ALU source value. - input wire [31:0] i_shifted_source_value_ff, // Shifted source value. - input wire i_shift_carry_ff, // Carry from shifter. - input wire [31:0] i_pc_plus_8_ff, // PC + 8 value. - - // ------------------------------------------------------------------ - // Interrupt Tagging - // ------------------------------------------------------------------ - - input wire i_abt_ff, // ABT flagged. - input wire i_irq_ff, // IRQ flagged. - input wire i_fiq_ff, // FIQ flagged. - input wire i_swi_ff, // SWI flagged. - input wire i_und_ff, // Flagged undefined instructions. - input wire i_data_mem_fault, // Flagged Data abort. - - // ------------------------------------------------------------------ - // Memory Access Related - // ------------------------------------------------------------------ - - input wire [31:0] i_mem_srcdest_value_ff, // Value to store. - input wire [zap_clog2(PHY_REGS)-1:0] i_mem_srcdest_index_ff, // LD/ST Memory data register index. - input wire i_mem_load_ff, // LD/ST Memory load. - input wire i_mem_store_ff, // LD/ST Memory store. - input wire i_mem_pre_index_ff, // LD/ST Pre/Post index. - input wire i_mem_unsigned_byte_enable_ff, // LD/ST uint8_t data type. - input wire i_mem_signed_byte_enable_ff, // LD/ST int8_t data type. - input wire i_mem_signed_halfword_enable_ff, // LD/ST int16_t data type. - input wire i_mem_unsigned_halfword_enable_ff,// LD/ST uint16_t data type. - input wire i_mem_translate_ff, // LD/ST Force user view of memory. - input wire i_force32align_ff, // Force address alignment to 32-bit. - - // ------------------------------------------------------------------- - // ALU controls - // ------------------------------------------------------------------- - - input wire [3:0] i_condition_code_ff, // CC associated with instr. - input wire [zap_clog2(PHY_REGS)-1:0] i_destination_index_ff, // Target register index. - input wire [zap_clog2(ALU_OPS)-1:0] i_alu_operation_ff, // Operation to perform. - input wire i_flag_update_ff, // Update flags if 1. - - // ----------------------------------------------------------------- - // ALU result - // ----------------------------------------------------------------- - - output reg [31:0] o_alu_result_nxt, // For feedback. ALU result _nxt version. - output reg [31:0] o_alu_result_ff, // ALU result flopped version. - output reg o_dav_ff, // Instruction valid. - output reg o_dav_nxt, // Instruction valid _nxt version. - output reg [FLAG_WDT-1:0] o_flags_ff, // Output flags (CPSR). - output reg [FLAG_WDT-1:0] o_flags_nxt, // CPSR next. - output reg [zap_clog2(PHY_REGS)-1:0] o_destination_index_ff, // Destination register index. - - // ----------------------------------------------------------------- - // Interrupt Tagging - // ----------------------------------------------------------------- - - output reg o_abt_ff, // Instruction abort flagged. - output reg o_irq_ff, // IRQ flagged. - output reg o_fiq_ff, // FIQ flagged. - output reg o_swi_ff, // SWI flagged. - output reg o_und_ff, // Flagged undefined instructions - - // ----------------------------------------------------------------- - // Jump Controls, BP Confirm, PC + 8 - // ----------------------------------------------------------------- - - output reg [31:0] o_pc_plus_8_ff, // Instr address + 8. - output reg o_clear_from_alu, // ALU commands a pipeline clear and a predictor correction. - output reg [31:0] o_pc_from_alu, // Corresponding address to go to is provided here. - output reg o_confirm_from_alu, // Tell branch predictor it was correct. - - // ---------------------------------------------------------------- - // Memory access related - // ---------------------------------------------------------------- - - output reg [zap_clog2(PHY_REGS)-1:0] o_mem_srcdest_index_ff, // LD/ST data register. - output reg o_mem_load_ff, // LD/ST load indicator. - output reg o_mem_store_ff, // LD/ST store indicator. - output reg [31:0] o_mem_address_ff, // LD/ST address to access. - output reg o_mem_unsigned_byte_enable_ff, // uint8_t - output reg o_mem_signed_byte_enable_ff, // int8_t - output reg o_mem_signed_halfword_enable_ff, // int16_t - output reg o_mem_unsigned_halfword_enable_ff, // uint16_t - output reg [31:0] o_mem_srcdest_value_ff, // LD/ST value to store. - output reg o_mem_translate_ff, // LD/ST force user view of memory. - output reg [3:0] o_ben_ff, // LD/ST byte enables (only for STore instructions). - output reg [31:0] o_address_nxt, // D pin of address register to drive TAG RAMs. - - // ------------------------------------------------------------- - // Wishbone signal outputs. - // ------------------------------------------------------------- - - output reg o_data_wb_we_nxt, - output reg o_data_wb_cyc_nxt, - output reg o_data_wb_stb_nxt, - output reg [31:0] o_data_wb_dat_nxt, - output reg [3:0] o_data_wb_sel_nxt, - output reg o_data_wb_we_ff, - output reg o_data_wb_cyc_ff, - output reg o_data_wb_stb_ff, - output reg [31:0] o_data_wb_dat_ff, - output reg [3:0] o_data_wb_sel_ff -); - -// ---------------------------------------------------------------------------- -// Includes -// ---------------------------------------------------------------------------- - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -// ----------------------------------------------------------------------------- -// Localparams -// ----------------------------------------------------------------------------- - -// Local N,Z,C,V structures. -localparam [1:0] _N = 2'd3; -localparam [1:0] _Z = 2'd2; -localparam [1:0] _C = 2'd1; -localparam [1:0] _V = 2'd0; - -// Branch status. -localparam [1:0] SNT = 2'd0; -localparam [1:0] WNT = 2'd1; -localparam [1:0] WT = 2'd2; -localparam [1:0] ST = 2'd3; - -// ------------------------------------------------------------------------------ -// Variables -// ------------------------------------------------------------------------------ - -// Memory srcdest value (i.e., data) -wire [31:0] mem_srcdest_value_nxt; - -// Byte enable generator. -wire [3:0] ben_nxt; - -// Address about to be output. Used to drive tag RAMs etc. -reg [31:0] mem_address_nxt; - -/* - Sleep flop. When 1 unit sleeps i.e., does not produce any output except on - the first clock cycle where LR is calculated using the ALU. -*/ -reg sleep_ff, sleep_nxt; - -/* - CPSR (Active CPSR). The active CPSR is from the where the CPU flags are - read out and the mode also is. Mode changes via manual writes to CPSR - are first written to the active and they then propagate to the passive CPSR - in the writeback stage. This reduces the pipeline flush penalty. -*/ -reg [31:0] flags_ff, flags_nxt; - -reg [31:0] rm, rn; // RM = shifted source value Rn for - // non shifted source value. These are - // values and not indices. - - -reg [5:0] clz_rm; // Count leading zeros in Rm. - -// Destination index about to be output. -reg [zap_clog2(PHY_REGS)-1:0] o_destination_index_nxt; - -// 1s complement of Rm and Rn. -wire [31:0] not_rm = ~rm; -wire [31:0] not_rn = ~rn; - -// Wires which connect to an adder. -reg [31:0] op1, op2; -reg cin; - -// 32-bit adder with carry input and carry output. -wire [32:0] sum = {1'd0, op1} + {1'd0, op2} + {32'd0, cin}; - -reg [31:0] tmp_flags, tmp_sum; - -// Opcode. -wire [zap_clog2(ALU_OPS)-1:0] opcode = i_alu_operation_ff; - -// ------------------------------------------------------------------------------- -// Assigns -// ------------------------------------------------------------------------------- - -/* - For memory stores, we must generate correct byte enables. This is done - by examining access type inputs. For loads, always 1111 is generated. - If there is neither a load or a store, the old value is preserved. -*/ -assign ben_nxt = generate_ben ( - i_mem_unsigned_byte_enable_ff, - i_mem_signed_byte_enable_ff, - i_mem_unsigned_halfword_enable_ff, - i_mem_unsigned_halfword_enable_ff, - mem_address_nxt); - -assign mem_srcdest_value_nxt = duplicate ( - i_mem_unsigned_byte_enable_ff, - i_mem_signed_byte_enable_ff, - i_mem_unsigned_halfword_enable_ff, - i_mem_unsigned_halfword_enable_ff, - i_mem_srcdest_value_ff ); - -/* - Hijack interface. Data aborts use the hijack interface to find return - address. The writeback drives the ALU inputs to find the final output. -*/ -assign o_hijack_sum = sum; - -// ------------------------------------------------------------------------------- -// CLZ logic. -// ------------------------------------------------------------------------------- - -always @* // CLZ implementation. -begin - casez(rm) - 32'b1???????????????????????????????: clz_rm = 6'd00; - 32'b01??????????????????????????????: clz_rm = 6'd01; - 32'b001?????????????????????????????: clz_rm = 6'd02; - 32'b0001????????????????????????????: clz_rm = 6'd03; - 32'b00001???????????????????????????: clz_rm = 6'd04; - 32'b000001??????????????????????????: clz_rm = 6'd05; - 32'b0000001?????????????????????????: clz_rm = 6'd06; - 32'b00000001????????????????????????: clz_rm = 6'd07; - 32'b000000001???????????????????????: clz_rm = 6'd08; - 32'b0000000001??????????????????????: clz_rm = 6'd09; - 32'b00000000001?????????????????????: clz_rm = 6'd10; - 32'b000000000001????????????????????: clz_rm = 6'd11; - 32'b0000000000001???????????????????: clz_rm = 6'd12; - 32'b00000000000001??????????????????: clz_rm = 6'd13; - 32'b000000000000001?????????????????: clz_rm = 6'd14; - 32'b0000000000000001????????????????: clz_rm = 6'd15; - 32'b00000000000000001???????????????: clz_rm = 6'd16; - 32'b000000000000000001??????????????: clz_rm = 6'd17; - 32'b0000000000000000001?????????????: clz_rm = 6'd18; - 32'b00000000000000000001????????????: clz_rm = 6'd19; - 32'b000000000000000000001???????????: clz_rm = 6'd20; - 32'b0000000000000000000001??????????: clz_rm = 6'd21; - 32'b00000000000000000000001?????????: clz_rm = 6'd22; - 32'b000000000000000000000001????????: clz_rm = 6'd23; - 32'b0000000000000000000000001???????: clz_rm = 6'd24; - 32'b00000000000000000000000001??????: clz_rm = 6'd25; - 32'b000000000000000000000000001?????: clz_rm = 6'd26; - 32'b0000000000000000000000000001????: clz_rm = 6'd27; - 32'b00000000000000000000000000001???: clz_rm = 6'd28; - 32'b000000000000000000000000000001??: clz_rm = 6'd29; - 32'b0000000000000000000000000000001?: clz_rm = 6'd30; - 32'b00000000000000000000000000000001: clz_rm = 6'd31; - default: clz_rm = 6'd32; // All zeros. - endcase -end - -// ---------------------------------------------------------------------------- -// Aliases -// ---------------------------------------------------------------------------- - -always @* -begin - rm = i_shifted_source_value_ff; - rn = i_alu_source_value_ff; - o_flags_ff = flags_ff; - o_flags_nxt = flags_nxt; -end - -// ----------------------------------------------------------------------------- -// Sequential logic. -// ----------------------------------------------------------------------------- - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - // On reset, processor enters supervisory mode with interrupts - // masked. - clear ( {1'd1,1'd1,1'd0,SVC} ); - end - else if ( i_clear_from_writeback ) - begin - // Clear but take CPSR from writeback. - clear ( i_cpsr_nxt ); - end - else if ( i_data_stall ) - begin - // Preserve values. - end - else if ( i_data_mem_fault || sleep_ff ) - begin - // Clear and preserve flags. Keep sleeping. - clear(flags_ff); - sleep_ff <= 1'd1; - o_dav_ff <= 1'd0; // Don't give any output. - end - else - begin - // Clock out all flops normally. - - o_alu_result_ff <= o_alu_result_nxt; - o_dav_ff <= o_dav_nxt; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_destination_index_ff <= o_destination_index_nxt; - flags_ff <= flags_nxt; - o_abt_ff <= i_abt_ff; - o_irq_ff <= i_irq_ff; - o_fiq_ff <= i_fiq_ff; - o_swi_ff <= i_swi_ff; - o_mem_srcdest_index_ff <= i_mem_srcdest_index_ff; - o_mem_srcdest_index_ff <= i_mem_srcdest_index_ff; - - // Load or store must come up only if an actual LDR/STR is - // detected. - o_mem_load_ff <= o_dav_nxt ? i_mem_load_ff : 1'd0; - o_mem_store_ff <= o_dav_nxt ? i_mem_store_ff: 1'd0; - - o_mem_unsigned_byte_enable_ff <= i_mem_unsigned_byte_enable_ff; - o_mem_signed_byte_enable_ff <= i_mem_signed_byte_enable_ff; - o_mem_signed_halfword_enable_ff <= i_mem_signed_halfword_enable_ff; - o_mem_unsigned_halfword_enable_ff<= i_mem_unsigned_halfword_enable_ff; - o_mem_translate_ff <= i_mem_translate_ff; - - // - // The value to store will have to be duplicated for easier - // memory controller design. See the duplicate() function. - // - o_mem_srcdest_value_ff <= mem_srcdest_value_nxt; - - sleep_ff <= sleep_nxt; - o_und_ff <= i_und_ff; - - // Generating byte enables based on the data type and address. - o_ben_ff <= ben_nxt; - - // For debug - o_decompile <= i_decompile; - end -end - -// ---------------------------------------------------------------------------- - -always @ ( posedge i_clk ) // Wishbone flops. -begin - // Wishbone updates. - o_data_wb_cyc_ff <= o_data_wb_cyc_nxt; - o_data_wb_stb_ff <= o_data_wb_stb_nxt; - o_data_wb_we_ff <= o_data_wb_we_nxt; - o_data_wb_dat_ff <= o_data_wb_dat_nxt; - o_data_wb_sel_ff <= o_data_wb_sel_nxt; - o_mem_address_ff <= o_address_nxt; -end - -// ----------------------------------------------------------------------------- -// WB next state logic. -// ----------------------------------------------------------------------------- - -always @* -begin - // Preserve values. - o_data_wb_cyc_nxt = o_data_wb_cyc_ff; - o_data_wb_stb_nxt = o_data_wb_stb_ff; - o_data_wb_we_nxt = o_data_wb_we_ff; - o_data_wb_dat_nxt = o_data_wb_dat_ff; - o_data_wb_sel_nxt = o_data_wb_sel_ff; - o_address_nxt = o_mem_address_ff; - - if ( i_reset ) // Synchronous reset. - begin - o_data_wb_cyc_nxt = 1'd0; - o_data_wb_stb_nxt = 1'd0; - end - else if ( i_clear_from_writeback ) - begin - o_data_wb_cyc_nxt = 0; - o_data_wb_stb_nxt = 0; - end - else if ( i_data_stall ) - begin - // Save state. - end - else if ( i_data_mem_fault || sleep_ff ) - begin - o_data_wb_cyc_nxt = 0; - o_data_wb_stb_nxt = 0; - end - else - begin - o_data_wb_cyc_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0; - o_data_wb_stb_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0; - o_data_wb_we_nxt = o_dav_nxt ? i_mem_store_ff : 1'd0; - o_data_wb_dat_nxt = mem_srcdest_value_nxt; - o_data_wb_sel_nxt = ben_nxt; - o_address_nxt = mem_address_nxt; - end -end - -// ---------------------------------------------------------------------------- -// Used to generate access address. -// ---------------------------------------------------------------------------- - -always @ (*) -begin:pre_post_index_address_generator - /* - * Do not change address if not needed. - * If not a load OR a store. Preserve this value. Power saving. - */ - if (!( (i_mem_load_ff || i_mem_store_ff) && o_dav_nxt )) - mem_address_nxt = o_mem_address_ff; - else - begin - /* - * Memory address output based on pre or post index. - * For post-index, update is done after memory access. - * For pre-index, update is done before memory access. - */ - if ( i_mem_pre_index_ff == 0 ) - mem_address_nxt = rn; // Postindex; - else - mem_address_nxt = o_alu_result_nxt; // Preindex. - - // If a force 32 align is set, make the lower 2 bits as zero. - if ( i_force32align_ff ) - mem_address_nxt[1:0] = 2'b00; - end -end - -// --------------------------------------------------------------------------------- -// Used to generate ALU result + Flags -// --------------------------------------------------------------------------------- - -always @* -begin: alu_result - - // Default value. - tmp_flags = flags_ff; - - // If it is a logical instruction. - if ( opcode == AND || - opcode == EOR || - opcode == MOV || - opcode == MVN || - opcode == BIC || - opcode == ORR || - opcode == TST || - opcode == TEQ || - opcode == CLZ - ) - begin - // Call the logical processing function. - {tmp_flags[31:28], tmp_sum} = process_logical_instructions ( - rn, rm, flags_ff[31:28], - opcode, i_flag_update_ff, i_nozero_ff - ); - end - - /* - * Flag MOV(FMOV) i.e., MOV to CPSR and MMOV handler. - * FMOV moves to CPSR and flushes the pipeline. - * MMOV moves to SPSR and does not flush the pipeline. - */ - else if ( opcode == FMOV || opcode == MMOV ) - begin: fmov_mmov - integer i; - reg [31:0] exp_mask; - - // Read entire CPSR or SPSR. - tmp_sum = opcode == FMOV ? flags_ff : i_mem_srcdest_value_ff; - - // Generate a proper mask. - exp_mask = {{8{rn[3]}},{8{rn[2]}},{8{rn[1]}},{8{rn[0]}}}; - - // Change only specific bits as specified by the mask. - for ( i=0;i<32;i=i+1 ) - begin - if ( exp_mask[i] ) - tmp_sum[i] = rm[i]; - end - - /* - * FMOV moves to the CPSR in ALU and writeback. - * No register is changed. The MSR out of this will have - * a target to CPSR. - */ - if ( opcode == FMOV ) - begin - tmp_flags = tmp_sum; - end - end - else - begin: blk3 - reg [3:0] flags; - reg [zap_clog2(ALU_OPS)-1:0] op; - reg n,z,c,v; - - op = opcode; - - // Assign output of adder to flags after some minimal logic. - c = sum[32]; - z = (sum[31:0] == 0); - n = sum[31]; - - // Overflow. - if ( ( op == ADD || op == ADC || op == CMN ) && (rn[31] == rm[31]) && (sum[31] != rn[31]) ) - v = 1; - else if ( (op == RSB || op == RSC) && (rm[31] == !rn[31]) && (sum[31] != rm[31] ) ) - v = 1; - else if ( (op == SUB || op == SBC || op == CMP) && (rn[31] == !rm[31]) && (sum[31] != rn[31]) ) - v = 1; - else - v = 0; - - // - // If you choose not to update flags, do not change the flags. - // Otherwise, they will contain their newly computed values. - // - if ( i_flag_update_ff ) - tmp_flags[31:28] = {n,z,c,v}; - - // Write out the result. - tmp_sum = op == CLZ ? clz_rm : sum; - end - - // Drive nxt pin of result register. - o_alu_result_nxt = tmp_sum; -end - -// ---------------------------------------------------------------------------- -// Flag propagation and branch prediction feedback unit -// ---------------------------------------------------------------------------- - -always @* -begin: flags_bp_feedback - - o_clear_from_alu = 1'd0; - o_pc_from_alu = 32'd0; - sleep_nxt = sleep_ff; - flags_nxt = tmp_flags; - o_destination_index_nxt = i_destination_index_ff; - o_confirm_from_alu = 1'd0; - - // Check if condition is satisfied. - o_dav_nxt = is_cc_satisfied ( i_condition_code_ff, flags_ff[31:28] ); - - if ( i_irq_ff || i_fiq_ff || i_abt_ff || i_swi_ff || i_und_ff ) - begin - // - // Any sign of an interrupt is present, put unit to sleep. - // The current instruction will not be executed ultimately. - // However o_dav_nxt = 1 since interrupt must be carried on. - // - o_dav_nxt = 1'd1; - sleep_nxt = 1'd1; - end - else if ( (opcode == FMOV) && o_dav_nxt ) // Writes to CPSR... - begin - o_clear_from_alu = 1'd1; // Need to flush everything because we might end up fetching stuff in KERNEL instead of USER mode. - o_pc_from_alu = sum; // NOT tmp_sum, that would be loaded into CPSR. - - // USR cannot change mode. Will silently fail. - flags_nxt[`CPSR_MODE] = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security. - end - else if ( i_destination_index_ff == ARCH_PC && (i_condition_code_ff != NV)) - begin - if ( i_flag_update_ff && o_dav_nxt ) // PC update with S bit. Context restore. - begin - o_destination_index_nxt = PHY_RAZ_REGISTER; - o_clear_from_alu = 1'd1; - o_pc_from_alu = tmp_sum; - flags_nxt = i_mem_srcdest_value_ff; // Restore CPSR from SPSR. - flags_nxt[`CPSR_MODE] = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security. - end - else if ( o_dav_nxt ) // Branch taken and no flag update. - begin - if ( i_taken_ff == SNT || i_taken_ff == WNT ) // Incorrectly predicted. - begin - // Quick branches - Flush everything before. - // Dumping ground since PC change is done. Jump to branch target for fast switching. - o_destination_index_nxt = PHY_RAZ_REGISTER; - o_clear_from_alu = 1'd1; - o_pc_from_alu = tmp_sum; - - if ( i_switch_ff ) - begin - flags_nxt[T] = tmp_sum[0]; - end - end - else // Correctly predicted. - begin - // If thumb bit changes, flush everything before - if ( i_switch_ff ) - begin - // Quick branches! PC goes to RAZ register since - // change is done. - - o_destination_index_nxt = PHY_RAZ_REGISTER; - o_clear_from_alu = 1'd1; - o_pc_from_alu = tmp_sum; // Jump to branch target. - flags_nxt[T] = tmp_sum[0]; - end - else - begin - // No mode change, do not change anything. - - o_destination_index_nxt = PHY_RAZ_REGISTER; - o_clear_from_alu = 1'd0; - - // Send confirmation message to branch predictor. - - o_pc_from_alu = 32'd0; - o_confirm_from_alu = 1'd1; - end - end - end - else // Branch not taken - begin - if ( i_taken_ff == WT || i_taken_ff == ST ) - // - // Wrong prediction as taken. Go back to the same - // branch. Non branches are always predicted as not-taken. - // - // GO BACK TO THE SAME BRANCH AND INFORM PREDICTOR OF ITS - // MISTAKE - THE NEXT TIME THE PREDICTION WILL BE NOT-TAKEN. - // - begin - o_clear_from_alu = 1'd1; - o_pc_from_alu = i_pc_ff; - end - else // Correct prediction. - begin - o_clear_from_alu = 1'd0; - o_pc_from_alu = 32'd0; - end - end - end - else if ( i_mem_srcdest_index_ff == ARCH_PC && o_dav_nxt && i_mem_load_ff) - begin - // Loads to PC also puts the unit to sleep. - sleep_nxt = 1'd1; - end - - // If the current instruction is invalid, do not update flags. - if ( o_dav_nxt == 1'd0 ) - flags_nxt = flags_ff; -end - -// ---------------------------------------------------------------------------- -// MUX structure on the inputs of the adder. -// ---------------------------------------------------------------------------- - -// These are adder connections. Data processing and FMOV use these. -always @* -begin: adder_ip_mux - reg [zap_clog2(ALU_OPS)-1:0] op; - reg [31:0] flags; - - flags = flags_ff[31:28]; - op = i_alu_operation_ff; - - if ( i_hijack ) - begin - op1 = i_hijack_op1; - op2 = i_hijack_op2; - cin = i_hijack_cin; - end - else - case ( op ) - FMOV: begin op1 = i_pc_plus_8_ff ; op2 = ~32'd4 ; cin = 1'd1; end - ADD: begin op1 = rn ; op2 = rm ; cin = 32'd0; end - ADC: begin op1 = rn ; op2 = rm ; cin = flags[_C]; end - SUB: begin op1 = rn ; op2 = not_rm ; cin = 32'd1; end - RSB: begin op1 = rm ; op2 = not_rn ; cin = 32'd1; end - SBC: begin op1 = rn ; op2 = not_rm ; cin = !flags[_C];end - RSC: begin op1 = rm ; op2 = not_rn ; cin = !flags[_C];end - - // Target is not written. - CMP: begin op1 = rn ; op2 = not_rm ; cin = 32'd1; end - CMN: begin op1 = rn ; op2 = rm ; cin = 32'd0; end - - default: - begin - op1 = 0; - op2 = 0; - cin = 0; - end - endcase -end - -// ---------------------------------------------------------------------------- -// Functions -// ---------------------------------------------------------------------------- - -// Process logical instructions. -function [35:0] process_logical_instructions -( - input [31:0] rn, - input [31:0] rm, - input [3:0] flags, - input [zap_clog2(ALU_OPS)-1:0] op, - input i_flag_upd, input nozero -); -begin: blk2 - reg [31:0] rd; - reg [3:0] flags_out; - - // Avoid accidental latch inference. - rd = 0; - flags_out = 0; - - case(op) - AND: rd = rn & rm; - EOR: rd = rn ^ rm; - BIC: rd = rn & ~(rm); - MOV: rd = rm; - MVN: rd = ~rm; - ORR: rd = rn | rm; - TST: rd = rn & rm; // Target is not written. - TEQ: rd = rn ^ rn; // Target is not written. - default: - begin - rd = 0; - $display("*Error: Logic unit got non logic opcode..."); - $finish; - end - endcase - - // Suppose flags are not going to change at ALL. - flags_out = flags; - - // Assign values to the flags only if an update is requested. Note that V - // is not touched even if change is requested. - if ( i_flag_upd ) - begin - // V is preserved since flags_out = flags assignment. - flags_out[_C] = i_shift_carry_ff; - - if ( nozero ) - // This specifically states that we must NOT set the - // ZERO flag under any circumstance. - flags_out[_Z] = 1'd0; - else - flags_out[_Z] = (rd == 0); - - flags_out[_N] = rd[31]; - end - - process_logical_instructions = {flags_out, rd}; -end -endfunction - -/* - * This task clears out the flip-flops in this module. - * The flag input is used to preserve/force flags to - * a specific state. - */ -task clear ( input [31:0] flags ); -begin - o_dav_ff <= 0; - flags_ff <= flags; - o_abt_ff <= 0; - o_irq_ff <= 0; - o_fiq_ff <= 0; - o_swi_ff <= 0; - o_und_ff <= 0; - sleep_ff <= 0; - o_mem_load_ff <= 0; - o_mem_store_ff <= 0; -end -endtask - -/* - * The reason we use the duplicate function is to copy value over the memory - * bus for memory stores. If we have a byte write to address 1, then the - * memory controller basically takes address 0 and byte enable 0010 and writes - * to address 1. This enables implementation of a 32-bit memory controller - * with byte enables to control updates as is commonly done. Basically this - * is to faciliate byte and halfword based writes on a 32-bit aligned memory - * bus using byte enables. The rules are simple: - * For a byte access - duplicate the lower byte of the register 4 times. - * For halfword access - duplicate the lower 16-bit of the register twice. - */ - -function [31:0] duplicate ( input ub, // Unsigned byte. - input sb, // Signed byte. - input uh, // Unsigned halfword. - input sh, // Signed halfword. - input [31:0] val ); -reg [31:0] x; -begin - if ( ub || sb) - begin - // Byte. - x = {val[7:0], val[7:0], val[7:0], val[7:0]}; - end - else if (uh || sh) - begin - // Halfword. - x = {val[15:0], val[15:0]}; - end - else - begin - x = val; - end - - duplicate = x; -end -endfunction - -/* - * Generate byte enables based on access mode. - * This function is similar in spirit to the previous one. The - * byte enables are generated in such a way that along with - * duplicate - byte and halfword accesses are possible. - * Rules - - * For a byte access, generate a byte enable with a 1 at the - * position that the lower 2-bits read (0,1,2,3). - * For a halfword access, based on lower 2-bits, if it is 00, - * make no change to byte enable (0011) else if it is 10, then - * make byte enable as (1100) which is basically the 32-bit - * address + 2 (and 3) which will be written. - */ -function [3:0] generate_ben ( input ub, // Unsigned byte. - input sb, // Signed byte. - input uh, // Unsigned halfword. - input sh, // Signed halfword. - input [31:0] addr ); -reg [3:0] x; -begin - if ( ub || sb ) // Byte oriented. - begin - case ( addr[1:0] ) // Based on address lower 2-bits. - 0: x = 1; - 1: x = 1 << 1; - 2: x = 1 << 2; - 3: x = 1 << 3; - endcase - end - else if ( uh || sh ) // Halfword. A word = 2 half words. - begin - case ( addr[1] ) - 0: x = 4'b0011; - 1: x = 4'b1100; - endcase - end - else - begin - x = 4'b1111; // Word oriented. - end - - generate_ben = x; -end -endfunction // generate_ben - -/* - * This assertion ensures that no privilege escalation is possible. - * It does so by ensuring that the flag register cannot change out - * of USR during normal operation. - */ -always @* -begin - if ( flags_nxt[`CPSR_MODE] != USR && flags_ff[`CPSR_MODE] == USR ) - begin - $display($time, " - %m :: Error: Privilege Escalation Error."); - $stop; - end -end - -reg [64*8-1:0] OPCODE; - -always @* -case(opcode) - AND:begin OPCODE = "AND"; end - EOR:begin OPCODE = "EOR"; end - MOV:begin OPCODE = "MOV"; end - MVN:begin OPCODE = "MVN"; end - BIC:begin OPCODE = "BIC"; end - ORR:begin OPCODE = "ORR"; end - TST:begin OPCODE = "TST"; end - TEQ:begin OPCODE = "TEQ"; end - CLZ:begin OPCODE = "CLZ"; end - FMOV:begin OPCODE = "FMOV"; end - ADD:begin OPCODE = "ADD"; end - ADC:begin OPCODE = "ADC"; end - SUB:begin OPCODE = "SUB"; end - RSB:begin OPCODE = "RSB"; end - SBC:begin OPCODE = "SBC"; end - RSC:begin OPCODE = "RSC"; end - CMP:begin OPCODE = "CMP"; end - CMN:begin OPCODE = "CMN"; end -endcase - -endmodule // zap_alu_main.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// END OF FILE -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_decode_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_decode_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_decode_main.v (nonexistent) @@ -1,393 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This module decodes 32-bit ARM instructions into an internal wide -- -// -- instruction format that is understood by downstream logic. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_decode_main #( - // Number of architectural registers. - parameter [31:0] ARCH_REGS = 32'd32, - - // Number of arithm. opcodes - parameter ALU_OPS = 32, - - // Total shift operations supported. - parameter SHIFT_OPS = 6, - - // Number of physical registers. - parameter PHY_REGS = 46 -) -( - output reg [64*8-1:0] o_decompile, // For debug purposes. - - // ------------------- - // Inputs. - // ------------------- - - // Clock and reset. - input wire i_clk, - input wire i_reset, - - // Branch state. - input wire [1:0] i_taken, - - // Thumb undefined. - input wire i_thumb_und, - - // Force 32-bit - input wire i_force32align, - - // Clear and stall signals. High to low priority. - input wire i_clear_from_writeback, // | Priority - input wire i_data_stall, // | - input wire i_clear_from_alu, // | - input wire i_stall_from_shifter, // | - input wire i_stall_from_issue, // V - - // Interrupt events. - input wire i_irq, - input wire i_fiq, - input wire i_abt, - - // PC input. - input wire [31:0] i_pc_ff, - input wire [31:0] i_pc_plus_8_ff, - - // CPU mode. Taken from CPSR. - input wire [4:0] i_cpsr_ff_mode, // Mode. - input wire i_cpsr_ff_i, // IRQ state. - input wire i_cpsr_ff_f, // FIQ state. - - // Instruction input. - input wire [35:0] i_instruction, - input wire i_instruction_valid, - - // ------------------------ - // Outputs. - // ------------------------ - - // This signal is used to check the validity of a pipeline stage. - output reg [3:0] o_condition_code_ff, - - // - // Where the primary output of the instruction must go to. Make this RAZ - // to throw away the primary output to a void. - // - output reg [$clog2(PHY_REGS)-1:0] o_destination_index_ff, - - // - // The ALU source is the source that is fed directly to the ALU without the - // barrel shifter. For multiplication, o_alu_source simply becomes an operand. - // For alu_source_ff, if bit 32 is 1, then [31:0] is a constant else - // [31:0] is a register index (lower 6-bit effectively). - // - output reg [32:0] o_alu_source_ff, - output reg [$clog2(ALU_OPS)-1:0] o_alu_operation_ff, - - // - // Stuff related to the shifter. For multiplication, the source and length - // simply become two operands. For shift_source_ff and shift_length_ff, - // bit 32 has the same meaning as for o_alu_source_ff. - // - output reg [32:0] o_shift_source_ff, - output reg [$clog2(SHIFT_OPS)-1:0] o_shift_operation_ff, - output reg [32:0] o_shift_length_ff, - - // - // Update the flags. Note that writing to CPSR will cause a flag-update (if - // you asked for) even if this is 0. - // - output reg o_flag_update_ff, - - // Things related to memory operations. - - // - // Data register index. Register is read - // for stores and written for loads. - // - output reg [$clog2(PHY_REGS)-1:0] o_mem_srcdest_index_ff, - - // Load or store. - output reg o_mem_load_ff, - output reg o_mem_store_ff, - - // Indicate pre-ALU tap for address since pre-index. - output reg o_mem_pre_index_ff, - - // Access size and type. - - // Unsigned byte access. - output reg o_mem_unsigned_byte_enable_ff, - - // Signed byte access. - output reg o_mem_signed_byte_enable_ff, - - // Signed halfword access. - output reg o_mem_signed_halfword_enable_ff, - - // Unsigned halfword access. - output reg o_mem_unsigned_halfword_enable_ff, - - // Force user view of memory. - output reg o_mem_translate_ff, - - // PC output. Simply clocked out. - output reg [31:0] o_pc_plus_8_ff, - output reg [31:0] o_pc_ff, - - // Switch. - output reg o_switch_ff, - - // Interrupts. - output reg o_irq_ff, // Goes through mask. - output reg o_fiq_ff, // Goes through mask. - output reg o_abt_ff, // Clocked out. - output reg o_und_ff, // Undefined instr. - output reg o_swi_ff, // SWI encountered. - // EXECUTE tests for condition validity and triggers SWI. - - // Force 32-bit alignment on memory accesses. Simply clocked out. - output reg o_force32align_ff, - - // Branch state. Simply clocked out. - output reg [1:0] o_taken_ff -); - -// ---------------------------------------------------------------------------- - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -wire [3:0] o_condition_code_nxt; -wire [$clog2(PHY_REGS )-1:0] o_destination_index_nxt; -wire [32:0] o_alu_source_nxt; -wire [$clog2(ALU_OPS)-1:0] o_alu_operation_nxt; -wire [32:0] o_shift_source_nxt; -wire [$clog2(SHIFT_OPS)-1:0] o_shift_operation_nxt; -wire [32:0] o_shift_length_nxt; -wire o_flag_update_nxt; -wire [$clog2(PHY_REGS )-1:0] o_mem_srcdest_index_nxt; // Data register. -wire o_mem_load_nxt; // Type of operation... -wire o_mem_store_nxt; -wire o_mem_pre_index_nxt; // Indicate pre-ALU tap for address. -wire o_mem_unsigned_byte_enable_nxt;// Byte enable (unsigned). -wire o_mem_signed_byte_enable_nxt; -wire o_mem_signed_halfword_enable_nxt; -wire o_mem_unsigned_halfword_enable_nxt; -wire o_mem_translate_nxt; // Force user's view of memory. -wire o_force_locked_access_nxt; -wire o_irq_nxt; -wire o_fiq_nxt; -wire o_abt_nxt; -reg o_swi_nxt; -wire o_und_nxt; -wire o_switch_nxt; - -wire [$clog2(ARCH_REGS)-1:0] destination_index_nxt; -wire [32:0] alu_source_nxt; -wire [32:0] shift_source_nxt; -wire [32:0] shift_length_nxt; -wire [$clog2(ARCH_REGS)-1:0] mem_srcdest_index_nxt; - -// ---------------------------------------------------------------------------- - -// Abort -assign o_abt_nxt = (i_abt || i_thumb_und) && i_instruction_valid; - -// IRQ and FIQ next state. -assign o_irq_nxt = i_irq & !i_cpsr_ff_i; // Pass only when mask is 0. -assign o_fiq_nxt = i_fiq & !i_cpsr_ff_f; // Pass only when mask is 0. - -// -// This section translates the indices from the decode stage converts -// into a physical index. This is needed because the decode.v module extracts -// architectural register numbers. -// -assign o_destination_index_nxt = // Always a register so no need for IMMED_EN. - translate ( destination_index_nxt, i_cpsr_ff_mode ); - -assign o_alu_source_nxt = - (alu_source_nxt[32] == IMMED_EN ) ? // Constant...? - alu_source_nxt : // Pass constant on. - translate ( alu_source_nxt, i_cpsr_ff_mode ); // Translate index. - -assign o_shift_source_nxt = - (shift_source_nxt[32] == IMMED_EN ) ? // Constant...? - shift_source_nxt : // Pass constant on. - translate ( shift_source_nxt, i_cpsr_ff_mode ); // Translate index. - -assign o_shift_length_nxt = - (shift_length_nxt[32] == IMMED_EN ) ? // Constant...? - shift_length_nxt : // Pass constant on. - translate ( shift_length_nxt, i_cpsr_ff_mode ); // Translate index. - -assign o_mem_srcdest_index_nxt = // Always a register so no need for IMMED_EN. - translate ( mem_srcdest_index_nxt, i_cpsr_ff_mode ); - - -// ---------------------------------------------------------------------------- - -// -// The actual decision whether or not to execute this is taken in EX stage. -// At this point, we don't do anything with the SWI except take note. -// -always @* - o_swi_nxt = &i_instruction[27:24]; - -// ---------------------------------------------------------------------------- - -wire [64*8-1:0] decompile_tmp; - -// Flop the outputs to break the pipeline at this point. -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - clear; - end - else if ( i_clear_from_writeback ) - begin - clear; - end - else if ( i_data_stall ) - begin - // Preserve state. - end - else if ( i_clear_from_alu ) - begin - clear; - end - else if ( i_stall_from_shifter ) - begin - // Preserve state. - end - else if ( i_stall_from_issue ) - begin - // Preserve state. - end - // If no stall, only then update... - else - begin - o_irq_ff <= o_irq_nxt; - o_fiq_ff <= o_fiq_nxt; - o_swi_ff <= o_swi_nxt; - o_abt_ff <= o_abt_nxt; - o_und_ff <= o_und_nxt; - o_condition_code_ff <= o_condition_code_nxt; - o_destination_index_ff <= o_destination_index_nxt; - o_alu_source_ff <= o_alu_source_nxt; - o_alu_operation_ff <= o_alu_operation_nxt; - o_shift_source_ff <= o_shift_source_nxt; - o_shift_operation_ff <= o_shift_operation_nxt; - o_shift_length_ff <= o_shift_length_nxt; - o_flag_update_ff <= o_flag_update_nxt; - o_mem_srcdest_index_ff <= o_mem_srcdest_index_nxt; - o_mem_load_ff <= o_mem_load_nxt; - o_mem_store_ff <= o_mem_store_nxt; - o_mem_pre_index_ff <= o_mem_pre_index_nxt; - o_mem_unsigned_byte_enable_ff <= o_mem_unsigned_byte_enable_nxt; - o_mem_signed_byte_enable_ff <= o_mem_signed_byte_enable_nxt; - o_mem_signed_halfword_enable_ff <= o_mem_signed_halfword_enable_nxt; - o_mem_unsigned_halfword_enable_ff <= o_mem_unsigned_halfword_enable_nxt; - o_mem_translate_ff <= o_mem_translate_nxt; - o_pc_plus_8_ff <= i_pc_plus_8_ff; - o_pc_ff <= i_pc_ff; - o_switch_ff <= o_switch_nxt; - o_force32align_ff <= i_force32align; - o_taken_ff <= i_taken; - - // For debug - o_decompile <= decompile_tmp; - end -end - -// ---------------------------------------------------------------------------- - -task clear; // Clear and refresh the unit. Clear everything and a set a dummy - // output to NV acting like a reset. -begin - o_irq_ff <= 0; - o_fiq_ff <= 0; - o_swi_ff <= 0; - o_abt_ff <= 0; - o_condition_code_ff <= NV; - o_und_ff <= 0; - o_taken_ff <= 0; -end -endtask - -// ---------------------------------------------------------------------------- - -// Bulk of the decode logic is here. -zap_decode #( - .ARCH_REGS (ARCH_REGS), - .ALU_OPS (ALU_OPS), - .SHIFT_OPS (SHIFT_OPS) -) -u_zap_decode ( - .i_irq(i_irq), - .i_fiq(i_fiq), - .i_abt(i_abt), - .i_instruction(i_instruction), - .i_instruction_valid(i_instruction_valid), - .i_cpsr_ff_mode(i_cpsr_ff_mode), - .o_condition_code(o_condition_code_nxt), - .o_destination_index(destination_index_nxt), - .o_alu_source(alu_source_nxt), - .o_alu_operation(o_alu_operation_nxt), - .o_shift_source(shift_source_nxt), - .o_shift_operation(o_shift_operation_nxt), - .o_shift_length(shift_length_nxt), - .o_flag_update(o_flag_update_nxt), - .o_mem_srcdest_index(mem_srcdest_index_nxt), - .o_mem_load(o_mem_load_nxt), - .o_mem_store(o_mem_store_nxt), - .o_mem_pre_index(o_mem_pre_index_nxt), - .o_mem_unsigned_byte_enable(o_mem_unsigned_byte_enable_nxt), - .o_mem_signed_byte_enable(o_mem_signed_byte_enable_nxt), - .o_mem_signed_halfword_enable(o_mem_signed_halfword_enable_nxt), - .o_mem_unsigned_halfword_enable(o_mem_unsigned_halfword_enable_nxt), - .o_mem_translate(o_mem_translate_nxt), - .o_und(o_und_nxt), - .o_switch(o_switch_nxt) -); - -// ------------------------------------------------------------------------------- - -// Decompile - - -zap_decompile u_zap_decompile ( - .i_instruction (i_instruction), - .i_dav (i_instruction_valid), - .o_decompile (decompile_tmp) -); - - -endmodule // zap_decode_main.v -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_core.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_core.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_core.v (nonexistent) @@ -1,1201 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This is the ZAP core which contains the bare processor core without any -- -// -- cache or MMU. In other words, this is the bare pipeline. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_core #( - // Number of branch predictor entries. - parameter [31:0] BP_ENTRIES = 1024, - - // Depth of FIFO. - parameter [31:0] FIFO_DEPTH = 4 -) -( - -// ------------------------------------------------ -// Clock and reset. Reset is synchronous. -// ------------------------------------------------ - -input wire i_clk, -input wire i_reset, - -// ------------------------------------------------- -// Wishbone memory access for data. -// ------------------------------------------------- - -output wire o_data_wb_we, -output wire o_data_wb_cyc, -output wire o_data_wb_stb, -output wire[31:0] o_data_wb_adr, -input wire i_data_wb_ack, -input wire i_data_wb_err, -input wire [31:0] i_data_wb_dat, -output wire [31:0] o_data_wb_dat, -output wire [3:0] o_data_wb_sel, - -// Next state stuff for Wishbone data. -output wire o_data_wb_we_nxt, -output wire o_data_wb_cyc_nxt, -output wire o_data_wb_stb_nxt, -output wire [31:0] o_data_wb_dat_nxt, -output wire [3:0] o_data_wb_sel_nxt, -output wire [31:0] o_data_wb_adr_nxt, - -// Force user view. -output wire o_mem_translate, - -// -------------------------------------------------- -// Interrupts. Active high. -// -------------------------------------------------- - -input wire i_fiq, // FIQ signal. -input wire i_irq, // IRQ signal. - -// --------------------------------------------------- -// Wishbone instruction access ports. -// --------------------------------------------------- - -output wire [31:0] o_instr_wb_adr, // Code address. -output wire o_instr_wb_cyc, // Always 1. -output wire o_instr_wb_stb, // Always 1. -output wire o_instr_wb_we, // Always 0. -input wire [31:0] i_instr_wb_dat, // A 32-bit ZAP instruction. -input wire i_instr_wb_ack, // Instruction available. -input wire i_instr_wb_err, // Instruction abort fault. Given with ack = 1. -output wire [3:0] o_instr_wb_sel, // wishbone byte select. - -// Instruction wishbone nxt ports. -output wire [31:0] o_instr_wb_adr_nxt, -output wire o_instr_wb_stb_nxt, - -// Determines user or supervisory mode. Cache must use this for VM. -output wire [31:0] o_cpsr, - -// ----------------------------------------------------- -// For MMU/cache connectivity. -// ----------------------------------------------------- - -input wire [31:0] i_fsr, -input wire [31:0] i_far, -output wire [31:0] o_dac, -output wire [31:0] o_baddr, -output wire o_mmu_en, -output wire [1:0] o_sr, -output wire o_pid, -output wire o_dcache_inv, -output wire o_icache_inv, -output wire o_dcache_clean, -output wire o_icache_clean, -output wire o_dtlb_inv, -output wire o_itlb_inv, -output wire o_dcache_en, -output wire o_icache_en, -input wire i_dcache_inv_done, -input wire i_icache_inv_done, -input wire i_dcache_clean_done, -input wire i_icache_clean_done -); - -// ---------------------------------------------------------------------------- - -`include "zap_localparams.vh" -`include "zap_defines.vh" -`include "zap_functions.vh" - -localparam ARCH_REGS = 32; -localparam ALU_OPS = 32; -localparam SHIFT_OPS = 7; -localparam PHY_REGS = TOTAL_PHY_REGS; -localparam FLAG_WDT = 32; - -// ---------------------------------------------------------------------------- - -// Low Bandwidth Coprocessor (COP) I/F to CP15 control block. -wire copro_done; // COP done. -wire copro_dav; // COP command valid. -wire [31:0] copro_word; // COP command. -wire copro_reg_en; // COP controls registers. -wire [$clog2(PHY_REGS)-1:0] copro_reg_wr_index;// Reg. file write index. -wire [$clog2(PHY_REGS)-1:0] copro_reg_rd_index;// Reg. file read index. -wire [31:0] copro_reg_wr_data; // Reg. file write data. -wire [31:0] copro_reg_rd_data; // Reg. file read data. - -wire reset; // Tied to i_reset. -wire shelve; // From writeback. -wire fiq; // Tied to FIQ. -wire irq; // Tied to IRQ. - -// Clear and stall signals. -wire stall_from_decode; -wire clear_from_alu; -wire stall_from_issue; -wire clear_from_writeback; -wire data_stall; -wire code_stall; -wire instr_valid; -wire pipeline_is_not_empty; - -// Fetch -wire [31:0] fetch_instruction; // Instruction from the fetch unit. -wire fetch_valid; // Instruction valid from the fetch unit. -wire fetch_instr_abort; // abort indicator. -wire [31:0] fetch_pc_plus_8_ff; // PC + 8 generated from the fetch unit. -wire [31:0] fetch_pc_ff; // PC generated from fetch unit. -wire [1:0] fetch_bp_state; - -// FIFO. -wire [31:0] fifo_pc_plus_8; -wire fifo_valid; -wire fifo_instr_abort; -wire [31:0] fifo_instruction; -wire [1:0] fifo_bp_state; - -// Predecode -wire [31:0] predecode_pc_plus_8; -wire [31:0] predecode_pc; -wire predecode_irq; -wire predecode_fiq; -wire predecode_abt; -wire [35:0] predecode_inst; -wire predecode_val; -wire predecode_force32; -wire predecode_und; -wire [1:0] predecode_taken; - -// Compressed decoder. -wire thumb_irq; -wire thumb_fiq; -wire thumb_iabort; -wire [34:0] thumb_instruction; -wire thumb_valid; -wire thumb_und; -wire thumb_force32; -wire [1:0] thumb_bp_state; -wire [31:0] thumb_pc_ff; -wire [31:0] thumb_pc_plus_8_ff; - -// Decode -wire [3:0] decode_condition_code; -wire [$clog2(PHY_REGS)-1:0] decode_destination_index; -wire [32:0] decode_alu_source_ff; -wire [$clog2(ALU_OPS)-1:0] decode_alu_operation_ff; -wire [32:0] decode_shift_source_ff; -wire [$clog2(SHIFT_OPS)-1:0] decode_shift_operation_ff; -wire [32:0] decode_shift_length_ff; -wire decode_flag_update_ff; -wire [$clog2(PHY_REGS)-1:0] decode_mem_srcdest_index_ff; -wire decode_mem_load_ff; -wire decode_mem_store_ff; -wire decode_mem_pre_index_ff; -wire decode_mem_unsigned_byte_enable_ff; -wire decode_mem_signed_byte_enable_ff; -wire decode_mem_signed_halfword_enable_ff; -wire decode_mem_unsigned_halfword_enable_ff; -wire decode_mem_translate_ff; -wire decode_irq_ff; -wire decode_fiq_ff; -wire decode_abt_ff; -wire decode_swi_ff; -wire [31:0] decode_pc_plus_8_ff; -wire [31:0] decode_pc_ff; -wire decode_switch_ff; -wire decode_force32_ff; -wire decode_und_ff; -wire clear_from_decode; -wire [31:0] pc_from_decode; -wire [1:0] decode_taken_ff; - -// Issue -wire [$clog2(PHY_REGS)-1:0] issue_rd_index_0, - issue_rd_index_1, - issue_rd_index_2, - issue_rd_index_3; - -wire [3:0] issue_condition_code_ff; -wire [$clog2(PHY_REGS)-1:0] issue_destination_index_ff; -wire [$clog2(ALU_OPS)-1:0] issue_alu_operation_ff; -wire [$clog2(SHIFT_OPS)-1:0] issue_shift_operation_ff; -wire issue_flag_update_ff; -wire [$clog2(PHY_REGS)-1:0] issue_mem_srcdest_index_ff; -wire issue_mem_load_ff; -wire issue_mem_store_ff; -wire issue_mem_pre_index_ff; -wire issue_mem_unsigned_byte_enable_ff; -wire issue_mem_signed_byte_enable_ff; -wire issue_mem_signed_halfword_enable_ff; -wire issue_mem_unsigned_halfword_enable_ff; -wire issue_mem_translate_ff; -wire issue_irq_ff; -wire issue_fiq_ff; -wire issue_abt_ff; -wire issue_swi_ff; -wire [31:0] issue_alu_source_value_ff; -wire [31:0] issue_shift_source_value_ff; -wire [31:0] issue_shift_length_value_ff; -wire [31:0] issue_mem_srcdest_value_ff; -wire [32:0] issue_alu_source_ff; -wire [32:0] issue_shift_source_ff; -wire [31:0] issue_pc_plus_8_ff; -wire [31:0] issue_pc_ff; -wire issue_shifter_disable_ff; -wire issue_switch_ff; -wire issue_force32_ff; -wire issue_und_ff; -wire [1:0] issue_taken_ff; - -wire [$clog2(PHY_REGS)-1:0] rd_index_0; -wire [$clog2(PHY_REGS)-1:0] rd_index_1; -wire [$clog2(PHY_REGS)-1:0] rd_index_2; -wire [$clog2(PHY_REGS)-1:0] rd_index_3; - -// Shift -wire [$clog2(PHY_REGS)-1:0] shifter_mem_srcdest_index_ff; -wire shifter_mem_load_ff; -wire shifter_mem_store_ff; -wire shifter_mem_pre_index_ff; -wire shifter_mem_unsigned_byte_enable_ff; -wire shifter_mem_signed_byte_enable_ff; -wire shifter_mem_signed_halfword_enable_ff; -wire shifter_mem_unsigned_halfword_enable_ff; -wire shifter_mem_translate_ff; -wire [3:0] shifter_condition_code_ff; -wire [$clog2(PHY_REGS)-1:0] shifter_destination_index_ff; -wire [$clog2(ALU_OPS)-1:0] shifter_alu_operation_ff; -wire shifter_nozero_ff; -wire shifter_flag_update_ff; -wire [31:0] shifter_mem_srcdest_value_ff; -wire [31:0] shifter_alu_source_value_ff; -wire [31:0] shifter_shifted_source_value_ff; -wire shifter_shift_carry_ff; -wire [31:0] shifter_pc_plus_8_ff; -wire [31:0] shifter_pc_ff; -wire shifter_irq_ff; -wire shifter_fiq_ff; -wire shifter_abt_ff; -wire shifter_swi_ff; -wire shifter_switch_ff; -wire shifter_force32_ff; -wire shifter_und_ff; -wire stall_from_shifter; -wire [1:0] shifter_taken_ff; - -// ALU -wire [$clog2(SHIFT_OPS)-1:0] alu_shift_operation_ff; -wire [31:0] alu_alu_result_nxt; -wire [31:0] alu_alu_result_ff; -wire alu_abt_ff; -wire alu_irq_ff; -wire alu_fiq_ff; -wire alu_swi_ff; -wire alu_dav_ff; -wire alu_dav_nxt; -wire [31:0] alu_pc_plus_8_ff; -wire [31:0] pc_from_alu; -wire [$clog2(PHY_REGS)-1:0] alu_destination_index_ff; -wire [FLAG_WDT-1:0] alu_flags_ff; -wire [$clog2(PHY_REGS)-1:0] alu_mem_srcdest_index_ff; -wire alu_mem_load_ff; -wire alu_und_ff; -wire [31:0] alu_cpsr_nxt; -wire confirm_from_alu; -wire alu_sbyte_ff; -wire alu_ubyte_ff; -wire alu_shalf_ff; -wire alu_uhalf_ff; -wire [31:0] alu_address_ff; -wire [31:0] alu_address_nxt; - -// Memory -wire [31:0] memory_alu_result_ff; -wire [$clog2(PHY_REGS)-1:0] memory_destination_index_ff; -wire [$clog2(PHY_REGS)-1:0] memory_mem_srcdest_index_ff; -wire memory_dav_ff; -wire [31:0] memory_pc_plus_8_ff; -wire memory_irq_ff; -wire memory_fiq_ff; -wire memory_swi_ff; -wire memory_instr_abort_ff; -wire memory_mem_load_ff; -wire [FLAG_WDT-1:0] memory_flags_ff; -wire [31:0] memory_mem_rd_data; -wire memory_und_ff; -wire memory_data_abt_ff; - -// Writeback -wire [31:0] rd_data_0; -wire [31:0] rd_data_1; -wire [31:0] rd_data_2; -wire [31:0] rd_data_3; -wire [31:0] cpsr_nxt, cpsr; - -// Hijack interface - related to Writeback - ALU interaction. -wire wb_hijack; -wire [31:0] wb_hijack_op1; -wire [31:0] wb_hijack_op2; -wire wb_hijack_cin; -wire [31:0] alu_hijack_sum; - -// Decompile chain for debugging. -wire [64*8-1:0] decode_decompile; -wire [64*8-1:0] issue_decompile; -wire [64*8-1:0] shifter_decompile; -wire [64*8-1:0] alu_decompile; -wire [64*8-1:0] memory_decompile; -wire [64*8-1:0] rb_decompile; - -// ---------------------------------------------------------------------------- - -assign o_cpsr = alu_flags_ff; -assign o_data_wb_adr = {alu_address_ff[31:2], 2'd0}; -assign o_data_wb_adr_nxt = {alu_address_nxt[31:2], 2'd0}; -assign o_instr_wb_we = 1'd0; -assign o_instr_wb_sel = 4'b1111; -assign reset = i_reset; -assign irq = i_irq; -assign fiq = i_fiq; -assign data_stall = o_data_wb_stb && o_data_wb_cyc && !i_data_wb_ack; -assign code_stall = (!o_instr_wb_stb && !o_instr_wb_cyc) || !i_instr_wb_ack; -assign instr_valid = o_instr_wb_stb && o_instr_wb_cyc && i_instr_wb_ack & !shelve; -assign pipeline_is_not_empty = predecode_val || - (decode_condition_code != NV) || - (issue_condition_code_ff != NV) || - (shifter_condition_code_ff!= NV) || - alu_dav_ff || - memory_dav_ff; - -// ---------------------------------------------------------------------------- - -// ========================= -// FETCH STAGE -// ========================= -zap_fetch_main -#( - .BP_ENTRIES(BP_ENTRIES) -) -u_zap_fetch_main ( - // Input. - .i_clk (i_clk), - .i_reset (reset), - - .i_code_stall (code_stall), - - .i_clear_from_writeback (clear_from_writeback), - .i_clear_from_decode (clear_from_decode), - - .i_data_stall (1'd0), - - .i_clear_from_alu (clear_from_alu), - - .i_stall_from_shifter (1'd0), - .i_stall_from_issue (1'd0), - .i_stall_from_decode (1'd0), - - .i_pc_ff (o_instr_wb_adr), - .i_instruction (i_instr_wb_dat), - .i_valid (instr_valid), - .i_instr_abort (i_instr_wb_err), - - .i_cpsr_ff_t (alu_flags_ff[T]), - - // Output. - .o_instruction (fetch_instruction), - .o_valid (fetch_valid), - .o_instr_abort (fetch_instr_abort), - .o_pc_plus_8_ff (fetch_pc_plus_8_ff), - .o_pc_ff (fetch_pc_ff), - - - .i_confirm_from_alu (confirm_from_alu), - .i_pc_from_alu (shifter_pc_ff), - .i_taken (shifter_taken_ff), - .o_taken (fetch_bp_state) -); - -// ========================= -// FIFO. -// ========================= -zap_fifo -#( .WDT(67), .DEPTH(FIFO_DEPTH) ) U_ZAP_FIFO ( - .i_clk (i_clk), - .i_reset (i_reset), - .i_clear_from_writeback (clear_from_writeback), - - .i_write_inhibit ( code_stall ), - .i_data_stall ( data_stall ), - - .i_clear_from_alu (clear_from_alu), - .i_stall_from_shifter (stall_from_shifter), - .i_stall_from_issue (stall_from_issue), - .i_stall_from_decode (stall_from_decode), - .i_clear_from_decode (clear_from_decode), - - .i_instr ({fetch_pc_plus_8_ff, fetch_instr_abort, fetch_instruction, fetch_bp_state}), - .i_valid (fetch_valid), - .o_instr ({fifo_pc_plus_8, fifo_instr_abort, fifo_instruction, fifo_bp_state}), - .o_valid (fifo_valid), - - .o_wb_stb (o_instr_wb_stb), - .o_wb_stb_nxt (o_instr_wb_stb_nxt), - .o_wb_cyc (o_instr_wb_cyc) -); - -// ========================= -// COMPRESSED DECODER STAGE -// ========================= -zap_thumb_decoder u_zap_thumb_decoder ( -.i_clk (i_clk), -.i_reset (i_reset), -.i_clear_from_writeback (clear_from_writeback), -.i_data_stall (data_stall), -.i_clear_from_alu (clear_from_alu), -.i_stall_from_shifter (stall_from_shifter), -.i_stall_from_issue (stall_from_issue), -.i_stall_from_decode (stall_from_decode), -.i_clear_from_decode (clear_from_decode), - -.i_taken (fifo_bp_state), -.i_instruction (fifo_instruction), -.i_instruction_valid (fifo_valid), -.i_irq (fifo_valid ? irq && !alu_flags_ff[I] : 1'd0), // Pass interrupt only if mask = 0 and instruction exists. -.i_fiq (fifo_valid ? fiq && !alu_flags_ff[F] : 1'd0), // Pass interrupt only if mask = 0 and instruction exists. -.i_iabort (fifo_instr_abort), -.o_iabort (thumb_iabort), -.i_cpsr_ff_t (alu_flags_ff[T]), -.i_pc_ff (alu_flags_ff[T] ? fifo_pc_plus_8 - 32'd4 : fifo_pc_plus_8 - 32'd8), -.i_pc_plus_8_ff (fifo_pc_plus_8), - -.o_instruction (thumb_instruction), -.o_instruction_valid (thumb_valid), -.o_und (thumb_und), -.o_force32_align (thumb_force32), -.o_pc_ff (thumb_pc_ff), -.o_pc_plus_8_ff (thumb_pc_plus_8_ff), -.o_irq (thumb_irq), -.o_fiq (thumb_fiq), -.o_taken_ff (thumb_bp_state) -); - -// ========================= -// PREDECODE STAGE -// ========================= -zap_predecode_main #( - .ARCH_REGS(ARCH_REGS), - .PHY_REGS(PHY_REGS), - .SHIFT_OPS(SHIFT_OPS), - .ALU_OPS(ALU_OPS), - .COPROCESSOR_INTERFACE_ENABLE(1'd1), - .COMPRESSED_EN(1'd1) -) -u_zap_predecode ( - // Input. - .i_clk (i_clk), - .i_reset (reset), - - .i_clear_from_writeback (clear_from_writeback), - .i_data_stall (data_stall), - .i_clear_from_alu (clear_from_alu), - .i_stall_from_shifter (stall_from_shifter), - .i_stall_from_issue (stall_from_issue), - - .i_irq (thumb_irq), - .i_fiq (thumb_fiq), - - .i_abt (thumb_iabort), - .i_pc_plus_8_ff (thumb_pc_plus_8_ff), - .i_pc_ff (thumb_pc_plus_8_ff - 32'd8), - - .i_cpu_mode_t (alu_flags_ff[T]), - .i_cpu_mode_mode (alu_flags_ff[`CPSR_MODE]), - - .i_instruction (thumb_instruction), - .i_instruction_valid (thumb_valid), - .i_taken (thumb_bp_state), - - .i_force32 (thumb_force32), - .i_und (thumb_und), - - .i_copro_done (copro_done), - .i_pipeline_dav (pipeline_is_not_empty), - - // Output. - .o_stall_from_decode (stall_from_decode), - .o_pc_plus_8_ff (predecode_pc_plus_8), - - .o_pc_ff (predecode_pc), - .o_irq_ff (predecode_irq), - .o_fiq_ff (predecode_fiq), - .o_abt_ff (predecode_abt), - .o_und_ff (predecode_und), - - .o_force32align_ff (predecode_force32), - - .o_copro_dav_ff (copro_dav), - .o_copro_word_ff (copro_word), - - .o_clear_from_decode (clear_from_decode), - .o_pc_from_decode (pc_from_decode), - - .o_instruction_ff (predecode_inst), - .o_instruction_valid_ff (predecode_val), - - .o_taken_ff (predecode_taken) -); - -// ===================== -// DECODE STAGE -// ===================== - -zap_decode_main #( - .ARCH_REGS(ARCH_REGS), - .PHY_REGS(PHY_REGS), - .SHIFT_OPS(SHIFT_OPS), - .ALU_OPS(ALU_OPS) -) -u_zap_decode_main ( - .o_decompile (decode_decompile), - - // Input. - .i_clk (i_clk), - .i_reset (reset), - - .i_clear_from_writeback (clear_from_writeback), - .i_data_stall (data_stall), - .i_clear_from_alu (clear_from_alu), - .i_stall_from_shifter (stall_from_shifter), - .i_stall_from_issue (stall_from_issue), - .i_thumb_und (predecode_und), - .i_irq (predecode_irq), - .i_fiq (predecode_fiq), - .i_abt (predecode_abt), - .i_pc_plus_8_ff (predecode_pc_plus_8), - .i_pc_ff (predecode_pc), - - .i_cpsr_ff_mode (alu_flags_ff[`CPSR_MODE]), - .i_cpsr_ff_i (alu_flags_ff[I]), - .i_cpsr_ff_f (alu_flags_ff[F]), - - .i_instruction (predecode_inst), - .i_instruction_valid (predecode_val), - .i_taken (predecode_taken), - .i_force32align (predecode_force32), - - // Output. - .o_condition_code_ff (decode_condition_code), - .o_destination_index_ff (decode_destination_index), - .o_alu_source_ff (decode_alu_source_ff), - .o_alu_operation_ff (decode_alu_operation_ff), - .o_shift_source_ff (decode_shift_source_ff), - .o_shift_operation_ff (decode_shift_operation_ff), - .o_shift_length_ff (decode_shift_length_ff), - .o_flag_update_ff (decode_flag_update_ff), - .o_mem_srcdest_index_ff (decode_mem_srcdest_index_ff), - .o_mem_load_ff (decode_mem_load_ff), - .o_mem_store_ff (decode_mem_store_ff), - .o_mem_pre_index_ff (decode_mem_pre_index_ff), - .o_mem_unsigned_byte_enable_ff (decode_mem_unsigned_byte_enable_ff), - .o_mem_signed_byte_enable_ff (decode_mem_signed_byte_enable_ff), - .o_mem_signed_halfword_enable_ff(decode_mem_signed_halfword_enable_ff), - .o_mem_unsigned_halfword_enable_ff (decode_mem_unsigned_halfword_enable_ff), - .o_mem_translate_ff (decode_mem_translate_ff), - .o_pc_plus_8_ff (decode_pc_plus_8_ff), - .o_pc_ff (decode_pc_ff), - .o_switch_ff (decode_switch_ff), - .o_irq_ff (decode_irq_ff), - .o_fiq_ff (decode_fiq_ff), - .o_abt_ff (decode_abt_ff), - .o_swi_ff (decode_swi_ff), - .o_und_ff (decode_und_ff), - .o_force32align_ff (decode_force32_ff), - .o_taken_ff (decode_taken_ff) -); - -// ================== -// ISSUE -// ================== - -zap_issue_main #( - .PHY_REGS(PHY_REGS), - .SHIFT_OPS(SHIFT_OPS), - .ALU_OPS(ALU_OPS) - -) -u_zap_issue_main -( - .i_decompile(decode_decompile), - .o_decompile(issue_decompile), - - .i_und_ff(decode_und_ff), - .o_und_ff(issue_und_ff), - - .i_taken_ff(decode_taken_ff), - .o_taken_ff(issue_taken_ff), - - .i_pc_ff(decode_pc_ff), - .o_pc_ff(issue_pc_ff), - - // Inputs - .i_clk (i_clk), - .i_reset (reset), - .i_clear_from_writeback (clear_from_writeback), - .i_stall_from_shifter (stall_from_shifter), - .i_data_stall (data_stall), - .i_clear_from_alu (clear_from_alu), - .i_pc_plus_8_ff (decode_pc_plus_8_ff), - .i_condition_code_ff (decode_condition_code), - .i_destination_index_ff (decode_destination_index), - .i_alu_source_ff (decode_alu_source_ff), - .i_alu_operation_ff (decode_alu_operation_ff), - .i_shift_source_ff (decode_shift_source_ff), - .i_shift_operation_ff (decode_shift_operation_ff), - .i_shift_length_ff (decode_shift_length_ff), - .i_flag_update_ff (decode_flag_update_ff), - .i_mem_srcdest_index_ff (decode_mem_srcdest_index_ff), - .i_mem_load_ff (decode_mem_load_ff), - .i_mem_store_ff (decode_mem_store_ff), - .i_mem_pre_index_ff (decode_mem_pre_index_ff), - .i_mem_unsigned_byte_enable_ff (decode_mem_unsigned_byte_enable_ff), - .i_mem_signed_byte_enable_ff (decode_mem_signed_byte_enable_ff), - .i_mem_signed_halfword_enable_ff(decode_mem_signed_halfword_enable_ff), - .i_mem_unsigned_halfword_enable_ff(decode_mem_unsigned_halfword_enable_ff), - .i_mem_translate_ff (decode_mem_translate_ff), - .i_irq_ff (decode_irq_ff), - .i_fiq_ff (decode_fiq_ff), - .i_abt_ff (decode_abt_ff), - .i_swi_ff (decode_swi_ff), - .i_cpu_mode (alu_flags_ff), - // Needed to resolve CPSR refs. - - .i_force32align_ff (decode_force32_ff), - .o_force32align_ff (issue_force32_ff), - - // Register file. - .i_rd_data_0 (rd_data_0), - .i_rd_data_1 (rd_data_1), - .i_rd_data_2 (rd_data_2), - .i_rd_data_3 (rd_data_3), - - // Feedback. - .i_shifter_destination_index_ff (shifter_destination_index_ff), - .i_alu_destination_index_ff (alu_destination_index_ff), - .i_memory_destination_index_ff (memory_destination_index_ff), - .i_alu_dav_nxt (alu_dav_nxt), - .i_alu_dav_ff (alu_dav_ff), - .i_memory_dav_ff (memory_dav_ff), - .i_alu_destination_value_nxt (alu_alu_result_nxt), - .i_alu_destination_value_ff (alu_alu_result_ff), - .i_memory_destination_value_ff (memory_alu_result_ff), - .i_shifter_mem_srcdest_index_ff (shifter_mem_srcdest_index_ff), - .i_alu_mem_srcdest_index_ff (alu_mem_srcdest_index_ff), - .i_memory_mem_srcdest_index_ff (memory_mem_srcdest_index_ff), - .i_shifter_mem_load_ff (shifter_mem_load_ff), - .i_alu_mem_load_ff (alu_mem_load_ff), - .i_memory_mem_load_ff (memory_mem_load_ff), - .i_memory_mem_srcdest_value_ff (memory_mem_rd_data), - - // Switch indicator. - .i_switch_ff (decode_switch_ff), - .o_switch_ff (issue_switch_ff), - - // Outputs. - .o_rd_index_0 (rd_index_0), - .o_rd_index_1 (rd_index_1), - .o_rd_index_2 (rd_index_2), - .o_rd_index_3 (rd_index_3), - .o_condition_code_ff (issue_condition_code_ff), - .o_destination_index_ff (issue_destination_index_ff), - .o_alu_operation_ff (issue_alu_operation_ff), - .o_shift_operation_ff (issue_shift_operation_ff), - .o_flag_update_ff (issue_flag_update_ff), - .o_mem_srcdest_index_ff (issue_mem_srcdest_index_ff), - .o_mem_load_ff (issue_mem_load_ff), - .o_mem_store_ff (issue_mem_store_ff), - .o_mem_pre_index_ff (issue_mem_pre_index_ff), - .o_mem_unsigned_byte_enable_ff (issue_mem_unsigned_byte_enable_ff), - .o_mem_signed_byte_enable_ff (issue_mem_signed_byte_enable_ff), - .o_mem_signed_halfword_enable_ff(issue_mem_signed_halfword_enable_ff), - .o_mem_unsigned_halfword_enable_ff(issue_mem_unsigned_halfword_enable_ff), - .o_mem_translate_ff (issue_mem_translate_ff), - .o_irq_ff (issue_irq_ff), - .o_fiq_ff (issue_fiq_ff), - .o_abt_ff (issue_abt_ff), - .o_swi_ff (issue_swi_ff), - - .o_alu_source_value_ff (issue_alu_source_value_ff), - .o_shift_source_value_ff (issue_shift_source_value_ff), - .o_shift_length_value_ff (issue_shift_length_value_ff), - .o_mem_srcdest_value_ff (issue_mem_srcdest_value_ff), - - .o_alu_source_ff (issue_alu_source_ff), - .o_shift_source_ff (issue_shift_source_ff), - .o_stall_from_issue (stall_from_issue), - .o_pc_plus_8_ff (issue_pc_plus_8_ff), - .o_shifter_disable_ff (issue_shifter_disable_ff) -); - -// ======================= -// SHIFTER STAGE -// ======================= - -zap_shifter_main #( - .PHY_REGS(PHY_REGS), - .ALU_OPS(ALU_OPS), - .SHIFT_OPS(SHIFT_OPS) -) -u_zap_shifter_main -( - .i_decompile (issue_decompile), - .o_decompile (shifter_decompile), - - .i_pc_ff (issue_pc_ff), - .o_pc_ff (shifter_pc_ff), - - .i_taken_ff (issue_taken_ff), - .o_taken_ff (shifter_taken_ff), - - .i_und_ff (issue_und_ff), - .o_und_ff (shifter_und_ff), - - .o_nozero_ff (shifter_nozero_ff), - - .i_clk (i_clk), - .i_reset (reset), - - .i_clear_from_writeback (clear_from_writeback), - .i_data_stall (data_stall), - .i_clear_from_alu (clear_from_alu), - .i_condition_code_ff (issue_condition_code_ff), - .i_destination_index_ff (issue_destination_index_ff), - .i_alu_operation_ff (issue_alu_operation_ff), - .i_shift_operation_ff (issue_shift_operation_ff), - .i_flag_update_ff (issue_flag_update_ff), - .i_mem_srcdest_index_ff (issue_mem_srcdest_index_ff), - .i_mem_load_ff (issue_mem_load_ff), - .i_mem_store_ff (issue_mem_store_ff), - .i_mem_pre_index_ff (issue_mem_pre_index_ff), - .i_mem_unsigned_byte_enable_ff (issue_mem_unsigned_byte_enable_ff), - .i_mem_signed_byte_enable_ff (issue_mem_signed_byte_enable_ff), - .i_mem_signed_halfword_enable_ff(issue_mem_signed_halfword_enable_ff), - .i_mem_unsigned_halfword_enable_ff(issue_mem_unsigned_halfword_enable_ff), - .i_mem_translate_ff (issue_mem_translate_ff), - .i_irq_ff (issue_irq_ff), - .i_fiq_ff (issue_fiq_ff), - .i_abt_ff (issue_abt_ff), - .i_swi_ff (issue_swi_ff), - .i_alu_source_ff (issue_alu_source_ff), - .i_shift_source_ff (issue_shift_source_ff), - .i_alu_source_value_ff (issue_alu_source_value_ff), - .i_shift_source_value_ff (issue_shift_source_value_ff), - .i_shift_length_value_ff (issue_shift_length_value_ff), - .i_mem_srcdest_value_ff (issue_mem_srcdest_value_ff), - .i_pc_plus_8_ff (issue_pc_plus_8_ff), - .i_disable_shifter_ff (issue_shifter_disable_ff), - - // Next CPSR. - .i_cpsr_nxt (alu_cpsr_nxt), - .i_cpsr_ff (alu_flags_ff), - - // Feedback - .i_alu_value_nxt (alu_alu_result_nxt), - .i_alu_dav_nxt (alu_dav_nxt), - - // Switch indicator. - .i_switch_ff (issue_switch_ff), - .o_switch_ff (shifter_switch_ff), - - // Force32 - .i_force32align_ff (issue_force32_ff), - .o_force32align_ff (shifter_force32_ff), - - // Outputs. - - .o_mem_srcdest_value_ff (shifter_mem_srcdest_value_ff), - .o_alu_source_value_ff (shifter_alu_source_value_ff), - .o_shifted_source_value_ff (shifter_shifted_source_value_ff), - .o_shift_carry_ff (shifter_shift_carry_ff), - - .o_pc_plus_8_ff (shifter_pc_plus_8_ff), - - .o_mem_srcdest_index_ff (shifter_mem_srcdest_index_ff), - .o_mem_load_ff (shifter_mem_load_ff), - .o_mem_store_ff (shifter_mem_store_ff), - .o_mem_pre_index_ff (shifter_mem_pre_index_ff), - .o_mem_unsigned_byte_enable_ff (shifter_mem_unsigned_byte_enable_ff), - .o_mem_signed_byte_enable_ff (shifter_mem_signed_byte_enable_ff), - .o_mem_signed_halfword_enable_ff(shifter_mem_signed_halfword_enable_ff), - .o_mem_unsigned_halfword_enable_ff(shifter_mem_unsigned_halfword_enable_ff), - .o_mem_translate_ff (shifter_mem_translate_ff), - - .o_condition_code_ff (shifter_condition_code_ff), - .o_destination_index_ff (shifter_destination_index_ff), - .o_alu_operation_ff (shifter_alu_operation_ff), - .o_flag_update_ff (shifter_flag_update_ff), - - // Interrupts. - .o_irq_ff (shifter_irq_ff), - .o_fiq_ff (shifter_fiq_ff), - .o_abt_ff (shifter_abt_ff), - .o_swi_ff (shifter_swi_ff), - - // Stall - .o_stall_from_shifter (stall_from_shifter) -); - -// =============== -// ALU STAGE -// =============== - -zap_alu_main #( - .PHY_REGS(PHY_REGS), - .SHIFT_OPS(SHIFT_OPS), - .ALU_OPS(ALU_OPS) -) -u_zap_alu_main -( - .i_decompile (shifter_decompile), - .o_decompile (alu_decompile), - - .i_hijack ( wb_hijack ), - .i_hijack_op1 ( wb_hijack_op1 ), - .i_hijack_op2 ( wb_hijack_op2 ), - .i_hijack_cin ( wb_hijack_cin ), - .o_hijack_sum ( alu_hijack_sum ), - - .i_taken_ff (shifter_taken_ff), - .o_confirm_from_alu (confirm_from_alu), - - .i_pc_ff (shifter_pc_ff), - - .i_und_ff (shifter_und_ff), - .o_und_ff (alu_und_ff), - - .i_nozero_ff ( shifter_nozero_ff ), - - .i_clk (i_clk), - .i_reset (reset), - .i_clear_from_writeback (clear_from_writeback), - .i_data_stall (data_stall), - .i_cpsr_nxt (cpsr_nxt), - .i_flag_update_ff (shifter_flag_update_ff), - .i_switch_ff (shifter_switch_ff), - - .i_force32align_ff (shifter_force32_ff), - - .i_mem_srcdest_value_ff (shifter_mem_srcdest_value_ff), - .i_alu_source_value_ff (shifter_alu_source_value_ff), - .i_shifted_source_value_ff (shifter_shifted_source_value_ff), - .i_shift_carry_ff (shifter_shift_carry_ff), - .i_pc_plus_8_ff (shifter_pc_plus_8_ff), - - .i_abt_ff (shifter_abt_ff), - .i_irq_ff (shifter_irq_ff), - .i_fiq_ff (shifter_fiq_ff), - .i_swi_ff (shifter_swi_ff), - - .i_mem_srcdest_index_ff (shifter_mem_srcdest_index_ff), - .i_mem_load_ff (shifter_mem_load_ff), - .i_mem_store_ff (shifter_mem_store_ff), - .i_mem_pre_index_ff (shifter_mem_pre_index_ff), - .i_mem_unsigned_byte_enable_ff (shifter_mem_unsigned_byte_enable_ff), - .i_mem_signed_byte_enable_ff (shifter_mem_signed_byte_enable_ff), - .i_mem_signed_halfword_enable_ff(shifter_mem_signed_halfword_enable_ff), - .i_mem_unsigned_halfword_enable_ff(shifter_mem_unsigned_halfword_enable_ff), - .i_mem_translate_ff (shifter_mem_translate_ff), - - .i_condition_code_ff (shifter_condition_code_ff), - .i_destination_index_ff (shifter_destination_index_ff), - .i_alu_operation_ff (shifter_alu_operation_ff), // {OP,S} - - .i_data_mem_fault (i_data_wb_err), - - .o_alu_result_nxt (alu_alu_result_nxt), - - .o_alu_result_ff (alu_alu_result_ff), - - .o_abt_ff (alu_abt_ff), - .o_irq_ff (alu_irq_ff), - .o_fiq_ff (alu_fiq_ff), - .o_swi_ff (alu_swi_ff), - - .o_dav_ff (alu_dav_ff), - .o_dav_nxt (alu_dav_nxt), - - .o_pc_plus_8_ff (alu_pc_plus_8_ff), - - // Data access address. Ignore [1:0]. - .o_mem_address_ff (alu_address_ff), - .o_clear_from_alu (clear_from_alu), - .o_pc_from_alu (pc_from_alu), - .o_destination_index_ff (alu_destination_index_ff), - .o_flags_ff (alu_flags_ff), // Output flags. - .o_flags_nxt (alu_cpsr_nxt), - - .o_mem_srcdest_value_ff (), - .o_mem_srcdest_index_ff (alu_mem_srcdest_index_ff), - .o_mem_load_ff (alu_mem_load_ff), - .o_mem_store_ff (), - - .o_ben_ff (), - - .o_mem_unsigned_byte_enable_ff (alu_ubyte_ff), - .o_mem_signed_byte_enable_ff (alu_sbyte_ff), - .o_mem_signed_halfword_enable_ff (alu_shalf_ff), - .o_mem_unsigned_halfword_enable_ff(alu_uhalf_ff), - .o_mem_translate_ff (o_mem_translate), - - .o_address_nxt ( alu_address_nxt ), - - .o_data_wb_we_nxt (o_data_wb_we_nxt), - .o_data_wb_cyc_nxt (o_data_wb_cyc_nxt), - .o_data_wb_stb_nxt (o_data_wb_stb_nxt), - .o_data_wb_dat_nxt (o_data_wb_dat_nxt), - .o_data_wb_sel_nxt (o_data_wb_sel_nxt), - - .o_data_wb_we_ff (o_data_wb_we), - .o_data_wb_cyc_ff (o_data_wb_cyc), - .o_data_wb_stb_ff (o_data_wb_stb), - .o_data_wb_dat_ff (o_data_wb_dat), - .o_data_wb_sel_ff (o_data_wb_sel) - -); - -// ==================== -// MEMORY -// ==================== - -zap_memory_main #( - .PHY_REGS(PHY_REGS) -) -u_zap_memory_main -( - .i_decompile (alu_decompile), - .o_decompile (memory_decompile), - - .i_und_ff (alu_und_ff), - .o_und_ff (memory_und_ff), - - .i_mem_address_ff (alu_address_ff), - - - .i_clk (i_clk), - .i_reset (reset), - - .i_sbyte_ff (alu_sbyte_ff), // Signed byte. - .i_ubyte_ff (alu_ubyte_ff), // Unsigned byte. - .i_shalf_ff (alu_shalf_ff), // Signed half word. - .i_uhalf_ff (alu_uhalf_ff), // Unsigned half word. - - .i_clear_from_writeback (clear_from_writeback), - .i_data_stall (data_stall), - .i_alu_result_ff (alu_alu_result_ff), - .i_flags_ff (alu_flags_ff), - - .i_mem_load_ff (alu_mem_load_ff), - - .i_mem_rd_data (i_data_wb_dat),// From memory. - - .i_mem_fault (i_data_wb_err), // From cache. - - .o_mem_fault (memory_data_abt_ff), - - - .i_dav_ff (alu_dav_ff), - .i_pc_plus_8_ff (alu_pc_plus_8_ff), - - .i_destination_index_ff (alu_destination_index_ff), - - .i_irq_ff (alu_irq_ff), - .i_fiq_ff (alu_fiq_ff), - .i_instr_abort_ff (alu_abt_ff), - .i_swi_ff (alu_swi_ff), - - // Used to speed up loads. - .i_mem_srcdest_index_ff (alu_mem_srcdest_index_ff), - - // Can come in handy since this is reused for several other things. - .i_mem_srcdest_value_ff (o_data_wb_dat), - - .o_alu_result_ff (memory_alu_result_ff), - .o_flags_ff (memory_flags_ff), - - .o_destination_index_ff (memory_destination_index_ff), - .o_mem_srcdest_index_ff (memory_mem_srcdest_index_ff), - - .o_dav_ff (memory_dav_ff), - .o_pc_plus_8_ff (memory_pc_plus_8_ff), - - .o_irq_ff (memory_irq_ff), - .o_fiq_ff (memory_fiq_ff), - .o_swi_ff (memory_swi_ff), - .o_instr_abort_ff (memory_instr_abort_ff), - - .o_mem_load_ff (memory_mem_load_ff), - - - .o_mem_rd_data (memory_mem_rd_data) -); - -// ================== -// WRITEBACK -// ================== - -zap_writeback #( - .PHY_REGS(PHY_REGS) -) -u_zap_writeback -( - .i_decompile (memory_decompile), - .o_decompile (rb_decompile), - - .o_shelve (shelve), - - .i_clk (i_clk), // ZAP clock. - - - .i_reset (reset), // ZAP reset. - .i_valid (memory_dav_ff), - .i_data_stall (data_stall), - .i_clear_from_alu (clear_from_alu), - .i_pc_from_alu (pc_from_alu), - .i_stall_from_decode (stall_from_decode), - .i_stall_from_issue (stall_from_issue), - .i_stall_from_shifter (stall_from_shifter), - - .i_thumb (alu_flags_ff[T]), // To indicate thumb state. - - .i_clear_from_decode (clear_from_decode), - .i_pc_from_decode (pc_from_decode), - - .i_code_stall (code_stall), - - // Used to valid writes on i_wr_index1. - .i_mem_load_ff (memory_mem_load_ff), - - .i_rd_index_0 (rd_index_0), - .i_rd_index_1 (rd_index_1), - .i_rd_index_2 (rd_index_2), - .i_rd_index_3 (rd_index_3), - - .i_wr_index (memory_destination_index_ff), - .i_wr_data (memory_alu_result_ff), - .i_flags (memory_flags_ff), - .i_wr_index_1 (memory_mem_srcdest_index_ff),// load index. - .i_wr_data_1 (memory_mem_rd_data), // load data. - - .i_irq (memory_irq_ff), - .i_fiq (memory_fiq_ff), - .i_instr_abt (memory_instr_abort_ff), - .i_data_abt (memory_data_abt_ff), - .i_swi (memory_swi_ff), - .i_und (memory_und_ff), - - .i_pc_buf_ff (memory_pc_plus_8_ff), - - .i_copro_reg_en (copro_reg_en), - .i_copro_reg_wr_index (copro_reg_wr_index), - .i_copro_reg_rd_index (copro_reg_rd_index), - .i_copro_reg_wr_data (copro_reg_wr_data), - - .o_copro_reg_rd_data_ff (copro_reg_rd_data), - - .o_rd_data_0 (rd_data_0), - .o_rd_data_1 (rd_data_1), - .o_rd_data_2 (rd_data_2), - .o_rd_data_3 (rd_data_3), - - .o_pc (o_instr_wb_adr), - .o_pc_nxt (o_instr_wb_adr_nxt), - .o_cpsr_nxt (cpsr_nxt), - .o_clear_from_writeback (clear_from_writeback), - - .o_hijack (wb_hijack), - .o_hijack_op1 (wb_hijack_op1), - .o_hijack_op2 (wb_hijack_op2), - .o_hijack_cin (wb_hijack_cin), - - .i_hijack_sum (alu_hijack_sum) -); - -// ================================== -// CP15 CB -// ================================== - -zap_cp15_cb u_zap_cp15_cb ( - .i_clk (i_clk), - .i_reset (i_reset), - .i_cp_word (copro_word), - .i_cp_dav (copro_dav), - .o_cp_done (copro_done), - .i_cpsr (o_cpsr), - .o_reg_en (copro_reg_en), - .o_reg_wr_data (copro_reg_wr_data), - .i_reg_rd_data (copro_reg_rd_data), - .o_reg_wr_index (copro_reg_wr_index), - .o_reg_rd_index (copro_reg_rd_index), - - .i_fsr (i_fsr), - .i_far (i_far), - .o_dac (o_dac), - .o_baddr (o_baddr), - .o_mmu_en (o_mmu_en), - .o_sr (o_sr), - .o_pid (o_pid), - .o_dcache_inv (o_dcache_inv), - .o_icache_inv (o_icache_inv), - .o_dcache_clean (o_dcache_clean), - .o_icache_clean (o_icache_clean), - .o_dtlb_inv (o_dtlb_inv), - .o_itlb_inv (o_itlb_inv), - .o_dcache_en (o_dcache_en), - .o_icache_en (o_icache_en), - .i_dcache_inv_done (i_dcache_inv_done), - .i_icache_inv_done (i_icache_inv_done), - .i_dcache_clean_done (i_dcache_clean_done), - .i_icache_clean_done (i_icache_clean_done) -); - -reg [(8*8)-1:0] CPU_MODE; // Max 8 characters i.e. 64-bit string. - -always @* -case(o_cpsr[`CPSR_MODE]) -FIQ: CPU_MODE = "FIQ"; -IRQ: CPU_MODE = "IRQ"; -USR: CPU_MODE = "USR"; -UND: CPU_MODE = "UND"; -SVC: CPU_MODE = "SVC"; -ABT: CPU_MODE = "ABT"; -SYS: CPU_MODE = "SYS"; -default: CPU_MODE = "???"; -endcase - -endmodule // zap_core.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_ram_simple.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_ram_simple.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_ram_simple.v (nonexistent) @@ -1,83 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- Synthesizes to standard 1R + 1W block RAM. The read and write addresses-- -// -- may be specified separately. Only for FPGA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_ram_simple #( - parameter WIDTH = 32, - parameter DEPTH = 32 -) -( - input wire i_clk, - - // Write and read enable. - input wire i_wr_en, - input wire i_rd_en, - - // Write data and address. - input wire [WIDTH-1:0] i_wr_data, - input wire[$clog2(DEPTH)-1:0] i_wr_addr, - - // Read address and data. - input wire [$clog2(DEPTH)-1:0] i_rd_addr, - output reg [WIDTH-1:0] o_rd_data -); - -// Memory array. -reg [WIDTH-1:0] mem [DEPTH-1:0]; - -// Initialize block RAM to 0. -initial -begin: blk1 - integer i; - - for(i=0;i 16 bytes. - -// States. -localparam IDLE = 0; -localparam CACHE_CLEAN_GET_ADDRESS = 1; -localparam CACHE_CLEAN_WRITE = 2; -localparam CACHE_INV = 3; - - -// ---------------------------------------------------------------------------- - -reg [(CACHE_SIZE/16)-1:0] dirty; -reg [(CACHE_SIZE/16)-1:0] valid; -reg [`CACHE_TAG_WDT-1:0] tag_ram [(CACHE_SIZE/16)-1:0]; -reg [127:0] dat_ram [(CACHE_SIZE/16)-1:0]; - -// ---------------------------------------------------------------------------- - -reg [`CACHE_TAG_WDT-1:0] tag_ram_wr_data; -reg tag_ram_wr_en; -reg [$clog2(CACHE_SIZE/16)-1:0] tag_ram_wr_addr, tag_ram_rd_addr; -reg tag_ram_clear; -reg tag_ram_clean; - -// ---------------------------------------------------------------------------- - -reg [1:0] state_ff, state_nxt; - -// ---------------------------------------------------------------------------- - -reg [$clog2(NUMBER_OF_DIRTY_BLOCKS)-1:0] blk_ctr_ff, blk_ctr_nxt; -reg [2:0] adr_ctr_ff, adr_ctr_nxt; - -// ---------------------------------------------------------------------------- - -initial -begin: blk1 - // FPGA anyway initializes to 0 on start. - integer i; - - for(i=0;i 3 ) - begin - // Remove dirty marking. BUG FIX. - tag_ram_clean = 1; - - // Kill access. - kill_access; - - // Go to new state. - state_nxt = CACHE_CLEAN_GET_ADDRESS; - end - else - begin: blk1111 - reg [31:0] shamt; - reg [31:0] data; - reg [31:0] pa; - - shamt = adr_ctr_nxt << 5; - data = o_cache_line >> shamt; - pa = {o_cache_tag[`CACHE_TAG__PA], 4'd0}; - - // Perform a Wishbone write using Physical Address. - wb_prpr_write( data, pa + (adr_ctr_nxt << 2), adr_ctr_nxt != 3 ? CTI_BURST : CTI_EOB, 4'b1111 - ); - end - end - - CACHE_INV: - begin - tag_ram_clear = 1'd1; - state_nxt = IDLE; - o_cache_inv_done = 1'd1; - end - - endcase -end - -// ----------------------------------------------------------------------------- - -// Priority encoder. -function [4:0] pri_enc1 ( input [15:0] in ); -begin: priEncFn - casez ( in ) - 16'b0000_0000_0000_0001: pri_enc1 = 4'd0; - 16'b0000_0000_0000_001?: pri_enc1 = 4'd1; - 16'b0000_0000_0000_01??: pri_enc1 = 4'd2; - 16'b0000_0000_0000_1???: pri_enc1 = 4'd3; - 16'b0000_0000_0001_????: pri_enc1 = 4'd4; - 16'b0000_0000_001?_????: pri_enc1 = 4'd5; - 16'b0000_0000_01??_????: pri_enc1 = 4'd6; - 16'b0000_0000_1???_????: pri_enc1 = 4'd7; - 16'b0000_0001_????_????: pri_enc1 = 4'd8; - 16'b0000_001?_????_????: pri_enc1 = 4'd9; - 16'b0000_01??_????_????: pri_enc1 = 4'hA; - 16'b0000_1???_????_????: pri_enc1 = 4'hB; - 16'b0001_????_????_????: pri_enc1 = 4'hC; - 16'b001?_????_????_????: pri_enc1 = 4'hD; - 16'b01??_????_????_????: pri_enc1 = 4'hE; - 16'b1???_????_????_????: pri_enc1 = 4'hF; - default: pri_enc1 = 5'b11111; - endcase -end -endfunction - -// ----------------------------------------------------------------------------- - -function [31:0] get_tag_ram_rd_addr ( -input [31:0] blk_ctr, -input [CACHE_SIZE/16-1:0] dirty -); -reg [CACHE_SIZE/16-1:0] dirty_new; -reg [3:0] enc; -reg [31:0] shamt; -begin - shamt = blk_ctr_ff << 4; - dirty_new = dirty >> shamt; - enc = pri_enc1(dirty_new); - get_tag_ram_rd_addr = shamt + enc; -end -endfunction - -// ---------------------------------------------------------------------------- - -/* Function to generate Wishbone read signals. */ -task wb_prpr_read; -input [31:0] i_address; -input [2:0] i_cti; -begin - o_wb_cyc_nxt = 1'd1; - o_wb_stb_nxt = 1'd1; - o_wb_wen_nxt = 1'd0; - o_wb_sel_nxt = 4'b1111; - o_wb_adr_nxt = i_address; - o_wb_cti_nxt = i_cti; - o_wb_dat_nxt = 0; -end -endtask - -// ---------------------------------------------------------------------------- - -/* Function to generate Wishbone write signals */ -task wb_prpr_write; -input [31:0] i_data; -input [31:0] i_address; -input [2:0] i_cti; -input [3:0] i_ben; -begin - o_wb_cyc_nxt = 1'd1; - o_wb_stb_nxt = 1'd1; - o_wb_wen_nxt = 1'd1; - o_wb_sel_nxt = i_ben; - o_wb_adr_nxt = i_address; - o_wb_cti_nxt = i_cti; - o_wb_dat_nxt = i_data; -end -endtask - -// ---------------------------------------------------------------------------- - -/* Disables Wishbone */ -task kill_access; -begin - o_wb_cyc_nxt = 0; - o_wb_stb_nxt = 0; - o_wb_wen_nxt = 0; - o_wb_adr_nxt = 0; - o_wb_dat_nxt = 0; - o_wb_sel_nxt = 0; - o_wb_cti_nxt = CTI_CLASSIC; -end -endtask - -// ---------------------------------------------------------------------------- - -function [4:0] baggage ( input [CACHE_SIZE/16-1:0] dirty, input [31:0] blk_ctr_ff ); -reg [31:0] shamt; -integer i; -begin - shamt = blk_ctr_ff << 4; - baggage = pri_enc1(dirty >> shamt); -end -endfunction - -endmodule // zap_cache_tag_ram.v - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// END OF FILE -// ---------------------------------------------------------------------------- - Index: zap/trunk/src/rtl/cpu/zap_fetch_main.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_fetch_main.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_fetch_main.v (nonexistent) @@ -1,312 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This is the simple I-cache frontend to the processor. This stage -- -// -- serves as a buffer for instructions. Data aborts are handled by adding -- -// -- an extra signal down the pipeline. Data aborts piggyback off -- -// -- AND R0, R0, R0. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_fetch_main #( - // Branch predictor entries. - parameter BP_ENTRIES = 1024 -) -( -// Clock and reset. -input wire i_clk, // ZAP clock. -input wire i_reset, // Active high synchronous reset. - -// -// From other parts of the pipeline. These -// signals either tell the unit to invalidate -// its outputs or freeze in place. -// -input wire i_code_stall, // | -input wire i_clear_from_writeback, // | High Priority. -input wire i_data_stall, // | -input wire i_clear_from_alu, // | -input wire i_stall_from_shifter, // | -input wire i_stall_from_issue, // | -input wire i_stall_from_decode, // | Low Priority. -input wire i_clear_from_decode, // V - -// Comes from WB unit. -input wire [31:0] i_pc_ff, // Program counter. - -// Comes from CPSR -input wire i_cpsr_ff_t, // CPSR T bit. - -// From I-cache. -input wire [31:0] i_instruction, // A 32-bit ZAP instruction. - -input wire i_valid, // Instruction valid indicator. -input wire i_instr_abort, // Instruction abort fault. - - -// To decode. -output reg [31:0] o_instruction, // The 32-bit instruction. -output reg o_valid, // Instruction valid. -output reg o_instr_abort, // Indication of an abort. -output reg [31:0] o_pc_plus_8_ff, // PC +8 ouput. -output reg [31:0] o_pc_ff, // PC output. - -// For BP. -input wire i_confirm_from_alu, // Confirm branch prediction from ALU. -input wire [31:0] i_pc_from_alu, // Address of branch. -input wire [1:0] i_taken, // Predicted status. -output wire [1:0] o_taken // Prediction. Not a flip-flop... - -); - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -// Unused signals are assigned to this. -wire _unused_ok_; - -// If an instruction abort occurs, this unit sleeps until it is woken up. -reg sleep_ff; - -// Taken_v -wire [1:0] taken_v; - -// Predict non branches as not taken... -assign o_taken = o_instruction[28:26] == 3'b101 ? taken_v : SNT; - -// ---------------------------------------------------------------------------- - -// -// This is the instruction payload on an abort -// because no instruction is actually available on -// an abort. This is AND R0, R0, R0 which is a NOP. -// -localparam ABORT_PAYLOAD = 32'd0; - -// Branch states. -localparam [1:0] SNT = 2'b00; // Strongly Not Taken. -localparam [1:0] WNT = 2'b01; // Weakly Not Taken. -localparam [1:0] WT = 2'b10; // Weakly Taken. -localparam [1:0] ST = 2'b11; // Strongly Taken. - -// -// NOTE: If an instruction is invalid, only then can it be tagged with any -// kind of interrupt. Thus, the MMU must make instruction valid as 1 before -// attaching an abort interrupt to it even though the instruction generated -// might be invalid. Such an instruction is not actually executed. -// - -// -// This stage simply forwards data from the -// I-cache downwards. -// -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - // Unit has no valid output. - o_valid <= 1'd0; - - // Do not signal any abort. - o_instr_abort <= 1'd0; - - // Wake unit up. - sleep_ff <= 1'd0; - end - else if ( i_clear_from_writeback ) clear_unit; - else if ( i_data_stall) begin end // Save state. - else if ( i_clear_from_alu ) clear_unit; - else if ( i_stall_from_shifter ) begin end // Save state. - else if ( i_stall_from_issue ) begin end // Save state. - else if ( i_stall_from_decode) begin end // Save state. - else if ( i_clear_from_decode ) clear_unit; - else if ( i_code_stall ) begin end - - // If unit is sleeping. - else if ( sleep_ff ) - begin - // Nothing valid to be sent. - o_valid <= 1'd0; - - // No aborts. - o_instr_abort <= 1'd0; - - // Keep sleeping. - sleep_ff <= 1'd1; - end - - // Data from memory is valid. This could also be used to signal - // an instruction access abort. - else if ( i_valid ) - begin - // Instruction aborts occur with i_valid as 1. See NOTE. - o_valid <= 1'd1; - o_instr_abort <= i_instr_abort; - - // Put unit to sleep on an abort. - sleep_ff <= i_instr_abort; - - // - // Pump PC + 8 or 4 down the pipeline. The number depends on - // ARM/Compressed mode. - // - o_pc_plus_8_ff <= i_cpsr_ff_t ? ( i_pc_ff + 32'd4 ) : - ( i_pc_ff + 32'd8 ); - - // PC is pumped down the pipeline. - o_pc_ff <= i_pc_ff; - - // Instruction. If 16-bit aligned address, move data from - // cache by 16-bit to focus on the instruction. - o_instruction <= i_pc_ff[1] ? i_instruction >> 16 : i_instruction; - end - else - begin - // Invalidate the output. - o_valid <= 1'd0; - end -end - -always @ (negedge i_clk) -begin - if ( i_pc_ff[0] != 1'd0 ) - begin - $display($time, " - %m :: Error: PC LSB isn't zero. This is not legal..."); - $finish; - end -end - -// ---------------------------------------------------------------------------- - -// -// Branch State RAM. -// Holds the 2-bit state for a range of branches. Whenever a branch is -// either detected as correctly taken or incorrectly taken, this RAM is -// updated. Each entry in the RAM corresponds to a virtual memory address -// whether or not it be a legit branch or not. -// -zap_ram_simple -#(.DEPTH(BP_ENTRIES), .WIDTH(2)) u_br_ram -( - .i_clk(i_clk), - - // The reason that a no-stall condition is included is that - // if the pipeline stalls, this memory should be trigerred multiply - // times. - .i_wr_en( !i_data_stall && - !i_stall_from_issue && - !i_stall_from_decode && - !i_stall_from_shifter && - (i_clear_from_alu || i_confirm_from_alu)), - - // Lower bits of the PC index into the branch RAM for read and - // write addresses. - .i_wr_addr(i_pc_from_alu[$clog2(BP_ENTRIES):1]), - .i_rd_addr(i_pc_ff[$clog2(BP_ENTRIES):1]), - - // Write the new state. - .i_wr_data(compute(i_taken, i_clear_from_alu)), - - // Read when there is no stall. - .i_rd_en( - !i_code_stall && - !i_data_stall && - !i_stall_from_issue && - !i_stall_from_decode && - !i_stall_from_shifter - ), - - // Send the read data over to o_taken_ff which is a 2-bit value. - .o_rd_data(taken_v) -); - -// ---------------------------------------------------------------------------- - -// -// Branch Memory writes. -// Implements a 4-state predictor. -// -function [1:0] compute ( input [1:0] i_taken, input i_clear_from_alu ); -begin - // Branch was predicted incorrectly. - if ( i_clear_from_alu ) - begin - case ( i_taken ) - SNT: compute = WNT; - WNT: compute = WT; - WT: compute = WNT; - ST: compute = WT; - endcase - end - else // Confirm from alu that branch was correctly predicted. - begin - case ( i_taken ) - SNT: compute = SNT; - WNT: compute = SNT; - WT: compute = ST; - ST: compute = ST; - endcase - end -end -endfunction - -// ---------------------------------------------------------------------------- - -// -// This task clears out the unit and refreshes it for a new -// service session. Will wake the unit up and clear the outputs. -// -task clear_unit; -begin - // No valid output. - o_valid <= 1'd0; - - // No aborts since we are clearing out the unit. - o_instr_abort <= 1'd0; - - // Wake up the unit. - sleep_ff <= 1'd0; -end -endtask - -assign _unused_ok_ = i_pc_from_alu[0] && - i_pc_from_alu[31:$clog2(BP_ENTRIES) + 1]; - -// ---------------------------------------------------------------------------- - -zap_decompile u_zap_decompile ( - .i_instruction ({4'd0, o_instruction}), - .i_dav (o_valid), - .o_decompile () -); - - -endmodule // zap_fetch_main.v -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/src/rtl/cpu/zap_predecode_mem_fsm.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_predecode_mem_fsm.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_predecode_mem_fsm.v (nonexistent) @@ -1,709 +0,0 @@ -// ----------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- -------------------------------------------------------------------------- -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// ----------------------------------------------------------------------------- -// -- -- -// -- This module sequences ARM LDM/STM CISC instructions into simpler RISC -- -// -- instructions. Basically LDM -> LDRs and STM -> STRs. Supports a base -- -// -- restored abort model. Start instruction carries interrupt information -- -// -- so this cannot block interrupts if there is a sequence of these. -- -// -- -- -// -- Also handles SWAP instruction. -- -// -- -- -// -- SWAP steps: -- -// -- - Read data from [Rn] into DUMMY. - LDR DUMMY0, [Rn] -- -// -- - Write data in Rm to [Rn] - STR Rm, [Rn] -- -// -- - Copy data from DUMMY to Rd. - MOV Rd, DUMMY0 -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -module zap_predecode_mem_fsm -( - // Clock and reset. - input wire i_clk, // ZAP clock. - input wire i_reset, // ZAP reset. - - // Instruction information from the fetch. - input wire [34:0] i_instruction, - input wire i_instruction_valid, - - // Interrupt information from the fetch. - input wire i_irq, - input wire i_fiq, - - // CPSR - input wire i_cpsr_t, - - // Pipeline control signals. - input wire i_clear_from_writeback, - input wire i_data_stall, - input wire i_clear_from_alu, - input wire i_stall_from_shifter, - input wire i_issue_stall, - - // Instruction output. - output reg [35:0] o_instruction, - output reg o_instruction_valid, - - // We generate a stall. - output reg o_stall_from_decode, - - // Possibly masked interrupts. - output reg o_irq, - output reg o_fiq -); - -/////////////////////////////////////////////////////////////////////////////// - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -// Instruction breakup -wire [3:0] cc ; -wire [2:0] id ; -wire pre_index ; -wire up ; -wire s_bit ; -wire writeback ; -wire load ; -wire [3:0] base ; -wire [15:0] reglist ; - -// Instruction breakup assignment. -assign {cc, id, pre_index, up, s_bit, writeback, load, base, reglist} = i_instruction; - -wire store = !load; -wire link = i_instruction[24]; -wire [11:0] branch_offset = i_instruction[11:0]; - -wire [11:0] oc_offset; // Ones counter offset. -reg [3:0] state_ff, state_nxt; // State. -reg [15:0] reglist_ff, reglist_nxt; // Register list. -reg [31:0] const_ff, const_nxt; // For BLX - const reg. - -/////////////////////////////////////////////////////////////////////////////// - -// States. -localparam IDLE = 0; -localparam MEMOP = 1; -localparam WRITE_PC = 2; -localparam SWAP1 = 3; -localparam SWAP2 = 4; -localparam LMULT_BUSY = 5; -localparam BL_S1 = 6; -localparam SWAP3 = 7; -localparam BLX1_ARM_S0 = 8; -localparam BLX1_ARM_S1 = 9; -localparam BLX1_ARM_S2 = 10; -localparam BLX1_ARM_S3 = 11; -localparam BLX1_ARM_S4 = 12; -localparam BLX1_ARM_S5 = 13; -localparam BLX2_ARM_S0 = 14; - -/////////////////////////////////////////////////////////////////////////////// - -assign oc_offset = ones_counter(i_instruction); - -/////////////////////////////////////////////////////////////////////////////// - -// Next state and output logic. -always @* -begin - const_nxt = const_ff; - - // Block interrupts by default. - o_irq = 0; - o_fiq = 0; - - // Avoid latch inference. - state_nxt = state_ff; - o_instruction = i_instruction; - o_instruction_valid = i_instruction_valid; - reglist_nxt = reglist_ff; - o_stall_from_decode = 1'd0; - - case ( state_ff ) - BLX1_ARM_S0: // SCONST = ($signed(constant) << 2) + ( H << 1 )) - begin: blk3223 - reg H; - - o_stall_from_decode = 1'd1; - - H = i_instruction[24]; - const_nxt = ( { {8{i_instruction[23]}} , i_instruction[23:0] } << 2 ) + ( H << 1 ); - - // MOV DUMMY0, SCONST[7:0] ror 0 - o_instruction[31:0] = {AL, 2'b00, 1'b1, MOV, 1'd0, 4'd0, 4'd0, 4'd0, const_nxt[7:0]}; - {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0; - end - - BLX1_ARM_S1: - begin - o_stall_from_decode = 1'd1; - - // ORR DUMMY0, DUMMY0, SCONST[15:8] ror 12*2 - o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd12, const_nxt[15:8]}; - {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0; - {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0; - end - - BLX1_ARM_S2: - begin - o_stall_from_decode = 1'd1; - - // ORR DUMMY0, DUMMY0, SCONST[23:16] ror 8*2 - o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd8, const_nxt[23:16]}; - {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0; - {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0; - end - - BLX1_ARM_S3: - begin - o_stall_from_decode = 1'd1; - - // ORR DUMMY0, DUMMY0, SCONST[31:24] ror 4*2 - o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd4, const_nxt[31:24]}; - {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0; - {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0; - end - - BLX1_ARM_S4: - begin - o_stall_from_decode = 1'd1; - - // ORR DUMMY0, DUMMY0, 1 - Needed to indicate a switch - // to Thumb if needed. - o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd0, !i_cpsr_t}; - {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0; - {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0; - end - - BLX1_ARM_S5: - begin - // Remove stall. - o_stall_from_decode = 1'd0; - - // BX DUMMY0 - o_instruction = 32'hE12FFF10; - {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]} = ARCH_DUMMY_REG0; - end - - BLX2_ARM_S0: - begin - // Remove stall. - o_stall_from_decode = 1'd0; - - // BX Rm. Just remove the L bit. Conditional is passed - // on. - o_instruction = i_instruction; - o_instruction[5] = 1'd0; - end - - IDLE: - begin - // BLX1 detected. Unconditional!!! - // Immediate Offset. - if ( i_instruction[31:25] == BLX1[31:25] && i_instruction_valid ) - begin - // We must generate a SUBAL LR,PC,4 ROR 0 - // This makes LR have the value - // PC+8-4=PC+4 which is the address of - // the next instruction. - o_instruction = {AL, 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4}; - - // In Thumb mode, we must generate PC+4-2 - if ( i_cpsr_t ) - begin - o_instruction[11:0] = 12'd2; // Modify the instruction. - end - - o_stall_from_decode = 1'd1; // Stall the core. - state_nxt = BLX1_ARM_S0; - end - else if ( i_instruction[27:4] == BLX2[27:4] && i_instruction_valid ) // BLX2 detected. Register offset. CONDITIONAL. - begin - // Write address of next instruction to LR. Now this - // depends on the mode we're in. Mode in the sense - // ARM/Thumb. We need to look at i_cpsr_t. - - // We need to generate a SUBcc LR,PC,4 ROR 0 - // to store the next instruction address in - // LR. - o_instruction = {i_instruction[31:28], 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4}; - - // In Thumb mode, we need to remove 2 from PC - // instead of 4. - if ( i_cpsr_t ) - begin - o_instruction[11:0] = 12'd2; // modify instr. - end - - o_stall_from_decode = 1'd1; // Stall the core. - state_nxt = BLX2_ARM_S0; - end - // LDM/STM detected... - else if ( id == 3'b100 && i_instruction_valid ) - begin - // Backup base register. - // MOV DUMMY0, Base - if ( up ) - begin - o_instruction = {cc, 2'b00, 1'b0, MOV, - 1'b0, 4'd0, 4'd0, 8'd0, base}; - - {o_instruction[`DP_RD_EXTEND], - o_instruction[`DP_RD]} - = ARCH_DUMMY_REG0; - end - else - begin - // SUB DUMMY0, BASE, OFFSET - o_instruction = {cc, 2'b00, 1'b1, SUB, - 1'd0, base, 4'd0, oc_offset}; - - {o_instruction[`DP_RD_EXTEND], - o_instruction[`DP_RD]} = - ARCH_DUMMY_REG0; - end - - o_instruction_valid = 1'd1; - reglist_nxt = reglist; - - state_nxt = MEMOP; - o_stall_from_decode = 1'd1; - - // Since this instruction does not change the - // actual state of the CPU, an interrupt may be - // taken on this. - o_irq = i_irq; - o_fiq = i_fiq; - end - else if ( i_instruction[27:23] == 5'b00010 && - i_instruction[21:20] == 2'b00 && - i_instruction[11:4] == 4'b1001 && i_instruction_valid ) // SWAP - begin - // Swap - - o_irq = i_irq; - o_fiq = i_fiq; - - // dummy = *(rn) - LDR ARCH_DUMMY_REG0, [rn, #0] - state_nxt = SWAP1; - - o_instruction = {cc, 3'b010, 1'd1, 1'd0, - i_instruction[22], 1'd0, 1'd1, - i_instruction[19:16], 4'b0000, 12'd0}; - // The 0000 is replaced with dummy0 below. - - {o_instruction[`SRCDEST_EXTEND], - o_instruction[`SRCDEST]} = ARCH_DUMMY_REG0; - - o_instruction_valid = 1'd1; - o_stall_from_decode = 1'd1; - end - else if ( i_instruction[27:23] == 5'd1 && - i_instruction[7:4] == 4'b1001 && i_instruction_valid ) - begin - // LMULT - state_nxt = LMULT_BUSY; - o_stall_from_decode = 1'd1; - o_irq = i_irq; - o_fiq = i_fiq; - o_instruction = i_instruction; - o_instruction_valid = i_instruction_valid; - end - else if ( i_instruction[27:25] == 3'b101 && - i_instruction[24] && i_instruction_valid ) // BL. - begin - // Move to new state. In that state, we will - // generate a plain branch. - state_nxt = BL_S1; - - // PC will stall preventing the fetch from - // presenting new data. - o_stall_from_decode = 1'd1; - - if ( i_cpsr_t == 1'd0 ) // ARM - begin - // PC is 8 bytes ahead. - // Craft a SUB LR, PC, 4. - o_instruction = {i_instruction[31:28], - 28'h24FE004}; - end - else - begin - // PC is 4 bytes ahead... - // Craft a SUB LR, PC, 1 so that return - // goes to the next 16bit instruction - // and making LSB of LR = 1. - o_instruction = {i_instruction[31:28], - 28'h24FE001}; - end - - // Sell it as a valid instruction - o_instruction_valid = 1; - - // Silence interrupts if a BL instruction is - // seen. - o_irq = 0; - o_fiq = 0; - end - else - begin - // Be transparent. - state_nxt = state_ff; - o_stall_from_decode = 1'd0; - o_instruction = i_instruction; - o_instruction_valid = i_instruction_valid; - reglist_nxt = 16'd0; - o_irq = i_irq; - o_fiq = i_fiq; - end - end - - BL_S1: - begin - // Launch out the original instruction clearing the - // link bit. This is like MOV PC, - o_instruction = i_instruction & ~(1 << 24); - o_instruction_valid = i_instruction_valid; - - // Move to IDLE state. - state_nxt = IDLE; - - // Free the fetch from your clutches. - o_stall_from_decode = 1'd0; - - // Continue to silence interrupts. - o_irq = 0; - o_fiq = 0; - end - - LMULT_BUSY: - begin - o_irq = 0; - o_fiq = 0; - o_instruction = {1'd1, i_instruction}; - o_instruction_valid = i_instruction_valid; - o_stall_from_decode = 1'd0; - state_nxt = IDLE; - end - - SWAP1, SWAP3: - begin - // STR Rm, [Rn, #0] - - o_irq = 0; - o_fiq = 0; - - // If in SWAP3, end the sequence so get next operation - // in when we move to IDLE. - o_stall_from_decode = state_ff == SWAP3 ? 1'd0 : 1'd1; - - o_instruction_valid = 1; - o_instruction = {cc, 3'b010, 1'd1, 1'd0, - i_instruction[22], 1'd0, 1'd0, - i_instruction[19:16], - i_instruction[3:0], 12'd0}; // BUG FIX - - state_nxt = state_ff == SWAP3 ? IDLE : SWAP2; - end - - SWAP2: - begin:SWP2BLK - // MOV Rd, DUMMY0 - - reg [3:0] rd; - - rd = i_instruction[15:12]; - - // Keep waiting. Next we initiate a read to ensure - // write buffer gets flushed. - o_stall_from_decode = 1'd1; - o_instruction_valid = 1'd1; - - o_irq = 0; - o_fiq = 0; - - o_instruction = {cc, 2'b00, 1'd0, MOV, 1'd0, 4'b0000, - rd, 12'd0}; // ALU src doesn't matter. - - {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]} - = ARCH_DUMMY_REG0; - - state_nxt = SWAP3; - end - - MEMOP: - begin: mem_op_blk_1 - - // Memory operations happen here. - - reg [3:0] pri_enc_out; - - pri_enc_out = pri_enc(reglist_ff); - reglist_nxt = reglist_ff & ~(16'd1 << pri_enc_out); - - o_irq = 0; - o_fiq = 0; - - // The map function generates a base restore - // instruction if reglist = 0. - o_instruction = map ( i_instruction, pri_enc_out, - reglist_ff ); - o_instruction_valid = 1'd1; - - if ( reglist_ff == 0 ) - begin - if ( i_instruction[ARCH_PC] && load ) - begin - o_stall_from_decode = 1'd1; - state_nxt = WRITE_PC; - end - else - begin - o_stall_from_decode = 1'd0; - state_nxt = IDLE; - end - end - else - begin - state_nxt = MEMOP; - o_stall_from_decode = 1'd1; - end - end - - // If needed, we finally write to the program counter as - // either a MOV PC, LR or MOVS PC, LR. - WRITE_PC: - begin - // MOV(S) PC, ARCH_DUMMY_REG1 - state_nxt = IDLE; - o_stall_from_decode = 1'd0; - - o_instruction = - { cc, 2'b00, 1'd0, MOV, s_bit, 4'd0, ARCH_PC, - 8'd0, 4'd0 }; - - {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]} - = ARCH_DUMMY_REG1; - - o_instruction_valid = 1'd1; - o_irq = 0; - o_fiq = 0; - end - endcase -end - -/////////////////////////////////////////////////////////////////////////////// - -function [33:0] map ( input [31:0] instr, input [3:0] enc, input [15:0] list ); -// These override the globals within the function scope. -reg [3:0] cc; -reg [2:0] id; -reg pre_index; -reg up; -reg s_bit; -reg writeback; -reg load; -reg [3:0] base; -reg [15:0] reglist; -reg store; -reg restore; -begin - restore = 0; - - {cc, id, pre_index, up, s_bit, writeback, load, base, reglist} = instr; - - store = !load; - map = instr; - map = map & ~(1<<22); // No byte access. - map = map & ~(1<<25); // Constant Offset (of 4). - map[23] = 1'd1; // Hard wired to increment. - - map[11:0] = 12'd4; // Offset - map[27:26] = 2'b01; // Memory instruction. - - map[`SRCDEST] = enc; - {map[`BASE_EXTEND],map[`BASE]} = ARCH_DUMMY_REG0;//Use as base register. - - // If not up, then DA -> IB and DB -> IA. - if ( !up ) // DA or DB. - begin - map[24] = !map[24]; // Post <---> Pre switch. - end - - // Since the indexing has swapped (possibly), we must rethink map[21]. - if ( map[24] == 0 ) // Post index. - begin - map[21] = 1'd0; // Writeback is implicit. - end - else // Pre-index - Must specify writeback. - begin - map[21] = 1'd1; - end - - if ( list == 0 ) // Catch 0 list here itself... - begin - // Restore base. MOV Rbase, DUMMY0 - if ( writeback ) - begin - restore = 1; - - if ( up ) // Original instruction asked increment. - begin - map = - { cc, 2'b0, 1'b0, MOV, 1'b0, 4'd0, - base, 8'd0, 4'd0 }; - - {map[`DP_RB_EXTEND],map[`DP_RB]} = - ARCH_DUMMY_REG0; - end - else - begin // Restore. - // SUB BASE, BASE, #OFFSET - map = {cc, 2'b00, 1'b1, SUB, - 1'd0, base, base, oc_offset}; - end - end - else - begin - map = 32'd0; // Wasted cycle. - end - end - else if ( (store && s_bit) || (load && s_bit && !list[15]) ) - // STR with S bit or LDR with S bit and no PC - force user bank access. - begin - case ( map[`SRCDEST] ) // Force user bank. - 8: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R8; - 9: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R9; - 10:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R10; - 11:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R11; - 12:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R12; - 13:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R13; - 14:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R14; - endcase - end - else if ( load && enc == 15 ) - // - // Load with PC in register list. Load to dummy register. - // Will never use user bank. - // - begin - // - // If S = 1, perform an atomic return. - // If S = 0, just write to PC i.e., a jump. - // - // For now, load to ARCH_DUMMY_REG1. - // - {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_DUMMY_REG1; - end -end -endfunction - -/////////////////////////////////////////////////////////////////////////////// - -always @ (posedge i_clk) -begin - if ( i_reset ) clear; - else if ( i_clear_from_writeback) clear; - else if ( i_data_stall ) begin end // Stall CPU. - else if ( i_clear_from_alu ) clear; - else if ( i_stall_from_shifter ) begin end - else if ( i_issue_stall ) begin end - else - begin - state_ff <= state_nxt; - reglist_ff <= reglist_nxt; - const_ff <= const_nxt; - end -end - -/////////////////////////////////////////////////////////////////////////////// - -// Unit is reset. -task clear; -begin - state_ff <= IDLE; - reglist_ff <= 16'd0; - const_ff <= 32'd0; -end -endtask - -// Counts the number of ones and multiplies that by 4 to get final -// address offset. -function [11:0] ones_counter ( - input [15:0] i_word // Register list. -); -begin: blk1 - integer i; - reg [11:0] offset; - - offset = 0; - - // Counter number of ones. - for(i=0;i<16;i=i+1) - offset = offset + i_word[i]; - - // Since LDM and STM occur only on 4 byte regions, compute the - // net offset. - offset = (offset << 2); // Multiply by 4. - - ones_counter = offset; -end -endfunction - -// -// Function to model a 16-bit priority encoder. -// - -// Priority encoder. -function [3:0] pri_enc ( input [15:0] in ); -begin: priEncFn - casez ( in ) - 16'b????_????_????_???1: pri_enc = 4'd0; - 16'b????_????_????_??10: pri_enc = 4'd1; - 16'b????_????_????_?100: pri_enc = 4'd2; - 16'b????_????_????_1000: pri_enc = 4'd3; - 16'b????_????_???1_0000: pri_enc = 4'd4; - 16'b????_????_??10_0000: pri_enc = 4'd5; - 16'b????_????_?100_0000: pri_enc = 4'd6; - 16'b????_????_1000_0000: pri_enc = 4'd7; - 16'b????_???1_0000_0000: pri_enc = 4'd8; - 16'b????_??10_0000_0000: pri_enc = 4'd9; - 16'b????_?100_0000_0000: pri_enc = 4'hA; - 16'b????_1000_0000_0000: pri_enc = 4'hB; - 16'b???1_0000_0000_0000: pri_enc = 4'hC; - 16'b??10_0000_0000_0000: pri_enc = 4'hD; - 16'b?100_0000_0000_0000: pri_enc = 4'hE; - 16'b1000_0000_0000_0000: pri_enc = 4'hF; - default: pri_enc = 4'h0; - endcase -end -endfunction - -endmodule // zap_predecode_mem_fsm.v -`default_nettype wire Index: zap/trunk/src/rtl/cpu/zap_predecode_coproc.v =================================================================== --- zap/trunk/src/rtl/cpu/zap_predecode_coproc.v (revision 57) +++ zap/trunk/src/rtl/cpu/zap_predecode_coproc.v (nonexistent) @@ -1,284 +0,0 @@ -// --------------------------------------------------------------------------- -// -- -- -// -- (C) 2016-2018 Revanth Kamaraj. -- -// -- -- -// -- ------------------------------------------------------------------------ -// -- -- -// -- This program is free software; you can redistribute it and/or -- -// -- modify it under the terms of the GNU General Public License -- -// -- as published by the Free Software Foundation; either version 2 -- -// -- of the License, or (at your option) any later version. -- -// -- -- -// -- This program is distributed in the hope that it will be useful, -- -// -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- -// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- -// -- GNU General Public License for more details. -- -// -- -- -// -- You should have received a copy of the GNU General Public License -- -// -- along with this program; if not, write to the Free Software -- -// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -- -// -- 02110-1301, USA. -- -// -- -- -// --------------------------------------------------------------------------- -// Implements a simple coprocessor interface for the ZAP core. The interface -// is low bandwidth and thus is suited only for coprocessor that do not -// perform large data exchanges. Note that the translate function must be -// present in the coprocessor to account for CPU modes. -// ---------------------------------------------------------------------------- - -`default_nettype none - -module zap_predecode_coproc #( - parameter PHY_REGS = 46 -) -( - input wire i_clk, - input wire i_reset, - - // Instruction and valid qualifier. - input wire [34:0] i_instruction, - input wire i_valid, - - // CPSR Thumb Bit. - input wire i_cpsr_ff_t, - input wire [4:0] i_cpsr_ff_mode, - - // Interrupts. - input wire i_irq, - input wire i_fiq, - - // Clear and stall signals. - input wire i_clear_from_writeback, // | High Priority - input wire i_data_stall, // | - input wire i_clear_from_alu, // | - input wire i_stall_from_shifter, // | - input wire i_stall_from_issue, // V Low Priority - - // Pipeline Valid. Must become 0 when every stage of the pipeline - // is invalid. - input wire i_pipeline_dav, - - // Coprocessor done signal. - input wire i_copro_done, - - // Interrupts output. - output reg o_irq, - output reg o_fiq, - - // Instruction and valid qualifier. - output reg [34:0] o_instruction, - output reg o_valid, - - // We can generate stall if coprocessor is slow. We also have - // some minimal latency. - output reg o_stall_from_decode, - - // Are we really asking for the coprocessor ? - output reg o_copro_dav_ff, - - // The entire instruction is passed to the coprocessor. - output reg [31:0] o_copro_word_ff -); - -/////////////////////////////////////////////////////////////////////////////// - -`include "zap_defines.vh" -`include "zap_localparams.vh" -`include "zap_functions.vh" - -/////////////////////////////////////////////////////////////////////////////// - -localparam IDLE = 0; -localparam BUSY = 1; - -/////////////////////////////////////////////////////////////////////////////// - -// State register. -reg state_ff, state_nxt; - -// Output registers. -reg cp_dav_ff, cp_dav_nxt; -reg [31:0] cp_word_ff, cp_word_nxt; - -/////////////////////////////////////////////////////////////////////////////// - -// Connect output registers to output. -always @* -begin - o_copro_word_ff = cp_word_ff; - o_copro_dav_ff = cp_dav_ff; -end - -/////////////////////////////////////////////////////////////////////////////// - -wire c1 = !i_cpsr_ff_t; -wire c2 = i_cpsr_ff_mode != USR; -wire c3 = i_instruction[11:8] == 4'b1111; -wire c4 = i_instruction[34:32] == 3'd0; -wire c5 = c1 & c2 & c3 & c4; -reg eclass; - -// Next state logic. -always @* -begin - // Default values. - cp_dav_nxt = cp_dav_ff; - cp_word_nxt = cp_word_ff; - o_stall_from_decode = 1'd0; - o_instruction = i_instruction; - o_valid = i_valid; - state_nxt = state_ff; - o_irq = i_irq; - o_fiq = i_fiq; - - eclass = 0; - - case ( state_ff ) - IDLE: - // Activate only if no thumb, not in USER mode and CP15 access is requested. - casez ( (!i_cpsr_ff_t && (i_instruction[34:32] == 3'd0) && i_valid) ? i_instruction[31:0] : 35'd0 ) - MRC, MCR, LDC, STC, CDP, MRC2, MCR2, LDC2, STC2: - begin - if ( i_instruction[11:8] == 4'b1111 && i_cpsr_ff_mode != USR ) // CP15 and root access -- perfectly fine. - begin - // Send ANDNV R0, R0, R0 instruction. - o_instruction = {4'b1111, 28'd0}; - o_valid = 1'd0; - o_irq = 1'd0; - o_fiq = 1'd0; - - // As long as there is an instruction to process... - if ( i_pipeline_dav ) - begin - // Do not impose any output. However, continue - // to stall all before this unit in the - // pipeline. - o_valid = 1'd0; - o_stall_from_decode = 1'd1; - cp_dav_nxt = 1'd0; - cp_word_nxt = 32'd0; - end - else - begin - // Prepare to move to BUSY. Continue holding - // stall. Send out 0s. - o_valid = 1'd0; - o_stall_from_decode = 1'd1; - cp_word_nxt = i_instruction; - cp_dav_nxt = 1'd1; - state_nxt = BUSY; - end - end - else // Warning... - begin - - if ( i_instruction[11:8] != 4'b1111 ) - eclass = 1; - else - eclass = 2; - - - // Remain transparent since this is not a coprocessor - // instruction. - o_valid = i_valid; - o_instruction = i_instruction; - o_irq = i_irq; - o_fiq = i_fiq; - cp_dav_nxt = 0; - o_stall_from_decode = 0; - cp_word_nxt = {32{1'dx}}; // Don't care. - end - end - default: - begin - // Remain transparent since this is not a coprocessor - // instruction. - o_valid = i_valid; - o_instruction = i_instruction; - o_irq = i_irq; - o_fiq = i_fiq; - cp_dav_nxt = 0; - o_stall_from_decode = 0; - cp_word_nxt = {32{1'dx}}; // Don't care. - end - endcase - - BUSY: - begin - // Provide coprocessor word and valid to the coprocessor. - cp_word_nxt = cp_word_ff; - cp_dav_nxt = cp_dav_ff; - - // Continue holding stall. - o_stall_from_decode = 1'd1; - - // Send out nothing. - o_valid = 1'd0; - o_instruction = 32'd0; - - // Block interrupts. - o_irq = 1'd0; - o_fiq = 1'd0; - - // If we get a response, we can move back to IDLE. Release - // the stall so that processor can continue. - if ( i_copro_done ) - begin - cp_dav_nxt = 1'd0; - cp_word_nxt = 32'd0; - state_nxt = IDLE; - o_stall_from_decode = 1'd0; - end - end - endcase -end - -always @ (posedge i_clk) -begin - if ( i_reset ) - begin - clear; - end - else if ( i_clear_from_writeback ) - begin - clear; - end - else if ( i_data_stall ) - begin - // Preserve values. - end - else if ( i_clear_from_alu ) - begin - clear; - end - else if ( i_stall_from_shifter ) - begin - // Preserve values. - end - else if ( i_stall_from_issue ) - begin - // Preserve values. - end - else - begin - state_ff <= state_nxt; - cp_word_ff <= cp_word_nxt; - cp_dav_ff <= cp_dav_nxt; - end -end - -// Clear out the unit. -task clear; -begin - state_ff <= IDLE; - cp_dav_ff <= 1'd0; -end -endtask - -endmodule - -`default_nettype wire - -// ---------------------------------------------------------------------------- -// EOF -// ---------------------------------------------------------------------------- Index: zap/trunk/makefile =================================================================== --- zap/trunk/makefile (revision 57) +++ zap/trunk/makefile (nonexistent) @@ -1,9 +0,0 @@ -.PHONY: clean -.PHONY: error - -error: - @echo "To run a TC, go to src/ts and do a make there. Only target supported here is 'clean'." - -clean: - @echo "Removing object folder." - rm -rf obj/ Index: zap/trunk/README.md =================================================================== --- zap/trunk/README.md (revision 57) +++ zap/trunk/README.md (revision 58) @@ -1,7 +1,7 @@ ## NOTE: This project was designed by me as a part of a student design contest. It is no longer actively supported. +## This project's files are hosted on GitHub. +## The ZAP ARM Processor (ARMv5T Compatible, FPGA Synthesizable Soft Processor) @ https://github.com/krevanth/ZAP.git -## The ZAP ARM Processor (ARMv5T Compatible, FPGA Synthesizable Soft Processor) - ### Author : Revanth Kamaraj (revanth91kamaraj@gmail.com) ### Introduction @@ -18,12 +18,10 @@ #### Repos -This project is hosted on Github and Opencores. +This project is hosted on Github. GIT: https://github.com/krevanth/ZAP -SVN: https://opencores.org/projects/zap - #### Features ##### ZAP Processor (zap_top.v) @@ -100,10 +98,18 @@ | output | | o_wb_cyc_nxt | IGNORE THIS PORT. LEAVE OPEN. | | output | [31:0] | o_wb_adr_nxt | IGNORE THIS PORT. LEAVE OPEN. | -### Directory Structure +### Installation and Directory Structure (GIT) +To get the files of the ZAP processor, please execute: +```bash +git pull https://github.com/krevanth/ZAP.git +``` +This should provide the following file structure: + + + ├── LICENSE ├── makefile ├── README.md

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.