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

Subversion Repositories zap

Compare Revisions

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

Rev 57 → Rev 58

/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
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: 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: trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf =================================================================== --- trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf (revision 57) +++ trunk/src/testbench/External_IP/uart16550/doc/UART_spec.pdf (nonexistent)
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: trunk/src/testbench/External_IP/uart16550/rtl/raminfr.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/raminfr.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/raminfr.v (nonexistent) @@ -1,112 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// raminfr.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// Inferrable Distributed RAM for FIFOs //// -//// //// -//// Known problems (limits): //// -//// None . //// -//// //// -//// To Do: //// -//// Nothing so far. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// //// -//// Created: 2002/07/22 //// -//// Last Updated: 2002/07/22 //// -//// (See log for the revision history) //// -//// //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.1 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// - -//Following is the Verilog code for a dual-port RAM with asynchronous read. -module raminfr - (clk, we, a, dpra, di, dpo); - -parameter addr_width = 4; -parameter data_width = 8; -parameter depth = 16; - -input clk; -input we; -input [addr_width-1:0] a; -input [addr_width-1:0] dpra; -input [data_width-1:0] di; -//output [data_width-1:0] spo; -output [data_width-1:0] dpo; -reg [data_width-1:0] ram [depth-1:0]; - -wire [data_width-1:0] dpo; -wire [data_width-1:0] di; -wire [addr_width-1:0] a; -wire [addr_width-1:0] dpra; - - always @(posedge clk) begin - if (we) - ram[a] <= di; - end -// assign spo = ram[a]; - assign dpo = ram[dpra]; -endmodule - Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_receiver.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_receiver.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_receiver.v (nonexistent) @@ -1,481 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_receiver.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core receiver logic //// -//// //// -//// Known problems (limits): //// -//// None known //// -//// //// -//// To Do: //// -//// Thourough testing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2001/05/17 //// -//// (See log for the revision history) //// -//// //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.29 2002/07/29 21:16:18 gorban -// The uart_defines.v file is included again in sources. -// -// Revision 1.28 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.27 2001/12/30 20:39:13 mohor -// More than one character was stored in case of break. End of the break -// was not detected correctly. -// -// Revision 1.26 2001/12/20 13:28:27 mohor -// Missing declaration of rf_push_q fixed. -// -// Revision 1.25 2001/12/20 13:25:46 mohor -// rx push changed to be only one cycle wide. -// -// Revision 1.24 2001/12/19 08:03:34 mohor -// Warnings cleared. -// -// Revision 1.23 2001/12/19 07:33:54 mohor -// Synplicity was having troubles with the comment. -// -// Revision 1.22 2001/12/17 14:46:48 mohor -// overrun signal was moved to separate block because many sequential lsr -// reads were preventing data from being written to rx fifo. -// underrun signal was not used and was removed from the project. -// -// Revision 1.21 2001/12/13 10:31:16 mohor -// timeout irq must be set regardless of the rda irq (rda irq does not reset the -// timeout counter). -// -// Revision 1.20 2001/12/10 19:52:05 gorban -// Igor fixed break condition bugs -// -// Revision 1.19 2001/12/06 14:51:04 gorban -// Bug in LSR[0] is fixed. -// All WISHBONE signals are now sampled, so another wait-state is introduced on all transfers. -// -// Revision 1.18 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.17 2001/11/28 19:36:39 gorban -// Fixed: timeout and break didn't pay attention to current data format when counting time -// -// Revision 1.16 2001/11/27 22:17:09 gorban -// Fixed bug that prevented synthesis in uart_receiver.v -// -// Revision 1.15 2001/11/26 21:38:54 gorban -// Lots of fixes: -// Break condition wasn't handled correctly at all. -// LSR bits could lose their values. -// LSR value after reset was wrong. -// Timing of THRE interrupt signal corrected. -// LSR bit 0 timing corrected. -// -// Revision 1.14 2001/11/10 12:43:21 gorban -// Logic Synthesis bugs fixed. Some other minor changes -// -// Revision 1.13 2001/11/08 14:54:23 mohor -// Comments in Slovene language deleted, few small fixes for better work of -// old tools. IRQs need to be fix. -// -// Revision 1.12 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.11 2001/10/31 15:19:22 gorban -// Fixes to break and timeout conditions -// -// Revision 1.10 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.9 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.8 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.6 2001/06/23 11:21:48 gorban -// DL made 16-bit long. Fixed transmission/reception bugs. -// -// Revision 1.5 2001/06/02 14:28:14 gorban -// Fixed receiver and transmitter. Major bug fixed. -// -// Revision 1.4 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/27 17:37:49 gorban -// Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. -// -// Revision 1.2 2001/05/21 19:12:02 gorban -// Corrected some Linter messages. -// -// Revision 1.1 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:11+02 jacob -// Initial revision -// -// -//// Modified for use in the ZAP project by Revanth Kamaraj //// - - -`include "uart_defines.v" - -module uart_receiver (clk, wb_rst_i, lcr, rf_pop, srx_pad_i, enable, - counter_t, rf_count, rf_data_out, rf_error_bit, rf_overrun, rx_reset, lsr_mask, rstate, rf_push_pulse); - -input clk; -input wb_rst_i; -input [7:0] lcr; -input rf_pop; -input srx_pad_i; -input enable; -input rx_reset; -input lsr_mask; - -output [9:0] counter_t; -output [`UART_FIFO_COUNTER_W-1:0] rf_count; -output [`UART_FIFO_REC_WIDTH-1:0] rf_data_out; -output rf_overrun; -output rf_error_bit; -output [3:0] rstate; -output rf_push_pulse; - -reg [3:0] rstate; -reg [3:0] rcounter16; -reg [2:0] rbit_counter; -reg [7:0] rshift; // receiver shift register -reg rparity; // received parity -reg rparity_error; -reg rframing_error; // framing error flag -reg rbit_in; -reg rparity_xor; -reg [7:0] counter_b; // counts the 0 (low) signals -reg rf_push_q; - -// RX FIFO signals -reg [`UART_FIFO_REC_WIDTH-1:0] rf_data_in; -wire [`UART_FIFO_REC_WIDTH-1:0] rf_data_out; -wire rf_push_pulse; -reg rf_push; -wire rf_pop; -wire rf_overrun; -wire [`UART_FIFO_COUNTER_W-1:0] rf_count; -wire rf_error_bit; // an error (parity or framing) is inside the fifo -wire break_error = (counter_b == 0); - -// RX FIFO instance -uart_rfifo #(`UART_FIFO_REC_WIDTH) fifo_rx( - .clk( clk ), - .wb_rst_i( wb_rst_i ), - .data_in( rf_data_in ), - .data_out( rf_data_out ), - .push( rf_push_pulse ), - .pop( rf_pop ), - .overrun( rf_overrun ), - .count( rf_count ), - .error_bit( rf_error_bit ), - .fifo_reset( rx_reset ), - .reset_status(lsr_mask) -); - -wire rcounter16_eq_7 = (rcounter16 == 4'd7); -wire rcounter16_eq_0 = (rcounter16 == 4'd0); -wire rcounter16_eq_1 = (rcounter16 == 4'd1); - -wire [3:0] rcounter16_minus_1 = rcounter16 - 1'b1; - -parameter sr_idle = 4'd0; -parameter sr_rec_start = 4'd1; -parameter sr_rec_bit = 4'd2; -parameter sr_rec_parity = 4'd3; -parameter sr_rec_stop = 4'd4; -parameter sr_check_parity = 4'd5; -parameter sr_rec_prepare = 4'd6; -parameter sr_end_bit = 4'd7; -parameter sr_ca_lc_parity = 4'd8; -parameter sr_wait1 = 4'd9; -parameter sr_push = 4'd10; - - -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - begin - rstate <= sr_idle; - rbit_in <= 1'b0; - rcounter16 <= 0; - rbit_counter <= 0; - rparity_xor <= 1'b0; - rframing_error <= 1'b0; - rparity_error <= 1'b0; - rparity <= 1'b0; - rshift <= 0; - rf_push <= 1'b0; - rf_data_in <= 0; - end - else - if (enable) - begin - case (rstate) - sr_idle : begin - rf_push <= 1'b0; - rf_data_in <= 0; - rcounter16 <= 4'b1110; - if (srx_pad_i==1'b0 & ~break_error) // detected a pulse (start bit?) - begin - rstate <= sr_rec_start; - end - end - sr_rec_start : begin - rf_push <= 1'b0; - if (rcounter16_eq_7) // check the pulse - if (srx_pad_i==1'b1) // no start bit - rstate <= sr_idle; - else // start bit detected - rstate <= sr_rec_prepare; - rcounter16 <= rcounter16_minus_1; - end - sr_rec_prepare:begin - case (lcr[/*`UART_LC_BITS*/1:0]) // number of bits in a word - 2'b00 : rbit_counter <= 3'b100; - 2'b01 : rbit_counter <= 3'b101; - 2'b10 : rbit_counter <= 3'b110; - 2'b11 : rbit_counter <= 3'b111; - endcase - if (rcounter16_eq_0) - begin - rstate <= sr_rec_bit; - rcounter16 <= 4'b1110; - rshift <= 0; - end - else - rstate <= sr_rec_prepare; - rcounter16 <= rcounter16_minus_1; - end - sr_rec_bit : begin - if (rcounter16_eq_0) - rstate <= sr_end_bit; - if (rcounter16_eq_7) // read the bit - case (lcr[/*`UART_LC_BITS*/1:0]) // number of bits in a word - 2'b00 : rshift[4:0] <= {srx_pad_i, rshift[4:1]}; - 2'b01 : rshift[5:0] <= {srx_pad_i, rshift[5:1]}; - 2'b10 : rshift[6:0] <= {srx_pad_i, rshift[6:1]}; - 2'b11 : rshift[7:0] <= {srx_pad_i, rshift[7:1]}; - endcase - rcounter16 <= rcounter16_minus_1; - end - sr_end_bit : begin - if (rbit_counter==3'b0) // no more bits in word - if (lcr[`UART_LC_PE]) // choose state based on parity - rstate <= sr_rec_parity; - else - begin - rstate <= sr_rec_stop; - rparity_error <= 1'b0; // no parity - no error :) - end - else // else we have more bits to read - begin - rstate <= sr_rec_bit; - rbit_counter <= rbit_counter - 1'b1; - end - rcounter16 <= 4'b1110; - end - sr_rec_parity: begin - if (rcounter16_eq_7) // read the parity - begin - rparity <= srx_pad_i; - rstate <= sr_ca_lc_parity; - end - rcounter16 <= rcounter16_minus_1; - end - sr_ca_lc_parity : begin // rcounter equals 6 - rcounter16 <= rcounter16_minus_1; - rparity_xor <= ^{rshift,rparity}; // calculate parity on all incoming data - rstate <= sr_check_parity; - end - sr_check_parity: begin // rcounter equals 5 - case ({lcr[`UART_LC_EP],lcr[`UART_LC_SP]}) - 2'b00: rparity_error <= rparity_xor == 0; // no error if parity 1 - 2'b01: rparity_error <= ~rparity; // parity should sticked to 1 - 2'b10: rparity_error <= rparity_xor == 1; // error if parity is odd - 2'b11: rparity_error <= rparity; // parity should be sticked to 0 - endcase - rcounter16 <= rcounter16_minus_1; - rstate <= sr_wait1; - end - sr_wait1 : if (rcounter16_eq_0) - begin - rstate <= sr_rec_stop; - rcounter16 <= 4'b1110; - end - else - rcounter16 <= rcounter16_minus_1; - sr_rec_stop : begin - if (rcounter16_eq_7) // read the parity - begin - rframing_error <= !srx_pad_i; // no framing error if input is 1 (stop bit) - rstate <= sr_push; - end - rcounter16 <= rcounter16_minus_1; - end - sr_push : begin -/////////////////////////////////////// -// $display($time, ": received: %b", rf_data_in); - if(srx_pad_i | break_error) - begin - if(break_error) - rf_data_in <= {8'b0, 3'b100}; // break input (empty character) to receiver FIFO - else - rf_data_in <= {rshift, 1'b0, rparity_error, rframing_error}; - rf_push <= 1'b1; - rstate <= sr_idle; - end - else if(~rframing_error) // There's always a framing before break_error -> wait for break or srx_pad_i - begin - rf_data_in <= {rshift, 1'b0, rparity_error, rframing_error}; - rf_push <= 1'b1; - rcounter16 <= 4'b1110; - rstate <= sr_rec_start; - end - - end - default : rstate <= sr_idle; - endcase - end // if (enable) -end // always of receiver - -always @ (posedge clk or posedge wb_rst_i) -begin - if(wb_rst_i) - rf_push_q <= 0; - else - rf_push_q <= rf_push; -end - -assign rf_push_pulse = rf_push & ~rf_push_q; - - -// -// Break condition detection. -// Works in conjuction with the receiver state machine - -reg [9:0] toc_value; // value to be set to timeout counter - -always @(lcr) - case (lcr[3:0]) - 4'b0000 : toc_value = 447; // 7 bits - 4'b0100 : toc_value = 479; // 7.5 bits - 4'b0001, 4'b1000 : toc_value = 511; // 8 bits - 4'b1100 : toc_value = 543; // 8.5 bits - 4'b0010, 4'b0101, 4'b1001 : toc_value = 575; // 9 bits - 4'b0011, 4'b0110, 4'b1010, 4'b1101 : toc_value = 639; // 10 bits - 4'b0111, 4'b1011, 4'b1110 : toc_value = 703; // 11 bits - 4'b1111 : toc_value = 767; // 12 bits - endcase // case(lcr[3:0]) - -wire [7:0] brc_value; // value to be set to break counter -assign brc_value = toc_value[9:2]; // the same as timeout but 1 insead of 4 character times - -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - counter_b <= 8'd159; - else - if (srx_pad_i) - counter_b <= brc_value; // character time length - 1 - else - if(enable & counter_b != 8'b0) // only work on enable times break not reached. - counter_b <= counter_b - 1; // decrement break counter -end // always of break condition detection - -/// -/// Timeout condition detection -reg [9:0] counter_t; // counts the timeout condition clocks - -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - counter_t <= 10'd639; // 10 bits for the default 8N1 - else - if(rf_push_pulse || rf_pop || rf_count == 0) // counter is reset when RX FIFO is empty, accessed or above trigger level - counter_t <= toc_value; - else - if (enable && counter_t != 10'b0) // we don't want to underflow - counter_t <= counter_t - 1; -end - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_debug_if.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_debug_if.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_debug_if.v (nonexistent) @@ -1,124 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_debug_if.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core debug interface. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// //// -//// Created: 2001/12/02 //// -//// (See log for the revision history) //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.4 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.3 2001/12/19 08:40:03 mohor -// Warnings fixed (unused signals removed). -// -// Revision 1.2 2001/12/12 22:17:30 gorban -// some synthesis bugs fixed -// -// Revision 1.1 2001/12/04 21:14:16 gorban -// committed the debug interface file -// - - -`include "uart_defines.v" - -module uart_debug_if (/*AUTOARG*/ -// Outputs -wb_dat32_o, -// Inputs -wb_adr_i, ier, iir, fcr, mcr, lcr, msr, -lsr, rf_count, tf_count, tstate, rstate -) ; - -input [`UART_ADDR_WIDTH-1:0] wb_adr_i; -output [31:0] wb_dat32_o; -input [3:0] ier; -input [3:0] iir; -input [1:0] fcr; /// bits 7 and 6 of fcr. Other bits are ignored -input [4:0] mcr; -input [7:0] lcr; -input [7:0] msr; -input [7:0] lsr; -input [`UART_FIFO_COUNTER_W-1:0] rf_count; -input [`UART_FIFO_COUNTER_W-1:0] tf_count; -input [2:0] tstate; -input [3:0] rstate; - - -wire [`UART_ADDR_WIDTH-1:0] wb_adr_i; -reg [31:0] wb_dat32_o; - -always @(/*AUTOSENSE*/fcr or ier or iir or lcr or lsr or mcr or msr - or rf_count or rstate or tf_count or tstate or wb_adr_i) - case (wb_adr_i) - // 8 + 8 + 4 + 4 + 8 - 5'b01000: wb_dat32_o = {msr,lcr,iir,ier,lsr}; - // 5 + 2 + 5 + 4 + 5 + 3 - 5'b01100: wb_dat32_o = {8'b0, fcr,mcr, rf_count, rstate, tf_count, tstate}; - default: wb_dat32_o = 0; - endcase // case(wb_adr_i) - -endmodule // uart_debug_if - Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_rfifo.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_rfifo.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_rfifo.v (nonexistent) @@ -1,318 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_rfifo.v (Modified from uart_fifo.v) //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core receiver FIFO //// -//// //// -//// To Do: //// -//// Nothing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2002/07/22 //// -//// (See log for the revision history) //// -//// //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.3 2003/06/11 16:37:47 gorban -// This fixes errors in some cases when data is being read and put to the FIFO at the same time. Patch is submitted by Scott Furman. Update is very recommended. -// -// Revision 1.2 2002/07/29 21:16:18 gorban -// The uart_defines.v file is included again in sources. -// -// Revision 1.1 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.16 2001/12/20 13:25:46 mohor -// rx push changed to be only one cycle wide. -// -// Revision 1.15 2001/12/18 09:01:07 mohor -// Bug that was entered in the last update fixed (rx state machine). -// -// Revision 1.14 2001/12/17 14:46:48 mohor -// overrun signal was moved to separate block because many sequential lsr -// reads were preventing data from being written to rx fifo. -// underrun signal was not used and was removed from the project. -// -// Revision 1.13 2001/11/26 21:38:54 gorban -// Lots of fixes: -// Break condition wasn't handled correctly at all. -// LSR bits could lose their values. -// LSR value after reset was wrong. -// Timing of THRE interrupt signal corrected. -// LSR bit 0 timing corrected. -// -// Revision 1.12 2001/11/08 14:54:23 mohor -// Comments in Slovene language deleted, few small fixes for better work of -// old tools. IRQs need to be fix. -// -// Revision 1.11 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.10 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.9 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.8 2001/08/24 08:48:10 mohor -// FIFO was not cleared after the data was read bug fixed. -// -// Revision 1.7 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.3 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/27 17:37:48 gorban -// Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. -// -// Revision 1.2 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:12+02 jacob -// Initial revision -// -// - - -`include "uart_defines.v" - -module uart_rfifo (clk, - wb_rst_i, data_in, data_out, -// Control signals - push, // push strobe, active high - pop, // pop strobe, active high -// status signals - overrun, - count, - error_bit, - fifo_reset, - reset_status - ); - - -// FIFO parameters -parameter fifo_width = `UART_FIFO_WIDTH; -parameter fifo_depth = `UART_FIFO_DEPTH; -parameter fifo_pointer_w = `UART_FIFO_POINTER_W; -parameter fifo_counter_w = `UART_FIFO_COUNTER_W; - -input clk; -input wb_rst_i; -input push; -input pop; -input [fifo_width-1:0] data_in; -input fifo_reset; -input reset_status; - -output [fifo_width-1:0] data_out; -output overrun; -output [fifo_counter_w-1:0] count; -output error_bit; - -wire [fifo_width-1:0] data_out; -wire [7:0] data8_out; -// flags FIFO -reg [2:0] fifo[fifo_depth-1:0]; - -// FIFO pointers -reg [fifo_pointer_w-1:0] top; -reg [fifo_pointer_w-1:0] bottom; - -reg [fifo_counter_w-1:0] count; -reg overrun; - -wire [fifo_pointer_w-1:0] top_plus_1 = top + 1'b1; - -raminfr #(fifo_pointer_w,8,fifo_depth) rfifo - (.clk(clk), - .we(push), - .a(top), - .dpra(bottom), - .di(data_in[fifo_width-1:fifo_width-8]), - .dpo(data8_out) - ); - -always @(posedge clk or posedge wb_rst_i) // synchronous FIFO -begin - if (wb_rst_i) - begin - top <= 0; - bottom <= 1'b0; - count <= 0; - fifo[0] <= 0; - fifo[1] <= 0; - fifo[2] <= 0; - fifo[3] <= 0; - fifo[4] <= 0; - fifo[5] <= 0; - fifo[6] <= 0; - fifo[7] <= 0; - fifo[8] <= 0; - fifo[9] <= 0; - fifo[10] <= 0; - fifo[11] <= 0; - fifo[12] <= 0; - fifo[13] <= 0; - fifo[14] <= 0; - fifo[15] <= 0; - end - else - if (fifo_reset) begin - top <= 0; - bottom <= 1'b0; - count <= 0; - fifo[0] <= 0; - fifo[1] <= 0; - fifo[2] <= 0; - fifo[3] <= 0; - fifo[4] <= 0; - fifo[5] <= 0; - fifo[6] <= 0; - fifo[7] <= 0; - fifo[8] <= 0; - fifo[9] <= 0; - fifo[10] <= 0; - fifo[11] <= 0; - fifo[12] <= 0; - fifo[13] <= 0; - fifo[14] <= 0; - fifo[15] <= 0; - end - else - begin - case ({push, pop}) - 2'b10 : if (count0) - begin - fifo[bottom] <= 0; - bottom <= bottom + 1'b1; - count <= count - 1'b1; - end - 2'b11 : begin - bottom <= bottom + 1'b1; - top <= top_plus_1; - fifo[top] <= data_in[2:0]; - end - default: ; - endcase - end -end // always - -always @(posedge clk or posedge wb_rst_i) // synchronous FIFO -begin - if (wb_rst_i) - overrun <= 1'b0; - else - if(fifo_reset | reset_status) - overrun <= 1'b0; - else - if(push & ~pop & (count==fifo_depth)) - overrun <= 1'b1; -end // always - - -// please note though that data_out is only valid one clock after pop signal -assign data_out = {data8_out,fifo[bottom]}; - -// Additional logic for detection of error conditions (parity and framing) inside the FIFO -// for the Line Status Register bit 7 - -wire [2:0] word0 = fifo[0]; -wire [2:0] word1 = fifo[1]; -wire [2:0] word2 = fifo[2]; -wire [2:0] word3 = fifo[3]; -wire [2:0] word4 = fifo[4]; -wire [2:0] word5 = fifo[5]; -wire [2:0] word6 = fifo[6]; -wire [2:0] word7 = fifo[7]; - -wire [2:0] word8 = fifo[8]; -wire [2:0] word9 = fifo[9]; -wire [2:0] word10 = fifo[10]; -wire [2:0] word11 = fifo[11]; -wire [2:0] word12 = fifo[12]; -wire [2:0] word13 = fifo[13]; -wire [2:0] word14 = fifo[14]; -wire [2:0] word15 = fifo[15]; - -// a 1 is returned if any of the error bits in the fifo is 1 -assign error_bit = |(word0[2:0] | word1[2:0] | word2[2:0] | word3[2:0] | - word4[2:0] | word5[2:0] | word6[2:0] | word7[2:0] | - word8[2:0] | word9[2:0] | word10[2:0] | word11[2:0] | - word12[2:0] | word13[2:0] | word14[2:0] | word15[2:0] ); - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_tfifo.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_tfifo.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_tfifo.v (nonexistent) @@ -1,241 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_tfifo.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core transmitter FIFO //// -//// //// -//// To Do: //// -//// Nothing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2002/07/22 //// -//// (See log for the revision history) //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.1 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.16 2001/12/20 13:25:46 mohor -// rx push changed to be only one cycle wide. -// -// Revision 1.15 2001/12/18 09:01:07 mohor -// Bug that was entered in the last update fixed (rx state machine). -// -// Revision 1.14 2001/12/17 14:46:48 mohor -// overrun signal was moved to separate block because many sequential lsr -// reads were preventing data from being written to rx fifo. -// underrun signal was not used and was removed from the project. -// -// Revision 1.13 2001/11/26 21:38:54 gorban -// Lots of fixes: -// Break condition wasn't handled correctly at all. -// LSR bits could lose their values. -// LSR value after reset was wrong. -// Timing of THRE interrupt signal corrected. -// LSR bit 0 timing corrected. -// -// Revision 1.12 2001/11/08 14:54:23 mohor -// Comments in Slovene language deleted, few small fixes for better work of -// old tools. IRQs need to be fix. -// -// Revision 1.11 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.10 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.9 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.8 2001/08/24 08:48:10 mohor -// FIFO was not cleared after the data was read bug fixed. -// -// Revision 1.7 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.3 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/27 17:37:48 gorban -// Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. -// -// Revision 1.2 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:12+02 jacob -// Initial revision -// -// - - -`include "uart_defines.v" - -module uart_tfifo (clk, - wb_rst_i, data_in, data_out, -// Control signals - push, // push strobe, active high - pop, // pop strobe, active high -// status signals - overrun, - count, - fifo_reset, - reset_status - ); - - -// FIFO parameters -parameter fifo_width = `UART_FIFO_WIDTH; -parameter fifo_depth = `UART_FIFO_DEPTH; -parameter fifo_pointer_w = `UART_FIFO_POINTER_W; -parameter fifo_counter_w = `UART_FIFO_COUNTER_W; - -input clk; -input wb_rst_i; -input push; -input pop; -input [fifo_width-1:0] data_in; -input fifo_reset; -input reset_status; - -output [fifo_width-1:0] data_out; -output overrun; -output [fifo_counter_w-1:0] count; - -wire [fifo_width-1:0] data_out; - -// FIFO pointers -reg [fifo_pointer_w-1:0] top; -reg [fifo_pointer_w-1:0] bottom; - -reg [fifo_counter_w-1:0] count; -reg overrun; -wire [fifo_pointer_w-1:0] top_plus_1 = top + 1'b1; - -raminfr #(fifo_pointer_w,fifo_width,fifo_depth) tfifo - (.clk(clk), - .we(push), - .a(top), - .dpra(bottom), - .di(data_in), - .dpo(data_out) - ); - - -always @(posedge clk or posedge wb_rst_i) // synchronous FIFO -begin - if (wb_rst_i) - begin - top <= 0; - bottom <= 1'b0; - count <= 0; - end - else - if (fifo_reset) begin - top <= 0; - bottom <= 1'b0; - count <= 0; - end - else - begin - case ({push, pop}) - 2'b10 : if (count0) - begin - bottom <= bottom + 1'b1; - count <= count - 1'b1; - end - 2'b11 : begin - bottom <= bottom + 1'b1; - top <= top_plus_1; - end - default: ; - endcase - end -end // always - -always @(posedge clk or posedge wb_rst_i) // synchronous FIFO -begin - if (wb_rst_i) - overrun <= 1'b0; - else - if(fifo_reset | reset_status) - overrun <= 1'b0; - else - if(push & (count==fifo_depth)) - overrun <= 1'b1; -end // always - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_wb.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_wb.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_wb.v (nonexistent) @@ -1,314 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_wb.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core WISHBONE interface. //// -//// //// -//// Known problems (limits): //// -//// Inserts one wait state on all transfers. //// -//// Note affected signals and the way they are affected. //// -//// //// -//// To Do: //// -//// Nothing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2001/05/17 //// -//// (See log for the revision history) //// -//// //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.16 2002/07/29 21:16:18 gorban -// The uart_defines.v file is included again in sources. -// -// Revision 1.15 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.12 2001/12/19 08:03:34 mohor -// Warnings cleared. -// -// Revision 1.11 2001/12/06 14:51:04 gorban -// Bug in LSR[0] is fixed. -// All WISHBONE signals are now sampled, so another wait-state is introduced on all transfers. -// -// Revision 1.10 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.9 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.8 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.7 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.4 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/21 19:12:01 gorban -// Corrected some Linter messages. -// -// Revision 1.2 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:13+02 jacob -// Initial revision -// -// - -// UART core WISHBONE interface -// -// Author: Jacob Gorban (jacob.gorban@flextronicssemi.com) -// Company: Flextronics Semiconductor -// - -`include "uart_defines.v" - -module uart_wb (clk, wb_rst_i, - wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_adr_i, - wb_adr_int, wb_dat_i, wb_dat_o, wb_dat8_i, wb_dat8_o, wb_dat32_o, wb_sel_i, - we_o, re_o // Write and read enable output for the core -); - -input clk; - -// WISHBONE interface -input wb_rst_i; -input wb_we_i; -input wb_stb_i; -input wb_cyc_i; -input [3:0] wb_sel_i; -input [`UART_ADDR_WIDTH-1:0] wb_adr_i; //WISHBONE address line - -`ifdef DATA_BUS_WIDTH_8 -input [7:0] wb_dat_i; //input WISHBONE bus -output [7:0] wb_dat_o; -reg [7:0] wb_dat_o; -wire [7:0] wb_dat_i; -reg [7:0] wb_dat_is; -`else // for 32 data bus mode -input [31:0] wb_dat_i; //input WISHBONE bus -output [31:0] wb_dat_o; -reg [31:0] wb_dat_o; -wire [31:0] wb_dat_i; -reg [31:0] wb_dat_is; -`endif // !`ifdef DATA_BUS_WIDTH_8 - -output [`UART_ADDR_WIDTH-1:0] wb_adr_int; // internal signal for address bus -input [7:0] wb_dat8_o; // internal 8 bit output to be put into wb_dat_o -output [7:0] wb_dat8_i; -input [31:0] wb_dat32_o; // 32 bit data output (for debug interface) -output wb_ack_o; -output we_o; -output re_o; - -wire we_o; -reg wb_ack_o; -reg [7:0] wb_dat8_i; -wire [7:0] wb_dat8_o; -wire [`UART_ADDR_WIDTH-1:0] wb_adr_int; // internal signal for address bus -reg [`UART_ADDR_WIDTH-1:0] wb_adr_is; -reg wb_we_is; -reg wb_cyc_is; -reg wb_stb_is; -reg [3:0] wb_sel_is; -wire [3:0] wb_sel_i; -reg wre ;// timing control signal for write or read enable - -// wb_ack_o FSM -reg [1:0] wbstate; -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) begin - wb_ack_o <= 1'b0; - wbstate <= 0; - wre <= 1'b1; - end else - case (wbstate) - 0: begin - if (wb_stb_is & wb_cyc_is) begin - wre <= 0; - wbstate <= 1; - wb_ack_o <= 1; - end else begin - wre <= 1; - wb_ack_o <= 0; - end - end - 1: begin - wb_ack_o <= 0; - wbstate <= 2; - wre <= 0; - end - 2,3: begin - wb_ack_o <= 0; - wbstate <= 0; - wre <= 0; - end - endcase - -assign we_o = wb_we_is & wb_stb_is & wb_cyc_is & wre ; //WE for registers -assign re_o = ~wb_we_is & wb_stb_is & wb_cyc_is & wre ; //RE for registers - -// Sample input signals -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) begin - wb_adr_is <= 0; - wb_we_is <= 0; - wb_cyc_is <= 0; - wb_stb_is <= 0; - wb_dat_is <= 0; - wb_sel_is <= 0; - end else begin - wb_adr_is <= wb_adr_i; - wb_we_is <= wb_we_i; - wb_cyc_is <= wb_cyc_i; - wb_stb_is <= wb_stb_i; - wb_dat_is <= wb_dat_i; - wb_sel_is <= wb_sel_i; - end - -`ifdef DATA_BUS_WIDTH_8 // 8-bit data bus -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - wb_dat_o <= 0; - else - wb_dat_o <= wb_dat8_o; - -always @(wb_dat_is) - wb_dat8_i = wb_dat_is; - -assign wb_adr_int = wb_adr_is; - -`else // 32-bit bus -// put output to the correct byte in 32 bits using select line -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - wb_dat_o <= 0; - else if (re_o) - case (wb_sel_is) - 4'b0001: wb_dat_o <= {24'b0, wb_dat8_o}; - 4'b0010: wb_dat_o <= {16'b0, wb_dat8_o, 8'b0}; - 4'b0100: wb_dat_o <= {8'b0, wb_dat8_o, 16'b0}; - 4'b1000: wb_dat_o <= {wb_dat8_o, 24'b0}; - 4'b1111: wb_dat_o <= wb_dat32_o; // debug interface output - default: wb_dat_o <= 0; - endcase // case(wb_sel_i) - -reg [1:0] wb_adr_int_lsb; - -always @(wb_sel_is or wb_dat_is) -begin - case (wb_sel_is) - 4'b0001 : wb_dat8_i = wb_dat_is[7:0]; - 4'b0010 : wb_dat8_i = wb_dat_is[15:8]; - 4'b0100 : wb_dat8_i = wb_dat_is[23:16]; - 4'b1000 : wb_dat8_i = wb_dat_is[31:24]; - default : wb_dat8_i = wb_dat_is[7:0]; - endcase // case(wb_sel_i) - - `ifdef LITLE_ENDIAN - case (wb_sel_is) - 4'b0001 : wb_adr_int_lsb = 2'h0; - 4'b0010 : wb_adr_int_lsb = 2'h1; - 4'b0100 : wb_adr_int_lsb = 2'h2; - 4'b1000 : wb_adr_int_lsb = 2'h3; - default : wb_adr_int_lsb = 2'h0; - endcase // case(wb_sel_i) - `else - case (wb_sel_is) - 4'b0001 : wb_adr_int_lsb = 2'h3; - 4'b0010 : wb_adr_int_lsb = 2'h2; - 4'b0100 : wb_adr_int_lsb = 2'h1; - 4'b1000 : wb_adr_int_lsb = 2'h0; - default : wb_adr_int_lsb = 2'h0; - endcase // case(wb_sel_i) - `endif -end - -assign wb_adr_int = {wb_adr_is[`UART_ADDR_WIDTH-1:2], wb_adr_int_lsb}; - -`endif // !`ifdef DATA_BUS_WIDTH_8 - -endmodule - - - - - - - - - - Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_transmitter.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_transmitter.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_transmitter.v (nonexistent) @@ -1,349 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_transmitter.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core transmitter logic //// -//// //// -//// Known problems (limits): //// -//// None known //// -//// //// -//// To Do: //// -//// Thourough testing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2001/05/17 //// -//// (See log for the revision history) //// -//// //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.18 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.16 2002/01/08 11:29:40 mohor -// tf_pop was too wide. Now it is only 1 clk cycle width. -// -// Revision 1.15 2001/12/17 14:46:48 mohor -// overrun signal was moved to separate block because many sequential lsr -// reads were preventing data from being written to rx fifo. -// underrun signal was not used and was removed from the project. -// -// Revision 1.14 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.13 2001/11/08 14:54:23 mohor -// Comments in Slovene language deleted, few small fixes for better work of -// old tools. IRQs need to be fix. -// -// Revision 1.12 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.11 2001/10/29 17:00:46 gorban -// fixed parity sending and tx_fifo resets over- and underrun -// -// Revision 1.10 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.9 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.8 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.6 2001/06/23 11:21:48 gorban -// DL made 16-bit long. Fixed transmission/reception bugs. -// -// Revision 1.5 2001/06/02 14:28:14 gorban -// Fixed receiver and transmitter. Major bug fixed. -// -// Revision 1.4 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/27 17:37:49 gorban -// Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. -// -// Revision 1.2 2001/05/21 19:12:02 gorban -// Corrected some Linter messages. -// -// Revision 1.1 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:12+02 jacob -// Initial revision -// -// - - -`include "uart_defines.v" - -module uart_transmitter (clk, wb_rst_i, lcr, tf_push, wb_dat_i, enable, stx_pad_o, tstate, tf_count, tx_reset, lsr_mask); - -input clk; -input wb_rst_i; -input [7:0] lcr; -input tf_push; -input [7:0] wb_dat_i; -input enable; -input tx_reset; -input lsr_mask; //reset of fifo -output stx_pad_o; -output [2:0] tstate; -output [`UART_FIFO_COUNTER_W-1:0] tf_count; - -reg [2:0] tstate; -reg [4:0] counter; -reg [2:0] bit_counter; // counts the bits to be sent -reg [6:0] shift_out; // output shift register -reg stx_o_tmp; -reg parity_xor; // parity of the word -reg tf_pop; -reg bit_out; - -// TX FIFO instance -// -// Transmitter FIFO signals -wire [`UART_FIFO_WIDTH-1:0] tf_data_in; -wire [`UART_FIFO_WIDTH-1:0] tf_data_out; -wire tf_push; -wire tf_overrun; -wire [`UART_FIFO_COUNTER_W-1:0] tf_count; - -assign tf_data_in = wb_dat_i; - -uart_tfifo fifo_tx( // error bit signal is not used in transmitter FIFO - .clk( clk ), - .wb_rst_i( wb_rst_i ), - .data_in( tf_data_in ), - .data_out( tf_data_out ), - .push( tf_push ), - .pop( tf_pop ), - .overrun( tf_overrun ), - .count( tf_count ), - .fifo_reset( tx_reset ), - .reset_status(lsr_mask) -); - -// TRANSMITTER FINAL STATE MACHINE - -parameter s_idle = 3'd0; -parameter s_send_start = 3'd1; -parameter s_send_byte = 3'd2; -parameter s_send_parity = 3'd3; -parameter s_send_stop = 3'd4; -parameter s_pop_byte = 3'd5; - -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - begin - tstate <= s_idle; - stx_o_tmp <= 1'b1; - counter <= 5'b0; - shift_out <= 7'b0; - bit_out <= 1'b0; - parity_xor <= 1'b0; - tf_pop <= 1'b0; - bit_counter <= 3'b0; - end - else - if (enable) - begin - case (tstate) - s_idle : if (~|tf_count) // if tf_count==0 - begin - tstate <= s_idle; - stx_o_tmp <= 1'b1; - end - else - begin - tf_pop <= 1'b0; - stx_o_tmp <= 1'b1; - tstate <= s_pop_byte; - end - s_pop_byte : begin - tf_pop <= 1'b1; - case (lcr[/*`UART_LC_BITS*/1:0]) // number of bits in a word - 2'b00 : begin - bit_counter <= 3'b100; - parity_xor <= ^tf_data_out[4:0]; - end - 2'b01 : begin - bit_counter <= 3'b101; - parity_xor <= ^tf_data_out[5:0]; - end - 2'b10 : begin - bit_counter <= 3'b110; - parity_xor <= ^tf_data_out[6:0]; - end - 2'b11 : begin - bit_counter <= 3'b111; - parity_xor <= ^tf_data_out[7:0]; - end - endcase - {shift_out[6:0], bit_out} <= tf_data_out; - tstate <= s_send_start; - end - s_send_start : begin - tf_pop <= 1'b0; - if (~|counter) - counter <= 5'b01111; - else - if (counter == 5'b00001) - begin - counter <= 0; - tstate <= s_send_byte; - end - else - counter <= counter - 1'b1; - stx_o_tmp <= 1'b0; - end - s_send_byte : begin - if (~|counter) - counter <= 5'b01111; - else - if (counter == 5'b00001) - begin - if (bit_counter > 3'b0) - begin - bit_counter <= bit_counter - 1'b1; - {shift_out[5:0],bit_out } <= {shift_out[6:1], shift_out[0]}; - tstate <= s_send_byte; - end - else // end of byte - if (~lcr[`UART_LC_PE]) - begin - tstate <= s_send_stop; - end - else - begin - case ({lcr[`UART_LC_EP],lcr[`UART_LC_SP]}) - 2'b00: bit_out <= ~parity_xor; - 2'b01: bit_out <= 1'b1; - 2'b10: bit_out <= parity_xor; - 2'b11: bit_out <= 1'b0; - endcase - tstate <= s_send_parity; - end - counter <= 0; - end - else - counter <= counter - 1'b1; - stx_o_tmp <= bit_out; // set output pin - end - s_send_parity : begin - if (~|counter) - counter <= 5'b01111; - else - if (counter == 5'b00001) - begin - counter <= 4'b0; - tstate <= s_send_stop; - end - else - counter <= counter - 1'b1; - stx_o_tmp <= bit_out; - end - s_send_stop : begin - if (~|counter) - begin - casex ({lcr[`UART_LC_SB],lcr[`UART_LC_BITS]}) - 3'b0xx: counter <= 5'b01101; // 1 stop bit ok igor - 3'b100: counter <= 5'b10101; // 1.5 stop bit - default: counter <= 5'b11101; // 2 stop bits - endcase - end - else - if (counter == 5'b00001) - begin - counter <= 0; - tstate <= s_idle; - end - else - counter <= counter - 1'b1; - stx_o_tmp <= 1'b1; - end - - default : // should never get here - tstate <= s_idle; - endcase - end // end if enable - else - tf_pop <= 1'b0; // tf_pop must be 1 cycle width -end // transmitter logic - -assign stx_pad_o = lcr[`UART_LC_BC] ? 1'b0 : stx_o_tmp; // Break condition - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_defines.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_defines.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_defines.v (nonexistent) @@ -1,249 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_defines.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// Defines of the Core //// -//// //// -//// Known problems (limits): //// -//// None //// -//// //// -//// To Do: //// -//// Nothing. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2001/05/17 //// -//// (See log for the revision history) //// -///// Modified for use in the ZAP project by Revanth Kamaraj //// -/// //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.13 2003/06/11 16:37:47 gorban -// This fixes errors in some cases when data is being read and put to the FIFO at the same time. Patch is submitted by Scott Furman. Update is very recommended. -// -// Revision 1.12 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.10 2001/12/11 08:55:40 mohor -// Scratch register define added. -// -// Revision 1.9 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.8 2001/11/26 21:38:54 gorban -// Lots of fixes: -// Break condition wasn't handled correctly at all. -// LSR bits could lose their values. -// LSR value after reset was wrong. -// Timing of THRE interrupt signal corrected. -// LSR bit 0 timing corrected. -// -// Revision 1.7 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.6 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.5 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.4 2001/05/21 19:12:02 gorban -// Corrected some Linter messages. -// -// Revision 1.3 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:11+02 jacob -// Initial revision -// -// - -// remove comments to restore to use the new version with 8 data bit interface -// in 32bit-bus mode, the wb_sel_i signal is used to put data in correct place -// also, in 8-bit version there'll be no debugging features included -// CAUTION: doesn't work with current version of OR1200 -//`define DATA_BUS_WIDTH_8 - -`ifdef DATA_BUS_WIDTH_8 - `define UART_ADDR_WIDTH 3 - `define UART_DATA_WIDTH 8 -`else - `define UART_ADDR_WIDTH 5 - `define UART_DATA_WIDTH 32 -`endif - -// Uncomment this if you want your UART to have -// 16xBaudrate output port. -// If defined, the enable signal will be used to drive baudrate_o signal -// It's frequency is 16xbaudrate - -// `define UART_HAS_BAUDRATE_OUTPUT - -// Register addresses -`define UART_REG_RB `UART_ADDR_WIDTH'd0 // receiver buffer -`define UART_REG_TR `UART_ADDR_WIDTH'd0 // transmitter -`define UART_REG_IE `UART_ADDR_WIDTH'd1 // Interrupt enable -`define UART_REG_II `UART_ADDR_WIDTH'd2 // Interrupt identification -`define UART_REG_FC `UART_ADDR_WIDTH'd2 // FIFO control -`define UART_REG_LC `UART_ADDR_WIDTH'd3 // Line Control -`define UART_REG_MC `UART_ADDR_WIDTH'd4 // Modem control -`define UART_REG_LS `UART_ADDR_WIDTH'd5 // Line status -`define UART_REG_MS `UART_ADDR_WIDTH'd6 // Modem status -`define UART_REG_SR `UART_ADDR_WIDTH'd7 // Scratch register -`define UART_REG_DL1 `UART_ADDR_WIDTH'd0 // Divisor latch bytes (1-2) -`define UART_REG_DL2 `UART_ADDR_WIDTH'd1 - -// Interrupt Enable register bits -`define UART_IE_RDA 0 // Received Data available interrupt -`define UART_IE_THRE 1 // Transmitter Holding Register empty interrupt -`define UART_IE_RLS 2 // Receiver Line Status Interrupt -`define UART_IE_MS 3 // Modem Status Interrupt - -// Interrupt Identification register bits -`define UART_II_IP 0 // Interrupt pending when 0 -`define UART_II_II 3:1 // Interrupt identification - -// Interrupt identification values for bits 3:1 -`define UART_II_RLS 3'b011 // Receiver Line Status -`define UART_II_RDA 3'b010 // Receiver Data available -`define UART_II_TI 3'b110 // Timeout Indication -`define UART_II_THRE 3'b001 // Transmitter Holding Register empty -`define UART_II_MS 3'b000 // Modem Status - -// FIFO Control Register bits -`define UART_FC_TL 1:0 // Trigger level - -// FIFO trigger level values -`define UART_FC_1 2'b00 -`define UART_FC_4 2'b01 -`define UART_FC_8 2'b10 -`define UART_FC_14 2'b11 - -// Line Control register bits -`define UART_LC_BITS 1:0 // bits in character -`define UART_LC_SB 2 // stop bits -`define UART_LC_PE 3 // parity enable -`define UART_LC_EP 4 // even parity -`define UART_LC_SP 5 // stick parity -`define UART_LC_BC 6 // Break control -`define UART_LC_DL 7 // Divisor Latch access bit - -// Modem Control register bits -`define UART_MC_DTR 0 -`define UART_MC_RTS 1 -`define UART_MC_OUT1 2 -`define UART_MC_OUT2 3 -`define UART_MC_LB 4 // Loopback mode - -// Line Status Register bits -`define UART_LS_DR 0 // Data ready -`define UART_LS_OE 1 // Overrun Error -`define UART_LS_PE 2 // Parity Error -`define UART_LS_FE 3 // Framing Error -`define UART_LS_BI 4 // Break interrupt -`define UART_LS_TFE 5 // Transmit FIFO is empty -`define UART_LS_TE 6 // Transmitter Empty indicator -`define UART_LS_EI 7 // Error indicator - -// Modem Status Register bits -`define UART_MS_DCTS 0 // Delta signals -`define UART_MS_DDSR 1 -`define UART_MS_TERI 2 -`define UART_MS_DDCD 3 -`define UART_MS_CCTS 4 // Complement signals -`define UART_MS_CDSR 5 -`define UART_MS_CRI 6 -`define UART_MS_CDCD 7 - -// FIFO parameter defines - -`define UART_FIFO_WIDTH 8 -`define UART_FIFO_DEPTH 16 -`define UART_FIFO_POINTER_W 4 -`define UART_FIFO_COUNTER_W 5 -// receiver fifo has width 11 because it has break, parity and framing error bits -`define UART_FIFO_REC_WIDTH 11 - - -`define VERBOSE_WB 0 // All activity on the WISHBONE is recorded -`define VERBOSE_LINE_STATUS 0 // Details about the lsr (line status register) -`define FAST_TEST 1 // 64/1024 packets are sent - -// Added by Revanth to support LITTLE_ENDIAN mode of operation. -`define LITLE_ENDIAN - - - - - Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_sync_flops.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_sync_flops.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_sync_flops.v (nonexistent) @@ -1,122 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_sync_flops.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core receiver logic //// -//// //// -//// Known problems (limits): //// -//// None known //// -//// //// -//// To Do: //// -//// Thourough testing. //// -//// //// -//// Author(s): //// -//// - Andrej Erzen (andreje@flextronics.si) //// -//// - Tadej Markovic (tadejm@flextronics.si) //// -//// //// -//// Created: 2004/05/20 //// -//// Last Updated: 2004/05/20 //// -//// (See log for the revision history) //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// - - - - -module uart_sync_flops -( - // internal signals - rst_i, - clk_i, - stage1_rst_i, - stage1_clk_en_i, - async_dat_i, - sync_dat_o -); - -parameter Tp = 1; -parameter width = 1; -parameter init_value = 1'b0; - -input rst_i; // reset input -input clk_i; // clock input -input stage1_rst_i; // synchronous reset for stage 1 FF -input stage1_clk_en_i; // synchronous clock enable for stage 1 FF -input [width-1:0] async_dat_i; // asynchronous data input -output [width-1:0] sync_dat_o; // synchronous data output - - -// -// Interal signal declarations -// - -reg [width-1:0] sync_dat_o; -reg [width-1:0] flop_0; - - -// first stage -always @ (posedge clk_i or posedge rst_i) -begin - if (rst_i) - flop_0 <= #Tp {width{init_value}}; - else - flop_0 <= #Tp async_dat_i; -end - -// second stage -always @ (posedge clk_i or posedge rst_i) -begin - if (rst_i) - sync_dat_o <= #Tp {width{init_value}}; - else if (stage1_rst_i) - sync_dat_o <= #Tp {width{init_value}}; - else if (stage1_clk_en_i) - sync_dat_o <= #Tp flop_0; -end - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_regs.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_regs.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_regs.v (nonexistent) @@ -1,892 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_regs.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// Registers of the uart 16550 core //// -//// //// -//// Known problems (limits): //// -//// Inserts 1 wait state in all WISHBONE transfers //// -//// //// -//// To Do: //// -//// Nothing or verification. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: (See log for the revision history //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.41 2004/05/21 11:44:41 tadejm -// Added synchronizer flops for RX input. -// -// Revision 1.40 2003/06/11 16:37:47 gorban -// This fixes errors in some cases when data is being read and put to the FIFO at the same time. Patch is submitted by Scott Furman. Update is very recommended. -// -// Revision 1.39 2002/07/29 21:16:18 gorban -// The uart_defines.v file is included again in sources. -// -// Revision 1.38 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.37 2001/12/27 13:24:09 mohor -// lsr[7] was not showing overrun errors. -// -// Revision 1.36 2001/12/20 13:25:46 mohor -// rx push changed to be only one cycle wide. -// -// Revision 1.35 2001/12/19 08:03:34 mohor -// Warnings cleared. -// -// Revision 1.34 2001/12/19 07:33:54 mohor -// Synplicity was having troubles with the comment. -// -// Revision 1.33 2001/12/17 10:14:43 mohor -// Things related to msr register changed. After THRE IRQ occurs, and one -// character is written to the transmit fifo, the detection of the THRE bit in the -// LSR is delayed for one character time. -// -// Revision 1.32 2001/12/14 13:19:24 mohor -// MSR register fixed. -// -// Revision 1.31 2001/12/14 10:06:58 mohor -// After reset modem status register MSR should be reset. -// -// Revision 1.30 2001/12/13 10:09:13 mohor -// thre irq should be cleared only when being source of interrupt. -// -// Revision 1.29 2001/12/12 09:05:46 mohor -// LSR status bit 0 was not cleared correctly in case of reseting the FCR (rx fifo). -// -// Revision 1.28 2001/12/10 19:52:41 gorban -// Scratch register added -// -// Revision 1.27 2001/12/06 14:51:04 gorban -// Bug in LSR[0] is fixed. -// All WISHBONE signals are now sampled, so another wait-state is introduced on all transfers. -// -// Revision 1.26 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.25 2001/11/28 19:36:39 gorban -// Fixed: timeout and break didn't pay attention to current data format when counting time -// -// Revision 1.24 2001/11/26 21:38:54 gorban -// Lots of fixes: -// Break condition wasn't handled correctly at all. -// LSR bits could lose their values. -// LSR value after reset was wrong. -// Timing of THRE interrupt signal corrected. -// LSR bit 0 timing corrected. -// -// Revision 1.23 2001/11/12 21:57:29 gorban -// fixed more typo bugs -// -// Revision 1.22 2001/11/12 15:02:28 mohor -// lsr1r error fixed. -// -// Revision 1.21 2001/11/12 14:57:27 mohor -// ti_int_pnd error fixed. -// -// Revision 1.20 2001/11/12 14:50:27 mohor -// ti_int_d error fixed. -// -// Revision 1.19 2001/11/10 12:43:21 gorban -// Logic Synthesis bugs fixed. Some other minor changes -// -// Revision 1.18 2001/11/08 14:54:23 mohor -// Comments in Slovene language deleted, few small fixes for better work of -// old tools. IRQs need to be fix. -// -// Revision 1.17 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.16 2001/11/02 09:55:16 mohor -// no message -// -// Revision 1.15 2001/10/31 15:19:22 gorban -// Fixes to break and timeout conditions -// -// Revision 1.14 2001/10/29 17:00:46 gorban -// fixed parity sending and tx_fifo resets over- and underrun -// -// Revision 1.13 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.12 2001/10/19 16:21:40 gorban -// Changes data_out to be synchronous again as it should have been. -// -// Revision 1.11 2001/10/18 20:35:45 gorban -// small fix -// -// Revision 1.10 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.9 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.10 2001/06/23 11:21:48 gorban -// DL made 16-bit long. Fixed transmission/reception bugs. -// -// Revision 1.9 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.8 2001/05/29 20:05:04 gorban -// Fixed some bugs and synthesis problems. -// -// Revision 1.7 2001/05/27 17:37:49 gorban -// Fixed many bugs. Updated spec. Changed FIFO files structure. See CHANGES.txt file. -// -// Revision 1.6 2001/05/21 19:12:02 gorban -// Corrected some Linter messages. -// -// Revision 1.5 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:11+02 jacob -// Initial revision -// -// -//// Modified for use in the ZAP project by Revanth Kamaraj //// - - -`include "uart_defines.v" - -`define UART_DL1 7:0 -`define UART_DL2 15:8 - -module uart_regs (clk, - wb_rst_i, wb_addr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_re_i, - -// additional signals - modem_inputs, - stx_pad_o, srx_pad_i, - -`ifdef DATA_BUS_WIDTH_8 -`else -// debug interface signals enabled -ier, iir, fcr, mcr, lcr, msr, lsr, rf_count, tf_count, tstate, rstate, -`endif - rts_pad_o, dtr_pad_o, int_o -`ifdef UART_HAS_BAUDRATE_OUTPUT - , baud_o -`endif - - ); - -input clk; -input wb_rst_i; -input [`UART_ADDR_WIDTH-1:0] wb_addr_i; -input [7:0] wb_dat_i; -output [7:0] wb_dat_o; -input wb_we_i; -input wb_re_i; - -output stx_pad_o; -input srx_pad_i; - -input [3:0] modem_inputs; -output rts_pad_o; -output dtr_pad_o; -output int_o; -`ifdef UART_HAS_BAUDRATE_OUTPUT -output baud_o; -`endif - -`ifdef DATA_BUS_WIDTH_8 -`else -// if 32-bit databus and debug interface are enabled -output [3:0] ier; -output [3:0] iir; -output [1:0] fcr; /// bits 7 and 6 of fcr. Other bits are ignored -output [4:0] mcr; -output [7:0] lcr; -output [7:0] msr; -output [7:0] lsr; -output [`UART_FIFO_COUNTER_W-1:0] rf_count; -output [`UART_FIFO_COUNTER_W-1:0] tf_count; -output [2:0] tstate; -output [3:0] rstate; - -`endif - -wire [3:0] modem_inputs; -reg enable; -`ifdef UART_HAS_BAUDRATE_OUTPUT -assign baud_o = enable; // baud_o is actually the enable signal -`endif - - -wire stx_pad_o; // received from transmitter module -wire srx_pad_i; -wire srx_pad; - -reg [7:0] wb_dat_o; - -wire [`UART_ADDR_WIDTH-1:0] wb_addr_i; -wire [7:0] wb_dat_i; - - -reg [3:0] ier; -reg [3:0] iir; -reg [1:0] fcr; /// bits 7 and 6 of fcr. Other bits are ignored -reg [4:0] mcr; -reg [7:0] lcr; -reg [7:0] msr; -reg [15:0] dl; // 32-bit divisor latch -reg [7:0] scratch; // UART scratch register -reg start_dlc; // activate dlc on writing to UART_DL1 -reg lsr_mask_d; // delay for lsr_mask condition -reg msi_reset; // reset MSR 4 lower bits indicator -//reg threi_clear; // THRE interrupt clear flag -reg [15:0] dlc; // 32-bit divisor latch counter -reg int_o; - -reg [3:0] trigger_level; // trigger level of the receiver FIFO -reg rx_reset; -reg tx_reset; - -wire dlab; // divisor latch access bit -wire cts_pad_i, dsr_pad_i, ri_pad_i, dcd_pad_i; // modem status bits -wire loopback; // loopback bit (MCR bit 4) -wire cts, dsr, ri, dcd; // effective signals -wire cts_c, dsr_c, ri_c, dcd_c; // Complement effective signals (considering loopback) -wire rts_pad_o, dtr_pad_o; // modem control outputs - -// LSR bits wires and regs -wire [7:0] lsr; -wire lsr0, lsr1, lsr2, lsr3, lsr4, lsr5, lsr6, lsr7; -reg lsr0r, lsr1r, lsr2r, lsr3r, lsr4r, lsr5r, lsr6r, lsr7r; -wire lsr_mask; // lsr_mask - -// -// ASSINGS -// - -assign lsr[7:0] = { lsr7r, lsr6r, lsr5r, lsr4r, lsr3r, lsr2r, lsr1r, lsr0r }; - -assign {cts_pad_i, dsr_pad_i, ri_pad_i, dcd_pad_i} = modem_inputs; -assign {cts, dsr, ri, dcd} = ~{cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i}; - -assign {cts_c, dsr_c, ri_c, dcd_c} = loopback ? {mcr[`UART_MC_RTS],mcr[`UART_MC_DTR],mcr[`UART_MC_OUT1],mcr[`UART_MC_OUT2]} - : {cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i}; - -assign dlab = lcr[`UART_LC_DL]; -assign loopback = mcr[4]; - -// assign modem outputs -assign rts_pad_o = mcr[`UART_MC_RTS]; -assign dtr_pad_o = mcr[`UART_MC_DTR]; - -// Interrupt signals -wire rls_int; // receiver line status interrupt -wire rda_int; // receiver data available interrupt -wire ti_int; // timeout indicator interrupt -wire thre_int; // transmitter holding register empty interrupt -wire ms_int; // modem status interrupt - -// FIFO signals -reg tf_push; -reg rf_pop; -wire [`UART_FIFO_REC_WIDTH-1:0] rf_data_out; -wire rf_error_bit; // an error (parity or framing) is inside the fifo -wire [`UART_FIFO_COUNTER_W-1:0] rf_count; -wire [`UART_FIFO_COUNTER_W-1:0] tf_count; -wire [2:0] tstate; -wire [3:0] rstate; -wire [9:0] counter_t; - -wire thre_set_en; // THRE status is delayed one character time when a character is written to fifo. -reg [7:0] block_cnt; // While counter counts, THRE status is blocked (delayed one character cycle) -reg [7:0] block_value; // One character length minus stop bit - -// Transmitter Instance -wire serial_out; - -uart_transmitter transmitter(clk, wb_rst_i, lcr, tf_push, wb_dat_i, enable, serial_out, tstate, tf_count, tx_reset, lsr_mask); - - // Synchronizing and sampling serial RX input - uart_sync_flops i_uart_sync_flops - ( - .rst_i (wb_rst_i), - .clk_i (clk), - .stage1_rst_i (1'b0), - .stage1_clk_en_i (1'b1), - .async_dat_i (srx_pad_i), - .sync_dat_o (srx_pad) - ); - defparam i_uart_sync_flops.width = 1; - defparam i_uart_sync_flops.init_value = 1'b1; - -// handle loopback -wire serial_in = loopback ? serial_out : srx_pad; -assign stx_pad_o = loopback ? 1'b1 : serial_out; - -// Receiver Instance -uart_receiver receiver(clk, wb_rst_i, lcr, rf_pop, serial_in, enable, - counter_t, rf_count, rf_data_out, rf_error_bit, rf_overrun, rx_reset, lsr_mask, rstate, rf_push_pulse); - - -// Asynchronous reading here because the outputs are sampled in uart_wb.v file -always @(dl or dlab or ier or iir or scratch - or lcr or lsr or msr or rf_data_out or wb_addr_i or wb_re_i) // asynchrounous reading -begin - case (wb_addr_i) - `UART_REG_RB : wb_dat_o = dlab ? dl[`UART_DL1] : rf_data_out[10:3]; - `UART_REG_IE : wb_dat_o = dlab ? dl[`UART_DL2] : ier; - `UART_REG_II : wb_dat_o = {4'b1100,iir}; - `UART_REG_LC : wb_dat_o = lcr; - `UART_REG_LS : wb_dat_o = lsr; - `UART_REG_MS : wb_dat_o = msr; - `UART_REG_SR : wb_dat_o = scratch; - default: wb_dat_o = 8'b0; // ?? - endcase // case(wb_addr_i) -end // always @ (dl or dlab or ier or iir or scratch... - - -// rf_pop signal handling -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - rf_pop <= 0; - else - if (rf_pop) // restore the signal to 0 after one clock cycle - rf_pop <= 0; - else - if (wb_re_i && wb_addr_i == `UART_REG_RB && !dlab) - rf_pop <= 1; // advance read pointer -end - -wire lsr_mask_condition; -wire iir_read; -wire msr_read; -wire fifo_read; -wire fifo_write; - -assign lsr_mask_condition = (wb_re_i && wb_addr_i == `UART_REG_LS && !dlab); -assign iir_read = (wb_re_i && wb_addr_i == `UART_REG_II && !dlab); -assign msr_read = (wb_re_i && wb_addr_i == `UART_REG_MS && !dlab); -assign fifo_read = (wb_re_i && wb_addr_i == `UART_REG_RB && !dlab); -assign fifo_write = (wb_we_i && wb_addr_i == `UART_REG_TR && !dlab); - -// lsr_mask_d delayed signal handling -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - lsr_mask_d <= 0; - else // reset bits in the Line Status Register - lsr_mask_d <= lsr_mask_condition; -end - -// lsr_mask is rise detected -assign lsr_mask = lsr_mask_condition && ~lsr_mask_d; - -// msi_reset signal handling -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - msi_reset <= 1; - else - if (msi_reset) - msi_reset <= 0; - else - if (msr_read) - msi_reset <= 1; // reset bits in Modem Status Register -end - - -// -// WRITES AND RESETS // -// -// Line Control Register -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - lcr <= 8'b00000011; // 8n1 setting - else - if (wb_we_i && wb_addr_i==`UART_REG_LC) - lcr <= wb_dat_i; - -// Interrupt Enable Register or UART_DL2 -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - begin - ier <= 4'b0000; // no interrupts after reset - dl[`UART_DL2] <= 8'b0; - end - else - if (wb_we_i && wb_addr_i==`UART_REG_IE) - if (dlab) - begin - dl[`UART_DL2] <= wb_dat_i; - end - else - ier <= wb_dat_i[3:0]; // ier uses only 4 lsb - - -// FIFO Control Register and rx_reset, tx_reset signals -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) begin - fcr <= 2'b11; - rx_reset <= 0; - tx_reset <= 0; - end else - if (wb_we_i && wb_addr_i==`UART_REG_FC) begin - fcr <= wb_dat_i[7:6]; - rx_reset <= wb_dat_i[1]; - tx_reset <= wb_dat_i[2]; - end else begin - rx_reset <= 0; - tx_reset <= 0; - end - -// Modem Control Register -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - mcr <= 5'b0; - else - if (wb_we_i && wb_addr_i==`UART_REG_MC) - mcr <= wb_dat_i[4:0]; - -// Scratch register -// Line Control Register -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - scratch <= 0; // 8n1 setting - else - if (wb_we_i && wb_addr_i==`UART_REG_SR) - scratch <= wb_dat_i; - -// TX_FIFO or UART_DL1 -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) - begin - dl[`UART_DL1] <= 8'b0; - tf_push <= 1'b0; - start_dlc <= 1'b0; - end - else - if (wb_we_i && wb_addr_i==`UART_REG_TR) - if (dlab) - begin - dl[`UART_DL1] <= wb_dat_i; - start_dlc <= 1'b1; // enable DL counter - tf_push <= 1'b0; - end - else - begin - tf_push <= 1'b1; - start_dlc <= 1'b0; - end // else: !if(dlab) - else - begin - start_dlc <= 1'b0; - tf_push <= 1'b0; - end // else: !if(dlab) - -// Receiver FIFO trigger level selection logic (asynchronous mux) -always @(fcr) - case (fcr[`UART_FC_TL]) - 2'b00 : trigger_level = 1; - 2'b01 : trigger_level = 4; - 2'b10 : trigger_level = 8; - 2'b11 : trigger_level = 14; - endcase // case(fcr[`UART_FC_TL]) - -// -// STATUS REGISTERS // -// - -// Modem Status Register -reg [3:0] delayed_modem_signals; -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - begin - msr <= 0; - delayed_modem_signals[3:0] <= 0; - end - else begin - msr[`UART_MS_DDCD:`UART_MS_DCTS] <= msi_reset ? 4'b0 : - msr[`UART_MS_DDCD:`UART_MS_DCTS] | ({dcd, ri, dsr, cts} ^ delayed_modem_signals[3:0]); - msr[`UART_MS_CDCD:`UART_MS_CCTS] <= {dcd_c, ri_c, dsr_c, cts_c}; - delayed_modem_signals[3:0] <= {dcd, ri, dsr, cts}; - end -end - - -// Line Status Register - -// activation conditions -assign lsr0 = (rf_count==0 && rf_push_pulse); // data in receiver fifo available set condition -assign lsr1 = rf_overrun; // Receiver overrun error -assign lsr2 = rf_data_out[1]; // parity error bit -assign lsr3 = rf_data_out[0]; // framing error bit -assign lsr4 = rf_data_out[2]; // break error in the character -assign lsr5 = (tf_count==5'b0 && thre_set_en); // transmitter fifo is empty -assign lsr6 = (tf_count==5'b0 && thre_set_en && (tstate == /*`S_IDLE */ 0)); // transmitter empty -assign lsr7 = rf_error_bit | rf_overrun; - -// lsr bit0 (receiver data available) -reg lsr0_d; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr0_d <= 0; - else lsr0_d <= lsr0; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr0r <= 0; - else lsr0r <= (rf_count==1 && rf_pop && !rf_push_pulse || rx_reset) ? 0 : // deassert condition - lsr0r || (lsr0 && ~lsr0_d); // set on rise of lsr0 and keep asserted until deasserted - -// lsr bit 1 (receiver overrun) -reg lsr1_d; // delayed - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr1_d <= 0; - else lsr1_d <= lsr1; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr1r <= 0; - else lsr1r <= lsr_mask ? 0 : lsr1r || (lsr1 && ~lsr1_d); // set on rise - -// lsr bit 2 (parity error) -reg lsr2_d; // delayed - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr2_d <= 0; - else lsr2_d <= lsr2; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr2r <= 0; - else lsr2r <= lsr_mask ? 0 : lsr2r || (lsr2 && ~lsr2_d); // set on rise - -// lsr bit 3 (framing error) -reg lsr3_d; // delayed - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr3_d <= 0; - else lsr3_d <= lsr3; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr3r <= 0; - else lsr3r <= lsr_mask ? 0 : lsr3r || (lsr3 && ~lsr3_d); // set on rise - -// lsr bit 4 (break indicator) -reg lsr4_d; // delayed - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr4_d <= 0; - else lsr4_d <= lsr4; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr4r <= 0; - else lsr4r <= lsr_mask ? 0 : lsr4r || (lsr4 && ~lsr4_d); - -// lsr bit 5 (transmitter fifo is empty) -reg lsr5_d; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr5_d <= 1; - else lsr5_d <= lsr5; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr5r <= 1; - else lsr5r <= (fifo_write) ? 0 : lsr5r || (lsr5 && ~lsr5_d); - -// lsr bit 6 (transmitter empty indicator) -reg lsr6_d; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr6_d <= 1; - else lsr6_d <= lsr6; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr6r <= 1; - else lsr6r <= (fifo_write) ? 0 : lsr6r || (lsr6 && ~lsr6_d); - -// lsr bit 7 (error in fifo) -reg lsr7_d; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr7_d <= 0; - else lsr7_d <= lsr7; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) lsr7r <= 0; - else lsr7r <= lsr_mask ? 0 : lsr7r || (lsr7 && ~lsr7_d); - -// Frequency divider -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - dlc <= 0; - else - if (start_dlc | ~ (|dlc)) - dlc <= dl - 1; // preset counter - else - dlc <= dlc - 1; // decrement counter -end - -// Enable signal generation logic -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - enable <= 1'b0; - else - if (|dl & ~(|dlc)) // dl>0 & dlc==0 - enable <= 1'b1; - else - enable <= 1'b0; -end - -// Delaying THRE status for one character cycle after a character is written to an empty fifo. -always @(lcr) - case (lcr[3:0]) - 4'b0000 : block_value = 95; // 6 bits - 4'b0100 : block_value = 103; // 6.5 bits - 4'b0001, 4'b1000 : block_value = 111; // 7 bits - 4'b1100 : block_value = 119; // 7.5 bits - 4'b0010, 4'b0101, 4'b1001 : block_value = 127; // 8 bits - 4'b0011, 4'b0110, 4'b1010, 4'b1101 : block_value = 143; // 9 bits - 4'b0111, 4'b1011, 4'b1110 : block_value = 159; // 10 bits - 4'b1111 : block_value = 175; // 11 bits - endcase // case(lcr[3:0]) - -// Counting time of one character minus stop bit -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - block_cnt <= 8'd0; - else - if(lsr5r & fifo_write) // THRE bit set & write to fifo occured - block_cnt <= block_value; - else - if (enable & block_cnt != 8'b0) // only work on enable times - block_cnt <= block_cnt - 1; // decrement break counter -end // always of break condition detection - -// Generating THRE status enable signal -assign thre_set_en = ~(|block_cnt); - - -// -// INTERRUPT LOGIC -// - -assign rls_int = ier[`UART_IE_RLS] && (lsr[`UART_LS_OE] || lsr[`UART_LS_PE] || lsr[`UART_LS_FE] || lsr[`UART_LS_BI]); -assign rda_int = ier[`UART_IE_RDA] && (rf_count >= {1'b0,trigger_level}); -assign thre_int = ier[`UART_IE_THRE] && lsr[`UART_LS_TFE]; -assign ms_int = ier[`UART_IE_MS] && (| msr[3:0]); -assign ti_int = ier[`UART_IE_RDA] && (counter_t == 10'b0) && (|rf_count); - -reg rls_int_d; -reg thre_int_d; -reg ms_int_d; -reg ti_int_d; -reg rda_int_d; - -// delay lines -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) rls_int_d <= 0; - else rls_int_d <= rls_int; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) rda_int_d <= 0; - else rda_int_d <= rda_int; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) thre_int_d <= 0; - else thre_int_d <= thre_int; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) ms_int_d <= 0; - else ms_int_d <= ms_int; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) ti_int_d <= 0; - else ti_int_d <= ti_int; - -// rise detection signals - -wire rls_int_rise; -wire thre_int_rise; -wire ms_int_rise; -wire ti_int_rise; -wire rda_int_rise; - -assign rda_int_rise = rda_int & ~rda_int_d; -assign rls_int_rise = rls_int & ~rls_int_d; -assign thre_int_rise = thre_int & ~thre_int_d; -assign ms_int_rise = ms_int & ~ms_int_d; -assign ti_int_rise = ti_int & ~ti_int_d; - -// interrupt pending flags -reg rls_int_pnd; -reg rda_int_pnd; -reg thre_int_pnd; -reg ms_int_pnd; -reg ti_int_pnd; - -// interrupt pending flags assignments -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) rls_int_pnd <= 0; - else - rls_int_pnd <= lsr_mask ? 0 : // reset condition - rls_int_rise ? 1 : // latch condition - rls_int_pnd && ier[`UART_IE_RLS]; // default operation: remove if masked - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) rda_int_pnd <= 0; - else - rda_int_pnd <= ((rf_count == {1'b0,trigger_level}) && fifo_read) ? 0 : // reset condition - rda_int_rise ? 1 : // latch condition - rda_int_pnd && ier[`UART_IE_RDA]; // default operation: remove if masked - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) thre_int_pnd <= 0; - else - thre_int_pnd <= fifo_write || (iir_read & ~iir[`UART_II_IP] & iir[`UART_II_II] == `UART_II_THRE)? 0 : - thre_int_rise ? 1 : - thre_int_pnd && ier[`UART_IE_THRE]; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) ms_int_pnd <= 0; - else - ms_int_pnd <= msr_read ? 0 : - ms_int_rise ? 1 : - ms_int_pnd && ier[`UART_IE_MS]; - -always @(posedge clk or posedge wb_rst_i) - if (wb_rst_i) ti_int_pnd <= 0; - else - ti_int_pnd <= fifo_read ? 0 : - ti_int_rise ? 1 : - ti_int_pnd && ier[`UART_IE_RDA]; -// end of pending flags - -// INT_O logic -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - int_o <= 1'b0; - else - int_o <= - rls_int_pnd ? ~lsr_mask : - rda_int_pnd ? 1 : - ti_int_pnd ? ~fifo_read : - thre_int_pnd ? !(fifo_write & iir_read) : - ms_int_pnd ? ~msr_read : - 0; // if no interrupt are pending -end - - -// Interrupt Identification register -always @(posedge clk or posedge wb_rst_i) -begin - if (wb_rst_i) - iir <= 1; - else - if (rls_int_pnd) // interrupt is pending - begin - iir[`UART_II_II] <= `UART_II_RLS; // set identification register to correct value - iir[`UART_II_IP] <= 1'b0; // and clear the IIR bit 0 (interrupt pending) - end else // the sequence of conditions determines priority of interrupt identification - if (rda_int) - begin - iir[`UART_II_II] <= `UART_II_RDA; - iir[`UART_II_IP] <= 1'b0; - end - else if (ti_int_pnd) - begin - iir[`UART_II_II] <= `UART_II_TI; - iir[`UART_II_IP] <= 1'b0; - end - else if (thre_int_pnd) - begin - iir[`UART_II_II] <= `UART_II_THRE; - iir[`UART_II_IP] <= 1'b0; - end - else if (ms_int_pnd) - begin - iir[`UART_II_II] <= `UART_II_MS; - iir[`UART_II_IP] <= 1'b0; - end else // no interrupt is pending - begin - iir[`UART_II_II] <= 0; - iir[`UART_II_IP] <= 1'b1; - end -end - -endmodule Index: trunk/src/testbench/External_IP/uart16550/rtl/uart_top.v =================================================================== --- trunk/src/testbench/External_IP/uart16550/rtl/uart_top.v (revision 57) +++ trunk/src/testbench/External_IP/uart16550/rtl/uart_top.v (nonexistent) @@ -1,338 +0,0 @@ -////////////////////////////////////////////////////////////////////// -//// //// -//// uart_top.v //// -//// //// -//// //// -//// This file is part of the "UART 16550 compatible" project //// -//// http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Documentation related to this project: //// -//// - http://www.opencores.org/cores/uart16550/ //// -//// //// -//// Projects compatibility: //// -//// - WISHBONE //// -//// RS232 Protocol //// -//// 16550D uart (mostly supported) //// -//// //// -//// Overview (main Features): //// -//// UART core top level. //// -//// //// -//// Known problems (limits): //// -//// Note that transmitter and receiver instances are inside //// -//// the uart_regs.v file. //// -//// //// -//// To Do: //// -//// Nothing so far. //// -//// //// -//// Author(s): //// -//// - gorban@opencores.org //// -//// - Jacob Gorban //// -//// - Igor Mohor (igorm@opencores.org) //// -//// //// -//// Created: 2001/05/12 //// -//// Last Updated: 2001/05/17 //// -//// (See log for the revision history) //// -//// //// -//// Modified for use in the ZAP project by Revanth Kamaraj //// -//// //// -////////////////////////////////////////////////////////////////////// -//// //// -//// Copyright (C) 2000, 2001 Authors //// -//// //// -//// This source file may be used and distributed without //// -//// restriction provided that this copyright statement is not //// -//// removed from the file and that any derivative work contains //// -//// the original copyright notice and the associated disclaimer. //// -//// //// -//// This source file is free software; you can redistribute it //// -//// and/or modify it under the terms of the GNU Lesser General //// -//// Public License as published by the Free Software Foundation; //// -//// either version 2.1 of the License, or (at your option) any //// -//// later version. //// -//// //// -//// This source 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 Lesser General Public License for more //// -//// details. //// -//// //// -//// You should have received a copy of the GNU Lesser General //// -//// Public License along with this source; if not, download it //// -//// from http://www.opencores.org/lgpl.shtml //// -//// //// -////////////////////////////////////////////////////////////////////// -// -// CVS Revision History -// -// $Log: not supported by cvs2svn $ -// Revision 1.18 2002/07/22 23:02:23 gorban -// Bug Fixes: -// * Possible loss of sync and bad reception of stop bit on slow baud rates fixed. -// Problem reported by Kenny.Tung. -// * Bad (or lack of ) loopback handling fixed. Reported by Cherry Withers. -// -// Improvements: -// * Made FIFO's as general inferrable memory where possible. -// So on FPGA they should be inferred as RAM (Distributed RAM on Xilinx). -// This saves about 1/3 of the Slice count and reduces P&R and synthesis times. -// -// * Added optional baudrate output (baud_o). -// This is identical to BAUDOUT* signal on 16550 chip. -// It outputs 16xbit_clock_rate - the divided clock. -// It's disabled by default. Define UART_HAS_BAUDRATE_OUTPUT to use. -// -// Revision 1.17 2001/12/19 08:40:03 mohor -// Warnings fixed (unused signals removed). -// -// Revision 1.16 2001/12/06 14:51:04 gorban -// Bug in LSR[0] is fixed. -// All WISHBONE signals are now sampled, so another wait-state is introduced on all transfers. -// -// Revision 1.15 2001/12/03 21:44:29 gorban -// Updated specification documentation. -// Added full 32-bit data bus interface, now as default. -// Address is 5-bit wide in 32-bit data bus mode. -// Added wb_sel_i input to the core. It's used in the 32-bit mode. -// Added debug interface with two 32-bit read-only registers in 32-bit mode. -// Bits 5 and 6 of LSR are now only cleared on TX FIFO write. -// My small test bench is modified to work with 32-bit mode. -// -// Revision 1.14 2001/11/07 17:51:52 gorban -// Heavily rewritten interrupt and LSR subsystems. -// Many bugs hopefully squashed. -// -// Revision 1.13 2001/10/20 09:58:40 gorban -// Small synopsis fixes -// -// Revision 1.12 2001/08/25 15:46:19 gorban -// Modified port names again -// -// Revision 1.11 2001/08/24 21:01:12 mohor -// Things connected to parity changed. -// Clock devider changed. -// -// Revision 1.10 2001/08/23 16:05:05 mohor -// Stop bit bug fixed. -// Parity bug fixed. -// WISHBONE read cycle bug fixed, -// OE indicator (Overrun Error) bug fixed. -// PE indicator (Parity Error) bug fixed. -// Register read bug fixed. -// -// Revision 1.4 2001/05/31 20:08:01 gorban -// FIFO changes and other corrections. -// -// Revision 1.3 2001/05/21 19:12:02 gorban -// Corrected some Linter messages. -// -// Revision 1.2 2001/05/17 18:34:18 gorban -// First 'stable' release. Should be sythesizable now. Also added new header. -// -// Revision 1.0 2001-05-17 21:27:12+02 jacob -// Initial revision -// -// - -`include "uart_defines.v" - -module uart_top ( - wb_clk_i, - - // Wishbone signals - wb_rst_i, wb_adr_i, wb_dat_i, wb_dat_o, wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_sel_i, - int_o, // interrupt request - - // UART signals - // serial input/output - stx_pad_o, srx_pad_i, - - // modem signals - rts_pad_o, cts_pad_i, dtr_pad_o, dsr_pad_i, ri_pad_i, dcd_pad_i -`ifdef UART_HAS_BAUDRATE_OUTPUT - , baud_o -`endif - ); - -parameter uart_data_width = `UART_DATA_WIDTH; -parameter uart_addr_width = `UART_ADDR_WIDTH; - -input wb_clk_i; - -// WISHBONE interface -input wb_rst_i; -input [uart_addr_width-1:0] wb_adr_i; -input [uart_data_width-1:0] wb_dat_i; -output [uart_data_width-1:0] wb_dat_o; -input wb_we_i; -input wb_stb_i; -input wb_cyc_i; -input [3:0] wb_sel_i; -output wb_ack_o; -output int_o; - -// UART signals -input srx_pad_i; -output stx_pad_o; -output rts_pad_o; -input cts_pad_i; -output dtr_pad_o; -input dsr_pad_i; -input ri_pad_i; -input dcd_pad_i; - -// optional baudrate output -`ifdef UART_HAS_BAUDRATE_OUTPUT -output baud_o; -`endif - - -wire stx_pad_o; -wire rts_pad_o; -wire dtr_pad_o; - -wire [uart_addr_width-1:0] wb_adr_i; -wire [uart_data_width-1:0] wb_dat_i; -wire [uart_data_width-1:0] wb_dat_o; - -wire [7:0] wb_dat8_i; // 8-bit internal data input -wire [7:0] wb_dat8_o; // 8-bit internal data output -wire [31:0] wb_dat32_o; // debug interface 32-bit output -wire [3:0] wb_sel_i; // WISHBONE select signal -wire [uart_addr_width-1:0] wb_adr_int; -wire we_o; // Write enable for registers -wire re_o; // Read enable for registers -// -// MODULE INSTANCES -// - -`ifdef DATA_BUS_WIDTH_8 -`else -// debug interface wires -wire [3:0] ier; -wire [3:0] iir; -wire [1:0] fcr; -wire [4:0] mcr; -wire [7:0] lcr; -wire [7:0] msr; -wire [7:0] lsr; -wire [`UART_FIFO_COUNTER_W-1:0] rf_count; -wire [`UART_FIFO_COUNTER_W-1:0] tf_count; -wire [2:0] tstate; -wire [3:0] rstate; -`endif - -`ifdef DATA_BUS_WIDTH_8 -//// WISHBONE interface module -uart_wb wb_interface( - .clk( wb_clk_i ), - .wb_rst_i( wb_rst_i ), - .wb_dat_i(wb_dat_i), - .wb_dat_o(wb_dat_o), - .wb_dat8_i(wb_dat8_i), - .wb_dat8_o(wb_dat8_o), - .wb_dat32_o(32'b0), - .wb_sel_i(4'b0), - .wb_we_i( wb_we_i ), - .wb_stb_i( wb_stb_i ), - .wb_cyc_i( wb_cyc_i ), - .wb_ack_o( wb_ack_o ), - .wb_adr_i(wb_adr_i), - .wb_adr_int(wb_adr_int), - .we_o( we_o ), - .re_o(re_o) - ); -`else -uart_wb wb_interface( - .clk( wb_clk_i ), - .wb_rst_i( wb_rst_i ), - .wb_dat_i(wb_dat_i), - .wb_dat_o(wb_dat_o), - .wb_dat8_i(wb_dat8_i), - .wb_dat8_o(wb_dat8_o), - .wb_sel_i(wb_sel_i), - .wb_dat32_o(wb_dat32_o), - .wb_we_i( wb_we_i ), - .wb_stb_i( wb_stb_i ), - .wb_cyc_i( wb_cyc_i ), - .wb_ack_o( wb_ack_o ), - .wb_adr_i(wb_adr_i), - .wb_adr_int(wb_adr_int), - .we_o( we_o ), - .re_o(re_o) - ); -`endif - -// Registers -uart_regs regs( - .clk( wb_clk_i ), - .wb_rst_i( wb_rst_i ), - .wb_addr_i( wb_adr_int ), - .wb_dat_i( wb_dat8_i ), - .wb_dat_o( wb_dat8_o ), - .wb_we_i( we_o ), - .wb_re_i(re_o), - .modem_inputs( {cts_pad_i, dsr_pad_i, - ri_pad_i, dcd_pad_i} ), - .stx_pad_o( stx_pad_o ), - .srx_pad_i( srx_pad_i ), -`ifdef DATA_BUS_WIDTH_8 -`else -// debug interface signals enabled -.ier(ier), -.iir(iir), -.fcr(fcr), -.mcr(mcr), -.lcr(lcr), -.msr(msr), -.lsr(lsr), -.rf_count(rf_count), -.tf_count(tf_count), -.tstate(tstate), -.rstate(rstate), -`endif - .rts_pad_o( rts_pad_o ), - .dtr_pad_o( dtr_pad_o ), - .int_o( int_o ) -`ifdef UART_HAS_BAUDRATE_OUTPUT - , .baud_o(baud_o) -`endif - -); - -`ifdef DATA_BUS_WIDTH_8 -`else -uart_debug_if dbg(/*AUTOINST*/ - // Outputs - .wb_dat32_o (wb_dat32_o[31:0]), - // Inputs - .wb_adr_i (wb_adr_int[`UART_ADDR_WIDTH-1:0]), - .ier (ier[3:0]), - .iir (iir[3:0]), - .fcr (fcr[1:0]), - .mcr (mcr[4:0]), - .lcr (lcr[7:0]), - .msr (msr[7:0]), - .lsr (lsr[7:0]), - .rf_count (rf_count[`UART_FIFO_COUNTER_W-1:0]), - .tf_count (tf_count[`UART_FIFO_COUNTER_W-1:0]), - .tstate (tstate[2:0]), - .rstate (rstate[3:0])); -`endif - -initial -begin - `ifdef DATA_BUS_WIDTH_8 - $display("(%m) UART INFO: Data bus width is 8. No Debug interface.\n"); - `else - $display("(%m) UART INFO: Data bus width is 32. Debug Interface present.\n"); - `endif - `ifdef UART_HAS_BAUDRATE_OUTPUT - $display("(%m) UART INFO: Has baudrate output\n"); - `else - $display("(%m) UART INFO: Doesn't have baudrate output\n"); - `endif -end - -endmodule - - Index: trunk/src/rtl/cpu/zap_wb_adapter.v =================================================================== --- trunk/src/rtl/cpu/zap_wb_adapter.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_shifter_main.v =================================================================== --- trunk/src/rtl/cpu/zap_shifter_main.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_writeback.v =================================================================== --- trunk/src/rtl/cpu/zap_writeback.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_cp15_cb.v =================================================================== --- trunk/src/rtl/cpu/zap_cp15_cb.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_tlb_check.v =================================================================== --- trunk/src/rtl/cpu/zap_tlb_check.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_functions.vh =================================================================== --- trunk/src/rtl/cpu/zap_functions.vh (revision 57) +++ 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: trunk/src/rtl/cpu/zap_decode.v =================================================================== --- trunk/src/rtl/cpu/zap_decode.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_register_file.v =================================================================== --- trunk/src/rtl/cpu/zap_register_file.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_alu_main.v =================================================================== --- trunk/src/rtl/cpu/zap_alu_main.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_tlb_fsm.v =================================================================== --- trunk/src/rtl/cpu/zap_tlb_fsm.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_core.v =================================================================== --- trunk/src/rtl/cpu/zap_core.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_ram_simple.v =================================================================== --- trunk/src/rtl/cpu/zap_ram_simple.v (revision 57) +++ 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 : 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: trunk/src/rtl/cpu/zap_predecode_coproc.v =================================================================== --- trunk/src/rtl/cpu/zap_predecode_coproc.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_decompile.v =================================================================== --- trunk/src/rtl/cpu/zap_decompile.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_shift_shifter.v =================================================================== --- trunk/src/rtl/cpu/zap_shift_shifter.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_top.v =================================================================== --- trunk/src/rtl/cpu/zap_top.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_shifter_multiply.v =================================================================== --- trunk/src/rtl/cpu/zap_shifter_multiply.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_thumb_decoder.v =================================================================== --- trunk/src/rtl/cpu/zap_thumb_decoder.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_predecode_compress.v =================================================================== --- trunk/src/rtl/cpu/zap_predecode_compress.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_cache_fsm.v =================================================================== --- trunk/src/rtl/cpu/zap_cache_fsm.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_wb_merger.v =================================================================== --- trunk/src/rtl/cpu/zap_wb_merger.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_memory_main.v =================================================================== --- trunk/src/rtl/cpu/zap_memory_main.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_sync_fifo.v =================================================================== --- trunk/src/rtl/cpu/zap_sync_fifo.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_tlb.v =================================================================== --- trunk/src/rtl/cpu/zap_tlb.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_fifo.v =================================================================== --- trunk/src/rtl/cpu/zap_fifo.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_defines.vh =================================================================== --- trunk/src/rtl/cpu/zap_defines.vh (revision 57) +++ 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: trunk/src/rtl/cpu/zap_decode_main.v =================================================================== --- trunk/src/rtl/cpu/zap_decode_main.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_cache_tag_ram.v =================================================================== --- trunk/src/rtl/cpu/zap_cache_tag_ram.v (revision 57) +++ trunk/src/rtl/cpu/zap_cache_tag_ram.v (nonexistent) @@ -1,458 +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 tag RAM and data RAM unit. The tag RAM holds both the -- -// -- virtual tag and the physical address. The physical address is used to -- -// -- avoid translation during clean operations. The cache data RAM is also -- -// -- present in this unit. This unit has a dedicated memory interface -- -// -- because it can perform global clean and flush by itself without -- -// -- depending on the cache controller. Only for FPGA. -- -// -- -- -// ----------------------------------------------------------------------------- - -`default_nettype none - -`include "zap_defines.vh" - -module zap_cache_tag_ram #( - -parameter CACHE_SIZE = 1024 // Bytes. - -)( - -input wire i_clk, -input wire i_reset, -input wire [31:0] i_address_nxt, -input wire [31:0] i_address, -input wire i_cache_en, -input wire [127:0] i_cache_line, -input wire [15:0] i_cache_line_ben, -output reg [127:0] o_cache_line, -input wire i_cache_tag_wr_en, -input wire [`CACHE_TAG_WDT-1:0] i_cache_tag, -input wire i_cache_tag_dirty, - -output reg [`CACHE_TAG_WDT-1:0] o_cache_tag, -output reg o_cache_tag_valid, -output reg o_cache_tag_dirty, -input wire i_cache_clean_req, -output reg o_cache_clean_done, -input wire i_cache_inv_req, -output reg o_cache_inv_done, - -/* - * Cache clean operations occur through these ports. - * 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 [31:0] i_wb_dat, -input wire i_wb_ack - -); - -// ---------------------------------------------------------------------------- - -`include "zap_localparams.vh" - -localparam NUMBER_OF_DIRTY_BLOCKS = ((CACHE_SIZE/16)/16); // Keep cache size > 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: trunk/src/rtl/cpu/zap_predecode_mem_fsm.v =================================================================== --- trunk/src/rtl/cpu/zap_predecode_mem_fsm.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_predecode_main.v =================================================================== --- trunk/src/rtl/cpu/zap_predecode_main.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_cache.v =================================================================== --- trunk/src/rtl/cpu/zap_cache.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_mem_inv_block.v =================================================================== --- trunk/src/rtl/cpu/zap_mem_inv_block.v (revision 57) +++ 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: trunk/src/rtl/cpu/zap_localparams.vh =================================================================== --- trunk/src/rtl/cpu/zap_localparams.vh (revision 57) +++ 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: trunk/src/ts/factorial/makefile =================================================================== --- trunk/src/ts/factorial/makefile (revision 57) +++ trunk/src/ts/factorial/makefile (nonexistent) @@ -1,2 +0,0 @@ -# Call original makefile -include ../../scripts/makefile Index: trunk/src/ts/factorial/Description.txt =================================================================== --- trunk/src/ts/factorial/Description.txt (revision 57) +++ trunk/src/ts/factorial/Description.txt (nonexistent) @@ -1,7 +0,0 @@ -This test mainly runs a program to find factorial of 5 and write -the value 3.14 to a memory location. This setup uses the MMU but is set up for -identity mapping using sections. IRQs are generated using the timer in the -testbench. At the end an SWI is called which performs a bunch of multiplications -and serial load/store. FIQs are enabled in testbench to be periodically generated -every 256 clock cycles. - Index: trunk/src/ts/factorial/factorial.ld =================================================================== --- trunk/src/ts/factorial/factorial.ld (revision 57) +++ trunk/src/ts/factorial/factorial.ld (nonexistent) @@ -1,16 +0,0 @@ - -/* Linker Script */ - -ENTRY(_Reset) /* _Reset is the entry point. This is the entry point in the bootstrap assembler */ - -/* Define how sections of the program are organized. */ -SECTIONS -{ - . = 0x00000; /* Location Counter. */ - .text : { *(.text) } /* Text section is expected to be starting at 0x0.*/ - .data : { *(.data) } /* Immediately followed by data section */ - .bss : { *(.bss) *(COMMON) } /* Immediately followed by BSS section. Common sections are also included in BSS. */ - . = ALIGN(8); /* Align the location counter. */ - . = . + 0x1000; /* 4kB of descending stack memory */ - stack_top = .; /* Make stack_top same as location counter. */ -} Index: trunk/src/ts/factorial/Config.cfg =================================================================== --- trunk/src/ts/factorial/Config.cfg (revision 57) +++ trunk/src/ts/factorial/Config.cfg (nonexistent) @@ -1,49 +0,0 @@ -# TC config. - -%Config = ( - # CPU configuration. - DATA_CACHE_SIZE => 4096, # Data cache size in bytes - CODE_CACHE_SIZE => 4096, # Instruction cache size in bytes - CODE_SECTION_TLB_ENTRIES => 512, # Instruction section TLB entries. - CODE_SPAGE_TLB_ENTRIES => 512, # Instruction small page TLB entries. - CODE_LPAGE_TLB_ENTRIES => 512, # Instruction large page TLB entries. - DATA_SECTION_TLB_ENTRIES => 512, # Data section TLB entries. - DATA_SPAGE_TLB_ENTRIES => 512, # Data small page TLB entries. - DATA_LPAGE_TLB_ENTRIES => 512, # Data large page TLB entries. - BP_DEPTH => 1024, # Branch predictor depth. - INSTR_FIFO_DEPTH => 4, # Instruction buffer depth. - STORE_BUFFER_DEPTH => 16, # Store buffer depth. - SYNTHESIS => 0, # 0 allows debug messages. - - # Testbench configuration. - WAVES => 1, - EXT_RAM_SIZE => 32768, # External RAM size. - SEED => -1, # Seed. Use -1 to use random seed. - DUMP_START => 2000, # Starting memory address from which to dump. - DUMP_SIZE => 200, # Length of dump in bytes. - MAX_CLOCK_CYCLES => 6500, # Clock cycles to run the simulation for. - DEFINE_TLB_DEBUG => 0, # Make this 1 to define TLB_DEBUG. Useful for debugging the TLB. - REG_CHECK => {}, # Registers to examine. - FINAL_CHECK => { - # Values of memory for test to succeed. - # LOCATION => VALUE - "32'd2000" => "32'h00007805", - "32'd2004" => "32'h4048f5c3", - "32'd2008" => "32'h00000001", - "32'd2012" => "32'h00000000", - "32'd2016" => "32'h00000001", - "32'd2020" => "32'hfffffffe", - "32'd2024" => "32'h00000001", - "32'd2028" => "32'h00000001", - "32'd2032" => "32'hfffffffe", - "32'd2036" => "32'h00000001", - "32'd2040" => "32'h00000000", - "32'd2044" => "32'h00000001" - } -); - -########################## -# # -# END OF FILE # -# # -########################## Index: trunk/src/ts/factorial/factorial.c =================================================================== --- trunk/src/ts/factorial/factorial.c (revision 57) +++ trunk/src/ts/factorial/factorial.c (nonexistent) @@ -1,44 +0,0 @@ -/* Computes factorial and stores 3.14 in 2004 memory location. */ - -void main (void) -{ - char *x = (char *)2000; - float *y = (float*) 2004; - x[0] = 5; - x[1] = fact(x[0]); - *y = 3.14; -} - -int fact (int x) -{ - if ( x == 0 ) - return 1; - else - return x * fact(x-1); -} - -////////////////// VECTORS ///////////////////////// - -void __undef(void) { - return; -} - -void __swi (void) { - return; -} - -void __pabt (void) { - return; -} - -void __dabt (void) { - return; -} - -void __irq (void) { - return; -} - -void __fiq (void) { - return; -} Index: trunk/src/ts/factorial/factorial.s =================================================================== --- trunk/src/ts/factorial/factorial.s (revision 57) +++ trunk/src/ts/factorial/factorial.s (nonexistent) @@ -1,227 +0,0 @@ -// -// Startup file for factorial. -// - -.global _Reset - -// Set up an interrupt vector table. -_Reset : b there -_Undef : b UNDEF -_Swi : b SWI -_Pabt : b __pabt -_Dabt : b __dabt -reserved : b _Reset -irq : b IRQ -fiq : b FIQ - -UNDEF: - -// Undefined vector. -// LR Points to next instruction. -stmfa sp!, {r0-r12, r14} - -// Corrupt registers. -mov r0, #1 -mov r1, #2 -mov r2, #3 -mov r3, #4 -mov r4, #5 -mov r5, #6 -mov r6, #7 -mov r7, #8 -mov r8, #9 -mov r9, #10 -mov r10, #12 -mov r11, #13 -mov r12, #14 -mov r14, #15 - -// Restore them. -ldmfa sp!, {r0-r12, pc}^ - -// IRQ. -IRQ: -sub r14, r14, #4 -stmfd sp!, {r0-r12, r14} - -mov r0, #1 -mov r1, #2 -mov r2, #3 -mov r3, #4 -mov r4, #5 -mov r5, #6 -mov r6, #7 -mov r7, #8 -mov r8, #9 -mov r9, #10 -mov r10, #12 -mov r11, #13 -mov r12, #14 -mov r14, #15 - -.set TIMER_BASE_ADDRESS, 0xFFFFFFC0 - -# Restart timer -ldr r0,=TIMER_BASE_ADDRESS // Timer base address. -add r0, r0, #12 -mov r1, #1 -str r1, [r0] // Restart the timer. - -.set VIC_BASE_ADDRESS, 0xFFFFFFA0 -.set CLEAR_ALL_PENDING, 0xFFFFFFFF - -# Clear interrupt in VIC. -ldr r0, =VIC_BASE_ADDRESS // VIC base address -add r0, r0, #8 -ldr r1, =CLEAR_ALL_PENDING -str r1, [r0] // Clear all interrupt pending status - -# Restore -ldmfd sp!, {r0-r12, pc}^ - -FIQ: -# Return from FIQ after writing to FIQ registers - shouldn't affect other things. -mov r8, #9 -mov r9, #10 -mov r10, #12 -mov r11, #13 -mov r12, #14 -subs pc, r14, #4 - -SWI: -.set SWI_SP_VALUE, 2500 -.set SWI_R11_VALUE, 2004 -ldr sp,=SWI_SP_VALUE -ldr r11,=SWI_R11_VALUE -mov r0, #12 -mov r1, #0 -mov r2, r0, lsr #32 -mov r3, r0, lsr r1 -mov r4, #-1 -mov r5, #-1 -muls r6, r5, r4 -umull r8, r7, r5, r4 -smull r10, r9, r5, r4 -mov r2, r10 -str r10, [r11, #4]! -str r9, [r11, #4]! -add r11, r11, #4 -str r8, [r11], #4 -str r7, [r11], #4 -str r6, [r11] -stmib r11, {r6-r10} -stmfd sp!, {r0-r12, r14} -mrs r1, spsr -orr r1, r1, #0x80 -msr spsr_c, r1 -mov r4, #0 -mcr p15, 0, r4, c7, c15, 0 -mov r4, #-1 -ldmfd sp!, {r0-r12, pc}^ - -there: -// Switch to IRQ mode. -mrs r2, cpsr -bic r2, r2, #31 -orr r2, r2, #18 -msr cpsr_c, r2 - -.set IRQ_SP_VALUE, 3000 -ldr sp,=IRQ_SP_VALUE - -// Switch to UND mode. -mrs r3, cpsr -bic r3, r3, #31 -orr r3, r3, #27 -msr cpsr_c, r3 -mov r4, #1 - -.set UND_SP_VALUE, 3500 -ldr sp, =UND_SP_VALUE - -// Enable interrupts (FIQ and IRQ). -mrs r1, cpsr -bic r1, r1, #0xC0 -msr cpsr_c, r1 - -// Enable cache (Uses a single bit to enable both caches). -.set ENABLE_CACHE_CP_WORD, 4100 -ldr r1, =ENABLE_CACHE_CP_WORD -mcr p15, 0, r1, c1, c1, 0 - -// Write out identitiy section mapping. Write 16KB to register 2. -mov r1, #1 -mov r1, r1, lsl #14 -mcr p15, 0, r1, c2, c0, 1 - -// Set domain access control to all 1s. -mvn r1, #0 -mcr p15, 0, r1, c3, c0, 0 - -// Set up a section desctiptor for identity mapping that is Cachaeable. -mov r1, #1 -mov r1, r1, lsl #14 // 16KB -mov r2, #14 // Cacheable identity descriptor. -str r2, [r1] // Write identity section desctiptor to 16KB location. -ldr r6, [r1] // R6 holds the descriptor. -mov r7, r1 // R7 holds the address. - -// Set up a section descriptor for upper 1MB of virtual address space. -// This is identity mapping. Uncacheable. -mov r1, #1 -mov r1, r1, lsl #14 // 16KB. This is descriptor 0. - -// Go to descriptor 4095. This is the address BASE + (#DESC * 4). -.set DESCRIPTOR_IO_SECTION_OFFSET, 16380 // 4095 x 4 -ldr r2,=DESCRIPTOR_IO_SECTION_OFFSET -add r1, r1, r2 - -// Prepare a descriptor. Descriptor = 0xFFF00002 (Uncacheable section descriptor). -.set DESCRIPTOR_IO_SECTION, 0xFFF00002 -ldr r2 ,=DESCRIPTOR_IO_SECTION -str r2, [r1] -ldr r6, [r1] -mov r7, r1 - -// ENABLE MMU -.set ENABLE_MMU_CP_WORD, 4101 -ldr r1, =ENABLE_MMU_CP_WORD -mcr p15, 0, r1, c1, c1, 0 - -// Switch mode. -mrs r2, cpsr -bic r2, r2, #31 -orr r2, r2, #16 -msr cpsr_c, r2 - -.set USR_SP_VALUE, 4000 -ldr sp,=USR_SP_VALUE - -// Run main loop. - -// Program VIC to allow timer interrupts. -ldr r0, =VIC_BASE_ADDRESS // VIC base address. -add r0, r0, #4 // Move to INT_MASK -mov r1, #0 // Prepare mask value -str r1, [r0] // Unmask all interrupt sources. - -// Program timer peripheral to tick every 32 clock cycles. -ldr r0 ,=TIMER_BASE_ADDRESS // Timer base address. -mov r1 , #1 -str r1, [r0] // Enable timer -add r0, r0, #4 -mov r1, #32 -str r1, [r0] // Program to 255 clocks. -add r0, r0, #8 -mov r1, #0x1 -str r1, [r0] // Start the timer. - -// Call C code -bl main - -// Do SWI 0x0 -swi #0x00 - -// Loop forever -here: b here - Index: trunk/src/ts/uart/Config.cfg =================================================================== --- trunk/src/ts/uart/Config.cfg (revision 57) +++ trunk/src/ts/uart/Config.cfg (nonexistent) @@ -1,30 +0,0 @@ -# TC config. - -%Config = ( - # CPU configuration. - DATA_CACHE_SIZE => 4096, # Data cache size in bytes - CODE_CACHE_SIZE => 4096, # Instruction cache size in bytes - CODE_SECTION_TLB_ENTRIES => 8, # Instruction section TLB entries. - CODE_SPAGE_TLB_ENTRIES => 32, # Instruction small page TLB entries. - CODE_LPAGE_TLB_ENTRIES => 16, # Instruction large page TLB entries. - DATA_SECTION_TLB_ENTRIES => 8, # Data section TLB entries. - DATA_SPAGE_TLB_ENTRIES => 32, # Data small page TLB entries. - DATA_LPAGE_TLB_ENTRIES => 16, # Data large page TLB entries. - BP_DEPTH => 1024, # Branch predictor depth. - INSTR_FIFO_DEPTH => 4, # Instruction buffer depth. - STORE_BUFFER_DEPTH => 16, # Store buffer depth. - SYNTHESIS => 0, # 0 allows debug messages. - - # Testbench configuration. - WAVES => 1, # Generate waveform. - UART0_TX_TERMINAL => 1, # Show TX terminal. - UART0_RX_TERMINAL => 1, # Show RX terminal. - EXT_RAM_SIZE => 32768, # External RAM size. - SEED => -1, # Seed. Use -1 to use random seed. - DUMP_START => 2000, # Starting memory address from which to dump. - DUMP_SIZE => 200, # Length of dump in bytes. - MAX_CLOCK_CYCLES => 0, # Clock cycles to run the simulation for. 0 is forever. - REG_CHECK => {}, # No registers to check. - FINAL_CHECK => {} # No memory locations to check. -); - Index: trunk/src/ts/uart/main.c =================================================================== --- trunk/src/ts/uart/main.c (revision 57) +++ trunk/src/ts/uart/main.c (nonexistent) @@ -1,12 +0,0 @@ -#include "uart.h" - -int main(void) -{ - // Just bringup the UART TX and RX - enable interrupts and exit. - UARTInit(); - UARTWrite("TX testing..."); - UARTEnableRXInterrupt(); - return 0; -} - - Index: trunk/src/ts/uart/irq_handler.c =================================================================== --- trunk/src/ts/uart/irq_handler.c (revision 57) +++ trunk/src/ts/uart/irq_handler.c (nonexistent) @@ -1,14 +0,0 @@ -#include "uart.h" - -void irq_handler () -{ - // Wait for space to be available. - while ( !UARTTransmitEmpty() ); - - // Write character - UARTWriteByte ( UARTGetChar() ); - - // Clear interrupt pending register in VIC. - *VIC_INT_CLEAR = 0xffffffff; -} - Index: trunk/src/ts/uart/uart.ld =================================================================== --- trunk/src/ts/uart/uart.ld (revision 57) +++ trunk/src/ts/uart/uart.ld (nonexistent) @@ -1,16 +0,0 @@ - -/* Linker Script */ - -ENTRY(_Reset) /* _Reset is the entry point. This is the entry point in the bootstrap assembler */ - -/* Define how sections of the program are organized. */ -SECTIONS -{ - . = 0x00000; /* Location Counter. */ - .text : { *(.text) } /* Text section is expected to be starting at 0x0.*/ - .data : { *(.data) } /* Immediately followed by data section */ - .bss : { *(.bss) *(COMMON) } /* Immediately followed by BSS section. Common sections are also included in BSS. */ - . = ALIGN(8); /* Align the location counter. */ - . = . + 0x1000; /* 4kB of descending stack memory */ - stack_top = .; /* Make stack_top same as location counter. */ -} Index: trunk/src/ts/uart/uart.c =================================================================== --- trunk/src/ts/uart/uart.c (revision 57) +++ trunk/src/ts/uart/uart.c (nonexistent) @@ -1,76 +0,0 @@ -#include "uart.h" - -/* Sets up rate as 1 baud = 16 CPU clocks. Also resets TX and RX logic */ -void UARTInit() -{ - // Set up frequency of operation. 1 bit time = 16 CPU clocks. - *UART0_LCR = (*UART0_LCR) | (1 << 7); - *UART0_DLAB1 = 1; - *UART0_DLAB2 = 0; - *UART0_LCR = (*UART0_LCR) & ~(1 << 7); - - // Enable TX and RX. - UARTEnableTX(); - UARTEnableRX(); -} - -/* Write a string to the UART device. This is an open loop function. */ -void UARTWrite(char* s) -{ - int len; - int i; - - len = strlen(s); - - for(i=0;i 4096, # Data cache size in bytes - CODE_CACHE_SIZE => 4096, # Instruction cache size in bytes - CODE_SECTION_TLB_ENTRIES => 8, # Instruction section TLB entries. - CODE_SPAGE_TLB_ENTRIES => 32, # Instruction small page TLB entries. - CODE_LPAGE_TLB_ENTRIES => 16, # Instruction large page TLB entries. - DATA_SECTION_TLB_ENTRIES => 8, # Data section TLB entries. - DATA_SPAGE_TLB_ENTRIES => 32, # Data small page TLB entries. - DATA_LPAGE_TLB_ENTRIES => 16, # Data large page TLB entries. - BP_DEPTH => 1024, # Branch predictor depth. - INSTR_FIFO_DEPTH => 4, # Instruction buffer depth. - STORE_BUFFER_DEPTH => 16, # Store buffer depth. - SYNTHESIS => 0, # 0 allows debug messages. - - # Testbench configuration. - EXT_RAM_SIZE => 32768, # External RAM size. - SEED => -1, # Seed. Use -1 to use random seed. - DUMP_START => 2000, # Starting memory address from which to dump. - DUMP_SIZE => 200, # Length of dump in bytes. - MAX_CLOCK_CYCLES => 1000, # Clock cycles to run the simulation for. - REG_CHECK => { - "r0" => "32'hFFFFFFFF", - "r1" => "32'd10", - "r2" => "32'd10", - "r3" => "32'd10", - "r4" => "32'd10", - "r5" => "32'd10", - "r6" => "32'd10", - "r7" => "32'd10" - }, - FINAL_CHECK => {} -); - Index: trunk/src/ts/thumb_test/main.c =================================================================== --- trunk/src/ts/thumb_test/main.c (revision 57) +++ trunk/src/ts/thumb_test/main.c (nonexistent) @@ -1,4 +0,0 @@ -int main() -{ - return 0; -} Index: trunk/src/ts/arm_test/arm_test.ld =================================================================== --- trunk/src/ts/arm_test/arm_test.ld (revision 57) +++ trunk/src/ts/arm_test/arm_test.ld (nonexistent) @@ -1,16 +0,0 @@ - -/* Linker Script */ - -ENTRY(_Reset) /* _Reset is the entry point. This is the entry point in the bootstrap assembler */ - -/* Define how sections of the program are organized. */ -SECTIONS -{ - . = 0x00000; /* Location Counter. */ - .text : { *(.text) } /* Text section is expected to be starting at 0x0.*/ - .data : { *(.data) } /* Immediately followed by data section */ - .bss : { *(.bss) *(COMMON) } /* Immediately followed by BSS section. Common sections are also included in BSS. */ - . = ALIGN(8); /* Align the location counter. */ - . = . + 0x1000; /* 4kB of descending stack memory */ - stack_top = .; /* Make stack_top same as location counter. */ -} Index: trunk/src/ts/arm_test/makefile =================================================================== --- trunk/src/ts/arm_test/makefile (revision 57) +++ trunk/src/ts/arm_test/makefile (nonexistent) @@ -1,2 +0,0 @@ -# Execute the main Makefile. -include ../../scripts/makefile Index: trunk/src/ts/arm_test/arm_test.c =================================================================== --- trunk/src/ts/arm_test/arm_test.c (revision 57) +++ trunk/src/ts/arm_test/arm_test.c (nonexistent) @@ -1,3 +0,0 @@ -void main() { - -} Index: trunk/src/ts/arm_test/arm_test.s =================================================================== --- trunk/src/ts/arm_test/arm_test.s (revision 57) +++ trunk/src/ts/arm_test/arm_test.s (nonexistent) @@ -1,1302 +0,0 @@ -@ -@ -@ This file is taken from the ARM4U CPU project. -@ -@ This is a creation of the Laboratory of Processor Architecture -@ of Ecole Polytechnique Fédérale de Lausanne ( http://lap.epfl.ch ) -@ -@ asm_test.s --- Test program which uses all the instruction set -@ to be assembled with GCC assembler -@ -@ Written By - Jonathan Masur and Xavier Jimenez (2013) -@ -@ 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, 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. -@ -@ In other words, you are welcome to use, share and improve this program. -@ You are forbidden to forbid anyone else to use, share and improve -@ what you give them. Help stamp out software-hoarding! -@ -@ MODIFICATION -- -@ Modified by Revanth Kamaraj for the ZAP ARM processor. The original code -@ attempts to change modes from USER mode itself, changed it to SYS mode. -@ NOTE: When running this code, do not enable interrupts as service routines -@ are not set up properly in this code. -@ -@ - - .text - .global test_cond, test_fwd, test_bshift, test_logic, test_adder, test_bshift_reg, test_load - .global test_store, test_byte, test_cpsr, test_mul, test_ldmstm, test_r15jumps, test_rti - -_Reset: - bl test_cond -fail1: - teq r0, #0 - mov r1, #1 - bne fail1 - - bl test_fwd -fail2: - teq r0, #0 - mov r1, #2 - bne fail2 - - bl test_bshift -fail3: - teq r0, #0 - mov r1, #3 - bne fail3 - - bl test_logic -fail4: - teq r0, #0 - mov r1, #4 - bne fail4 - - bl test_adder -fail5: - teq r0, #0 - mov r1, #5 - bne fail5 - - bl test_bshift_reg -fail6: - teq r0, #0 - mov r1, #6 - bne fail6 - - bl test_load -fail7: - teq r0, #0 - mov r1, #7 - bne fail7 - - bl test_store -fail8: - teq r0, #0 - mov r1, #8 - bne fail8 - - bl test_byte -fail9: - teq r0, #0 - mov r1, #9 - bne fail9 - - bl test_cpsr -fail10: - teq r0, #0 - mov r1, #10 - bne fail10 - - bl test_mul -fail11: - teq r0, #0 - mov r1, #11 - bne fail11 - - bl test_ldmstm -fail12: - teq r0, #0 - mov r1, #12 - bne fail12 - - bl test_r15jumps -fail13: - teq r0, #0 - mov r12, #13 - bne fail13 - - bl test_rti -passed: - mvn r0, #0 - mvn r1, #0 - mvn r2, #0 - mvn r3, #0 - mvn r4, #0 - mvn r5, #0 - mvn r6, #0 - mvn r7, #0 - mvn r8, #0 - mvn r9, #0 - mvn r10, #0 - mvn r11, #0 - mvn r12, #0 - mvn r13, #0 - mvn r14, #0 - b passed - - @test N and Z flags conditional execution -test_cond: - mov r0, #1 - - @ test 1 - test that the Z flag is set properly, and N flag clear properly - movs r5, #0 - bne fail - bmi fail - add r0, #1 - - @test 2 - test that an instruction without 'S' does not affect the flags - movs r5, #1 - mov r5, #0 - beq fail - bmi fail - add r0, #1 - - @test 3 - test that the N flag is set properly - movs r5, #-2 - mov r5, #0 - beq fail - bpl fail - add r0, #1 - - @test4 - make sure conditional MOV are skipped, and that flags are not updated on a skipped instruction - movs r5, #1 - movpls r5, #0 @valid - movnes r5, #1 @invalid - movmis r5, #2 @invalid - bne fail - cmp r5, #0 - bne fail - add r0, #1 - - @ test 5 - make sure instructions after a branch are skipped completely - b .dummy - movs r5, #-1 - movs r5, #-2 - movs r5, #-3 -.dummy: - bne fail - bmi fail - - @condition test passed - mov r0, #0 -fail: - bx lr - -test_fwd: - mov r0, #1 - - @test forwarding and register file for OPA - mov r1, #1 - add r1, r1, #1 - add r1, r1, #1 - add r1, r1, #1 - add r1, r1, #1 - add r1, r1, #1 - cmp r1, #6 - bne fail - add r0, #1 - - @test forwarding priority for opb - mov r1, #1 - mov r1, #2 - mov r1, #3 - mov r1, #4 - mov r1, #5 - cmp r1, #5 - bne fail - add r0, #1 - - @forwarding test passed - mov r0, #0 - bx lr - -test_bshift: - @test barrel shifter all modes (shift by literal const. only for now) - mov r0, #1 - - @test 1 - test LSL output - movs r5, #0xf0000000 - mov r1, #0x0f - mov r2, r1, lsl #28 - cmp r5, r2 - bne fail - add r0, #1 - - @test 2 - test ROR output - mov r3, r1, ror #4 - cmp r5, r3 - bne fail - add r0, #1 - - @test 3 - test LSR output - mov r4, r5, lsr #28 - cmp r4, r1 - bne fail - add r0, #1 - - @test 4 - test ASR output - mov r1, #0x80000000 - mov r2, r1, asr #3 - cmp r5 ,r2 - bne fail - add r0, #1 - - @test 5 - test RRX output and carry - mov r1, #1 - movs r1, r1, rrx - bcc fail - movs r1, r1, rrx - beq fail - bcs fail - add r0, #1 - - @test 6 - test carry output from rotated constant - movs r5, #0xf0000000 - bcc fail - movs r5, #0xf - bcc fail - movs r5, #0x100 - bcs fail - add r0, #1 - - @test 7 - test carry output from LSL - mov r5, #0x1 - movs r5, r5, lsl #1 - bcs fail - mov r5, #0x80000000 - movs r5, r5, lsl #1 - bcc fail - add r0, #1 - - @test 8 - test carry output from LSR - mov r5, #2 - movs r5, r5, lsr #1 - bcs fail - movs r5, r5, lsr #1 - bcc fail - bne fail - add r0, #1 - - @test 9 - test carry output from ASR - mvn r5, #0x01 - movs r5, r5, asr #1 - bcs fail - movs r5, r5, asr #1 - bcc fail - add r0, #1 - - @test 10 - check for LSR #32 to behave correctly - mov r1, #0xa5000000 - mvn r2, r1 - lsrs r3, r1, #32 - bcc fail - lsrs r3, r2, #32 - bcs fail - add r0, #1 - - @test 11 - check for ASR #32 to behave correctly - asrs r3, r1, #32 - bcc fail - cmp r3, #-1 - bne fail - asrs r3, r2, #32 - bcs fail - bne fail - - @barrelshift test passed - mov r0, #0 - bx lr - - @test logical operations -test_logic: - mov r0, #1 - - @test 1 - NOT operation - mov r5, #-1 - mvns r5, r5 - bne fail - add r0, #1 - - @test 2 - AND operation - mov r5, #0xa0 - mov r1, #0x0b - mov r2, #0xab - mov r3, #0xba - - ands r4, r5, r1 - bne fail - ands r4, r5, r2 - cmp r4, r5 - bne fail - add r0, #1 - - @test 3 - ORR and EOR operations - orr r4, r5, r1 - eors r4, r2, r4 - bne fail - orr r4, r1, r5 - teq r4, r2 - bne fail - add r0, #1 - - @test 4 - TST opcode - tst r1, r5 - bne fail - tst r4, r2 - beq fail - add r0, #1 - - @test 5 - BIC opcode - bics r4, r2, r3 - cmp r4, #1 - bne fail - - @logical test passed - mov r0, #0 - bx lr - - @test adder, substracter, C and V flags -test_adder: - mov r0, #1 - - @test 1 - check for carry when adding - mov r5, #0xf0000000 - mvn r1, r5 @0x0fffffff - adds r2, r1, r5 - bcs fail - bvs fail - - adds r2, #1 - bcc fail - bvs fail - - adc r2, #120 - cmp r2, #121 - bne fail - bvs fail - add r0, #1 - - @test 2 - check for overflow when adding - mov r3, #0x8fffffff @two large negative numbers become positive - adds r3, r5 - bvc fail - bcc fail - bmi fail - - mov r3, #0x10000000 - adds r3, r1 @r3 = 0x1fffffff - bvs fail - bcs fail - - adds r3, #0x60000001 @two large positive numbers become negative - bvc fail - bpl fail - - add r0, #1 - - @test 3 - check for carry when substracting - mov r5, #0x10000000 - subs r2, r5, r1 - bcc fail - bvs fail - - subs r2, #1 - bcc fail - bvs fail - - subs r2, #1 - bcs fail - bvs fail - - add r0, #1 - - @test 4 - check for overflow when substracting - mov r3, #0x90000000 - subs r3, r5 - bvs fail - bcc fail - - subs r3, #1 @substract a positive num from a large negative make the result positive - bvc fail - bcc fail - - @test 5 - check for carry when reverse substracting - mov r3, #1 - rsbs r2, r1, r5 - bcc fail - bvs fail - rsbs r2, r3, r2 - bcc fail - bvs fail - rscs r2, r3, r2 - bcs fail - bvs fail - - add r0, #1 - - @test 6 - check for overflow when reverse substracting - mov r2, #0x80000000 - mov r1, #-1 - rsbs r2, r1 - bvs fail - bmi fail - bcc fail - - mov r0, #0 - bx lr - -@test barrelshift with register controler rotates -test_bshift_reg: - mov r0, #1 - - mov r1, #0 - mov r2, #7 - mov r3, #32 - mov r4, #33 - mov r5, #127 - mov r6, #256 - add r7, r6, #7 - mov r8, #0xff000000 - - @test 1 LSL mode with register shift - movs r9, r8, lsl r2 - bpl fail - bcc fail - @make sure lsl #0 does not affect carry - movs r9, r2, lsl r1 - bcc fail - @test using the same register twice - mov r9, r2, lsl r2 - cmp r9, #0x380 - bne fail - - add r0, #1 - - @test 2 - LSL mode with barrelshift > 31 - movs r9, r2, lsl r3 - bcc fail - bne fail - movs r9, r2, lsl r4 - bcs fail - bne fail - add r0, #1 - - @test 3 - LSL mode with barrelshift >= 256 (only 8 bits used) - movs r9, r2, lsl r6 - bcs fail - cmp r9, #7 - bne fail - - mov r9, r2, lsl r7 - cmp r9, #0x380 - bne fail - - movs r9, r8, lsl r7 - bpl fail - bcc fail - - add r0, #1 - - @test 4 - LSR mode with register shift - mov r2, #4 - add r7, r6, #4 - - movs r9, r8, lsr r2 - bmi fail - bcs fail - @make sure lsr #0 does not affect carry - movs r9, r2, lsr r1 - bcs fail - cmp r9, #4 - bne fail - - movs r9, r8, lsr r2 - bcs fail - cmp r9, #0xff00000 - bne fail - - add r0, #1 - - @test 5 - LSR mode with barrelshift > 31 - movs r9, r8, lsr r3 - bcc fail - bne fail - movs r9, r8, lsr r4 - bcs fail - bne fail - add r0, #1 - - @test 6 - LSR mode with barrelshift >= 256 (only 8 bits used) - movs r9, r8, lsr r6 - bcs fail - cmp r9, #0xff000000 - bne fail - - movs r9, r8, lsr r7 - cmp r9, #0xff00000 - bne fail - - mov r0, #0 - bx lr - -array: - .word 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -array2: - .word 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 - -test_load: - mov r0, #1 - - @ Test1 basic load operations - ldr r1, .larray1 - ldr r2, .larray2 - - ldr r3, [r1] - teq r3, #0 - bne fail - - ldr r3, [r2] - teq r3, #16 - bne fail - add r0, #1 - - @ Test 2 load operations with offsets - ldr r3, [r2, #-60] - teq r3, #1 - bne fail - - ldr r3, [r1, #20] - teq r3, #5 - bne fail - add r0, #1 - - @ Test 3 - test positive register offset addressing - mov r3, #124 -.lloop: - ldr r4, [r1, r3] - cmp r4, r3, lsr #2 - bne fail - subs r3, #4 - bpl .lloop - add r0, #1 - - @ Test 4 - test negative register offset addressing - mov r3, #64 -.lloop2: - ldr r4, [r2, -r3] - rsb r4, #0x10 - cmp r4, r3, lsr #2 - bne fail - subs r3, #4 - bne .lloop2 - add r0, #1 - - @ Test 5 - test positive register offset addressing with shift - mov r3, #0 -.lloop3: - ldr r4, [r1, r3, lsl #2] - cmp r4, r3 - bne fail - add r3, #1 - cmp r3, #32 - bne .lloop3 - add r0, #1 - - @ Test 6 - test negative register offset addressing with shift - mov r3, #0 -.lloop4: - ldr r4, [r2, -r3, lsl #2] - rsb r4, #0x10 - cmp r4, r3 - bne fail - add r3, #1 - cmp r3, #16 - bne .lloop4 - add r0, #1 - - @ Test 7 - test offset with pre-increment - mov r3, #31 - mov r5, r1 -.lloop5: - ldr r4, [r5, #4]! - rsb r4, #32 - cmp r4, r3 - bne fail - subs r3, #1 - bne .lloop5 - add r0, #1 - - @ Test 8 - test offset with pre-degrement - mov r3, #31 - add r5, r1, #128 -.lloop6: - ldr r4, [r5, #-4]! - cmp r4, r3 - bne fail - subs r3, #1 - bpl .lloop6 - add r0, #1 - - @ Test 9 - test offset with post-increment - mov r3, #32 - mov r5, r1 -.lloop7: - ldr r4, [r5], #4 - rsb r4, #32 - cmp r4, r3 - bne fail - subs r3, #1 - bne .lloop7 - add r0, #1 - - @ Test 10 - test offset with post-decrement - mov r3, #31 - add r5, r1, #124 -.lloop8: - ldr r4, [r5], #-4 - cmp r3, r4 - bne fail - subs r3, #1 - bpl .lloop8 - add r0, #1 - - @ Test 11 - test register post-increment with a negative value - mov r6, #0xfffffff0 - mov r5, r2 - mov r3, #16 -.lloop9: - ldr r4, [r5], r6, asr #2 - cmp r4, r3 - bne fail - subs r3, #1 - bpl .lloop9 - - mov r0, #0 - bx lr - -.larray1: - .word array -.larray2: - .word array2 - -test_store: - mov r0, #1 - - @ Test 1 - test basic store opperation - ldr r1, .larray1 - mov r2, #0x24 - str r2, [r1] - ldr r2, [r1] - cmp r2, #0x24 - bne fail - add r0, #1 - - @ Test 2 - check for post-increment and pre-decrement writes - mov r2, #0xab - mov r3, #0xbc - str r2, [r1, #4]! @ array[1] = 0xab - str r3, [r1], #4 @ array[1] = 0xbc - ldr r2, [r1, #-4]! @ read 0xbc - ldr r3, [r1, #-4]! @ read 0x24 - cmp r3, #0x24 - bne fail - cmp r2, #0xbc - bne fail - add r0, #1 - - @ Test 3 - check for register post-increment addressing - mov r2, #8 - mov r3, #20 - mov r4, r1 - str r2, [r4], r2 - str r3, [r4], r2 - sub r4, #16 - cmp r4, r1 - bne fail - ldr r2, [r1] - cmp r2, #8 - bne fail - ldr r2, [r1, #8] - cmp r2, #20 - bne fail - - mov r0, #0 - bx lr - - @ Tests byte loads and store -test_byte: - mov r0, #1 - - @ test 1 - test store bytes - ldr r1, .larray1 - mov r2, #8 -.bloop: - strb r2, [r1], #1 - subs r2, #1 - bne .bloop - - ldr r2, .ref_words+4 - ldr r3, [r1, #-4]! - cmp r2, r3 - bne fail - - ldr r2, .ref_words - ldr r3, [r1, #-4]! - cmp r2, r3 - bne fail - add r0, #1 - - @ test 2 - test load bytes - mov r2, #8 -.bloop2: - ldrb r3, [r1], #1 - cmp r3, r2 - bne fail - subs r2, #1 - bne .bloop2 - - mov r0, #0 - bx lr - -.ref_words: - @ Table for ARMs who access bytes in a little-endian order - .word 0x05060708, 0x01020304 - - @ Table for ARMs who access bytes in a big-endian order -@ .word 0x08070605, 0x04030201 - - @ Good source for flags info : - @ http://blogs.arm.com/software-enablement/206-condition-codes-1-condition-flags-and-codes/ - -test_cpsr: - @ Enter SYS mode. - msr cpsr_c, #0x1f - mov r0, #1 - - @ Test 1 - in depth test for the condition flags - mrs r1, cpsr - and r1, #0x000000ff - msr cpsr_flg, r1 - @ NZCV = {0000} - bvs fail - bcs fail - beq fail - bmi fail - bhi fail @ bhi <-> bls - blt fail @ blt <-> bge - ble fail @ ble <-> bgt - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0001} - bvc fail - bhi fail - bge fail - bgt fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0010} - bvs fail - bcc fail - bls fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0011} - bls fail - bge fail - bgt fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0100} - bne fail - bhi fail - bgt fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0101} - bgt fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {0110} - bhi fail - - add r1, #0x20000000 - msr cpsr, r1 - @ NZCV = {1000} - bpl fail - bge fail - bgt fail - - add r1, #0x10000000 - msr cpsr, r1 - @ NZCV = {1001} - blt fail - - add r1, #0x30000000 - msr cpsr, r1 - @ NZCV = {1100} - bgt fail - - add r0, #1 - - @ Test 2 - test for the FIQ processor mode - mov r1, r14 @ save our link register and stack pointer - mov r2, r13 - mov r3, #30 - mov r4, #40 - mov r5, #50 - mov r6, #60 - mov r7, #70 - mov r8, #80 - mov r9, #90 - mov r10, #100 - mov r11, #110 - mov r12, #120 - mov r13, #130 - mov r14, #140 - - msr cpsr, #0xd1 @ go into FIQ mode, disable all interrupts (F and I bits set) - cmp r3, #30 - bne .fail - mov r8, #8 @ overwrite fiq regs... - mov r9, #9 - mov r10, #10 - mov r11, #11 - mov r12, #12 - mov r13, #13 - mov r14, #14 - mov r3, #3 @ also overwrite some user regs - mov r4, #4 - mov r5, #5 - mov r6, #6 - mov r7, #7 - msr cpsr, #0x1f @ back to SYS mode - cmp r3, #3 @ r3-7 should have been affected, but not r8-r14 - bne .fail - cmp r4, #4 - bne .fail - cmp r5, #5 - bne .fail - cmp r6, #6 - bne .fail - cmp r7, #7 - bne .fail - cmp r8, #80 - bne .fail - cmp r9, #90 - bne .fail - cmp r10, #100 - bne .fail - cmp r11, #110 - bne .fail - cmp r12, #120 - bne .fail - cmp r13, #130 - bne .fail - cmp r14, #140 - bne .fail - add r0, #1 - - - @ Test 3 - test for the SUP processor mode - mov r12, #120 - mov r13, #130 - mov r14, #140 - msr cpsr, #0x13 @ enter SUP mode - cmp r12, #120 - bne .fail - mov r12, #12 - mov r13, #13 - mov r14, #14 - msr cpsr, #0x1f @ back into SYS mode - cmp r12, #12 - bne .fail - cmp r13, #130 - bne .fail - cmp r14, #140 - bne .fail - add r0, #1 - - @ Test 4 - test for the UND processor mode - mov r12, #120 - mov r13, #130 - mov r14, #140 - msr cpsr, #0x1b @ enter UND mode - cmp r12, #120 - bne .fail - mov r12, #12 - mov r13, #13 - mov r14, #14 - msr cpsr, #0x1f @ back into SYS mode - cmp r12, #12 - bne .fail - cmp r13, #130 - bne .fail - cmp r14, #140 - bne .fail - add r0, #1 - - @ Test 5 - test for the IRQ processor mode - mov r12, #120 - mov r13, #130 - mov r14, #140 - msr cpsr, #0x92 @ enter IRQ mode, IRQ disabled - cmp r12, #120 - bne .fail - mov r12, #12 - mov r13, #13 - mov r14, #14 - msr cpsr, #0x1f @ back into SYS mode - cmp r12, #12 - bne .fail - cmp r13, #130 - bne .fail - cmp r14, #140 - bne .fail - - mov r0, #0 - -.fail: - msr cpsr, #0x1f @ back into SYS mode - mov r13, r2 - bx r1 @ return - - @ Test multiplier and how it affects the flags -test_mul: - mov r0, #1 - - @ Test 1 - MUL instruction - mov r1, #0 - mov r2, #2 - mov r3, #3 - mul r4, r2, r3 - cmp r4, #6 - bne fail - bmi fail - - muls r5, r1, r2 - bne fail - bmi fail - - muls r4, r2 - cmp r4, #12 - bne fail - bmi fail - -@ mul r3, r3, r4 @ no joke, verified to fail on a real ARM ! -@ cmp r4, #36 -@ bne fail - - mov r3, #-3 @ multiply positive * negative - muls r5, r2, r3 - bpl fail - cmp r5, #-6 - bne fail - - mov r2, #-2 @ multiply negative * negative - muls r5, r2, r3 - bmi fail - cmp r5, #6 - bne fail - add r0, #1 - - @ Test 2 - MLA instruction - mov r1, #10 - mov r2, #2 - mov r3, #5 - mlas r4, r1, r2, r3 @ 2*10 + 5 = 25 - bmi fail -@ bcs fail @ on a real ARM, C flag after MLA is unpredictable - bvs fail - cmp r4, #25 - bne fail - - mov r1, #-10 - mlas r4, r1, r2, r3 @ 2*-10 + 5 = -15 - bpl fail - bvs fail - cmp r4, #-15 - bne fail - - mov r3, #0x80000001 @ causes addition overflow - mlas r4, r1, r2, r3 - bmi fail -@ bvc fail @ on a real ARM, V flag is not updated ? - - mov r0, #0 - bx lr - - @ Test load multiple and store multiple instructions -test_ldmstm: - mov r0, #1 - - @ Test 1 - STMIA - mov r1, #1 - mov r2, #2 - mov r3, #3 - mov r4, #4 - ldr r5, .larray1 - mov r6, r5 - - stmia r6!, {r1-r4} - sub r6, r5 - cmp r6, #16 - bne fail - - ldr r6, [r5] - cmp r6, #1 - bne fail - ldr r6, [r5, #4] - cmp r6, #2 - bne fail - ldr r6, [r5, #8] - cmp r6, #3 - bne fail - ldr r6, [r5, #12] - cmp r6, #4 - bne fail - add r0, #1 - - @ Test 2 - STMIB - mov r6, r5 - stmib r6!, {r1-r3} - sub r6, r5 - cmp r6, #12 - bne fail - - ldr r6, [r5, #4] - cmp r6, #1 - bne fail - ldr r6, [r5, #8] - cmp r6, #2 - bne fail - ldr r6, [r5, #12] - cmp r6, #3 - bne fail - add r0, #1 - - @ Test 3 - STMDB - add r6, r5, #12 - stmdb r6!, {r1-r3} - cmp r6, r5 - bne fail - - ldr r6, [r5] - cmp r6, #1 - bne fail - ldr r6, [r5, #8] - cmp r6, #3 - bne fail - add r0, #1 - - @ Test 4 - STMDA - add r6, r5, #12 - stmda r6!, {r1-r3} - cmp r6, r5 - bne fail - ldr r6, [r5, #4] - cmp r6, #1 - bne fail - ldr r6, [r5, #12] - cmp r6, #3 - bne fail - add r0, #1 - - @ Test 5 - LDMIA - ldr r5, .larray2 - ldmia r5, {r1-r4} - cmp r1, #16 - bne fail - cmp r2, #17 - bne fail - cmp r3, #18 - bne fail - cmp r4, #19 - bne fail - add r0, #1 - - @ Test 6 - LDMIB - ldmib r5!, {r1-r4} - cmp r1, #17 - bne fail - cmp r2, #18 - bne fail - cmp r3, #19 - bne fail - cmp r4, #20 - bne fail - add r0, #1 - - @ Test 7 - LDMDB - ldmdb r5!, {r1-r3} - cmp r3, #19 - bne fail - cmp r2, #18 - bne fail - cmp r1, #17 - bne fail - add r0, #1 - - @ Test 8 - LDMDA - ldmda r5, {r1-r2} - cmp r1, #16 - bne fail - cmp r2, #17 - bne fail - - mov r0, #0 - bx lr - - @ Test proper jumping on instructions that affect R15 -test_r15jumps: - mov r0, #1 - - @ Test 1 - a standard, conditional jump instruction - ldr r3, .llabels - mov r1, #0 - movs r2, #0 - moveq r15, r3 @ jump to label 1 - movs r2, #12 - movs r1, #13 @ make sure fetched/decoded instructions do no execute -.label1: - bne fail - cmp r1, #0 - bne fail - cmp r2, #0 - bne fail - add r0, #1 - - @ Test 2 - a jump instruction is not executed - ldr r3, .llabels+4 - movs r2, #12 - moveq r15, r3 - movs r2, #0 -.label2: - cmp r2, #0 - bne fail - add r0, #1 - - @ Test 3 - add instruction to calculate new address - ldr r3, .llabels+8 - movs r1, #0 - movs r2, #0 - add r15, r3, #8 @go 2 instructions after label 3 -.label3: - movs r1, #12 - movs r2, #13 - bne fail @ program executions continues here - bne fail - add r0, #1 - - @ Test 4 - use an addition directly from PC+8 (r15) - movs r2, #0 - movs r1, #0 - add r15, r15, #4 @ Skip 2 instructions This could actually be used for a nice jump table if a register were used instead of #4 - movs r1, #1 - movs r2, #2 - bne fail - bne fail - add r0, #1 - - @ Test 5 - load r15 directly from memory - movs r1, #1 - movs r2, #2 - ldrne r15, .llabels+12 @ Makes sure code after a ldr r15 is not executed - movs r1, #0 - movs r2, #0 -.label4: - beq fail - beq fail - - ldreq r15, .llabels+16 @ Makes sure everything is right when a ldr r15 is not taken - movs r2, #-2 -.label5: - bpl fail - cmp r2, #-2 - bne fail - add r0, #1 - - @ Test 6 - load r15 as the last step of a LDM instruction - ldr r3, .llabels + 6*4 - movs r1, #0 - movs r2, #0 - ldmia r3, {r4-r8, r15} @jump to label6 - movs r1, #4 - movs r2, #2 -.label6: - bne fail - bne fail - - mov r0, #0 - bx lr - -.align 8 -.llabels: - .word .label1, .label2, .label3, .label4, .label5, .label6, .llabels - -test_rti: - mov r0, #1 - mov r12, #14 - - @ Test 1 - test normal RTI - msr cpsr, #0xd1 @ enter into FIQ mode (interrupt disabled) - msr spsr, #0x4000001f @ emulate a saved CPSR in SYS mode, with NZCV = {0100} - - movs r8, #-12 @ now the FIQ sets it's CPSR to NZCV = {1000} - ldr r8, .rtilabels @ simulate an interrupt return - movs r15, r8 @ return from interrupt and move SPSR to CPSR - -.rtilabel1: - mov r12, #1000 - bmi .rtifail @ ?!? WTF !?! - bne .rtifail - mov r12, #2000 - add r0, #1 - - @ Test 2 - test LDM instruction with S flag - msr cpsr, #0xd1 - ldr r8, .rtilabels + 20 - ldmib r8!, {r9, r10} @ fiq_r9 = 1, fiq_r10 = 2 - ldmib r8, {r9, r10}^ @ r8 = 3, r9 = 4 ( ^ => load to user registers ) - cmp r9, #1 - bne .rtifail - cmp r10, #2 - bne .rtifail - msr cpsr, #0x1f - cmp r9, #3 - bne .rtifail - cmp r10, #4 - bne .rtifail - add r0, #1 - - mov r12, #4000 - - @ Test 3 - test LDM instruction with S flag for returning from an interrupt - msr cpsr, #0xd1 @ FIQ mode, NZCV = {0000} - msr spsr, #0x80000010 @ saved is normal mode with NZCV = {1000} - - ldr r8, .rtilabels + 20 - add r8, #8 - - movs r9, #0 @ NZCV = {0100} - ldmib r8, {r9-r11, r15}^ @ This should return to user mode and restore CPSR to NZCV = {1000} - -.rtilabel2: - bpl .rtifail - beq .rtifail - b passed - -.rtifail: - msr cpsr, #0x10 - mov r12, #100 - b .rtifail - bx lr - - -.rtilabels: - .word .rtilabel1, 1, 2, 3, 4, .rtilabels, .rtilabel2 Index: trunk/src/ts/arm_test/Description.txt =================================================================== --- trunk/src/ts/arm_test/Description.txt (revision 57) +++ trunk/src/ts/arm_test/Description.txt (nonexistent) @@ -1,3 +0,0 @@ -This test is taken from the ARM4U CPU project. It is a comprehensive test -and exercises a bunch of different ARM instructions. Interrupts must not -be enabled during the test since handlers are not properly setup. Index: trunk/src/ts/arm_test/Config.cfg =================================================================== --- trunk/src/ts/arm_test/Config.cfg (revision 57) +++ trunk/src/ts/arm_test/Config.cfg (nonexistent) @@ -1,47 +0,0 @@ -# TC config. - -%Config = ( - # CPU configuration. - DATA_CACHE_SIZE => 4096, # Data cache size in bytes - CODE_CACHE_SIZE => 4096, # Instruction cache size in bytes - CODE_SECTION_TLB_ENTRIES => 8, # Instruction section TLB entries. - CODE_SPAGE_TLB_ENTRIES => 32, # Instruction small page TLB entries. - CODE_LPAGE_TLB_ENTRIES => 16, # Instruction large page TLB entries. - DATA_SECTION_TLB_ENTRIES => 8, # Data section TLB entries. - DATA_SPAGE_TLB_ENTRIES => 32, # Data small page TLB entries. - DATA_LPAGE_TLB_ENTRIES => 16, # Data large page TLB entries. - BP_DEPTH => 1024, # Branch predictor depth. - INSTR_FIFO_DEPTH => 4, # Instruction buffer depth. - STORE_BUFFER_DEPTH => 16, # Store buffer depth. - SYNTHESIS => 0, # 0 allows debug messages. - - # Testbench configuration. - WAVES => 0, # Log VCD - EXT_RAM_SIZE => 32768, # External RAM size. - SEED => -1, # Seed. Use -1 to use random seed. - DUMP_START => 2000, # Starting memory address from which to dump. - DUMP_SIZE => 200, # Length of dump in bytes. - MAX_CLOCK_CYCLES => 40000, # Clock cycles to run the simulation for. - DEFINE_TLB_DEBUG => 0, # Make this 1 to define TLB_DEBUG. Useful for debugging the TLB. - REG_CHECK => { - # Value of registers(Post Translate) at the end of the test. - # "r => Verilog_value" - "r0" => "32'hFFFFFFFF", - "r1" => "32'hFFFFFFFF", - "r2" => "32'hFFFFFFFF", - "r3" => "32'hFFFFFFFF", - "r4" => "32'hFFFFFFFF", - "r5" => "32'hFFFFFFFF", - "r6" => "32'hFFFFFFFF", - "r7" => "32'hFFFFFFFF", - "r8" => "32'hFFFFFFFF", - "r9" => "32'hFFFFFFFF", - "r10" => "32'hFFFFFFFF", - "r11" => "32'hFFFFFFFF", - "r12" => "32'hFFFFFFFF", - "r13" => "32'hFFFFFFFF", - "r14" => "32'hFFFFFFFF" - }, - FINAL_CHECK => {} -); - Index: trunk/src/scripts/uart_input.bash =================================================================== --- trunk/src/scripts/uart_input.bash (revision 57) +++ trunk/src/scripts/uart_input.bash (nonexistent) @@ -1,18 +0,0 @@ -#!/bin/bash - -############################################## -# This file reads characters into a file. The -# Verilog testbench then opens this file and -# writes it to the UART RX character wise. -# -# Call this like: -# bash uart_input.bash -############################################## - -IFS="" - -while true -do - read -n1 -r -d "" char - echo -n "$char" >> "$1" -done Index: trunk/src/scripts/run_sim.pl =================================================================== --- trunk/src/scripts/run_sim.pl (revision 57) +++ trunk/src/scripts/run_sim.pl (nonexistent) @@ -1,220 +0,0 @@ -#!/usr/bin/perl -w - -# ----------------------------------------------------------------------------- -# -- -- -# -- (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. -- -# -- -- -# ----------------------------------------------------------------------------- - - -use strict; -use warnings; - -my %Config = do "./Config.cfg"; - -# Extract from config -my $WAVES = $Config{'WAVES'}; -my $RAM_SIZE = $Config{'EXT_RAM_SIZE'}; -my $SEED = $Config{'SEED'}; -my $SYNTHESIS = $Config{'SYNTHESIS'}; -my $DUMP_START = $Config{'DUMP_START'}; -my $DUMP_SIZE = $Config{'DUMP_SIZE'}; -my $MAX_CLOCK_CYCLES = $Config{'MAX_CLOCK_CYCLES'}; -my $TLB_DEBUG = $Config{'DEFINE_TLB_DEBUG'}; -my $TX_TERM0 = $Config{'UART0_TX_TERMINAL'}; -my $TX_TERM1 = $Config{'UART1_TX_TERMINAL'}; -my $RX_TERM0 = $Config{'UART0_RX_TERMINAL'}; -my $RX_TERM1 = $Config{'UART1_RX_TERMINAL'}; -my $IRQ_EN = $Config{'IRQ_EN'}; -my $FIQ_EN = $Config{'FIQ_EN'}; -my $DATA_CACHE_SIZE = $Config{'DATA_CACHE_SIZE'}; -my $CODE_CACHE_SIZE = $Config{'CODE_CACHE_SIZE'}; -my $CODE_SECTION_TLB_ENTRIES = $Config{'CODE_SECTION_TLB_ENTRIES'}; -my $CODE_SPAGE_TLB_ENTRIES = $Config{'CODE_SPAGE_TLB_ENTRIES'}; -my $CODE_LPAGE_TLB_ENTRIES = $Config{'CODE_LPAGE_TLB_ENTRIES'}; -my $DATA_SECTION_TLB_ENTRIES = $Config{'DATA_SECTION_TLB_ENTRIES'}; -my $DATA_SPAGE_TLB_ENTRIES = $Config{'DATA_SPAGE_TLB_ENTRIES'}; -my $DATA_LPAGE_TLB_ENTRIES = $Config{'DATA_LPAGE_TLB_ENTRIES'}; -my $BP = $Config{'BP_DEPTH'}; -my $FIFO = $Config{'INSTR_FIFO_DEPTH'}; -my $SBUF_DEPTH = $Config{'STORE_BUFFER_DEPTH'}; - -# Leave this as is. -my $ZAP_HOME = "../../../"; -my $TEST = "null"; -my $SCRATCH = "/dev/null"; - -# Generate a random seed if needed -if ( $SEED == -1 ) { - $SEED = int rand (0xffffffff); -} - -# Parse arguments. -foreach(@ARGV) { - if (/^\+test\+(.*)/) { - $SCRATCH = "$ZAP_HOME/obj/ts/$1"; $TEST = $1; - } else { - die "Unrecognized option to run_sim.pl\n"; - } -} - -# Log file - the final file is compressed. -my $LOG_FILE_PATH = "$SCRATCH/zap.log"; -my $COMPRESSED_LOG_FILE_PATH = "$SCRATCH/zap.log.gz"; - -# VCD file - the final file is compressed. -my $VCD_PATH = "$SCRATCH/zap.vcd"; -my $COMPRESSED_VCD_PATH = "$SCRATCH/zap.vcd.gz"; - -# Paths -my $VVP_PATH = "$SCRATCH/zap.vvp"; -my $PROG_PATH = "$SCRATCH/zap_mem.v"; -my $TARGET_BIN_PATH = "$SCRATCH/zap.bin"; -my $UART0_PATH_TX = "$SCRATCH/zapuart0.tx"; -my $UART1_PATH_TX = "$SCRATCH/zapuart1.tx"; -my $UART0_PATH_RX = "$SCRATCH/zapuart0.rx"; -my $UART1_PATH_RX = "$SCRATCH/zapuart1.rx"; - -# Generate IVL options including VCD generation path. -my $IVL_OPTIONS = ""; - - # Compile CPU - $IVL_OPTIONS .= " -I$ZAP_HOME/src/rtl/cpu -I$ZAP_HOME/obj/ts/$TEST "; - $IVL_OPTIONS .= " $ZAP_HOME/src/rtl/cpu/*.v "; - - # Compile other TB components - $IVL_OPTIONS .= " -I$ZAP_HOME/src/testbench/External_IP/uart16550/rtl "; - $IVL_OPTIONS .= " $ZAP_HOME/src/testbench/External_IP/uart16550/rtl/*.v "; - $IVL_OPTIONS .= " $ZAP_HOME/src/testbench/*.v "; - $IVL_OPTIONS .= " -o $VVP_PATH -gstrict-ca-eval -Wall -g2001 -Winfloop -DSEED=$SEED -DMEMORY_IMAGE=\\\"$PROG_PATH\\\" "; - $IVL_OPTIONS .= " -DVCD_FILE_PATH=\\\"$VCD_PATH\\\" "; - -# Generate UART related defines for both the UARTs. -if ( $TX_TERM0 ) { $IVL_OPTIONS .= " -DUART0_FILE_PATH_TX=\\\"$UART0_PATH_TX\\\" "; } else { $IVL_OPTIONS .= " -DUART0_FILE_PATH_TX=\\\"/dev/null\\\" "; } -if ( $TX_TERM1 ) { $IVL_OPTIONS .= " -DUART1_FILE_PATH_TX=\\\"$UART1_PATH_TX\\\" "; } else { $IVL_OPTIONS .= " -DUART1_FILE_PATH_TX=\\\"/dev/null\\\" "; } -if ( $RX_TERM0 ) { $IVL_OPTIONS .= " -DUART0_FILE_PATH_RX=\\\"$UART0_PATH_RX\\\" "; } else { $IVL_OPTIONS .= " -DUART0_FILE_PATH_RX=\\\"/dev/null\\\" "; } -if ( $RX_TERM1 ) { $IVL_OPTIONS .= " -DUART1_FILE_PATH_RX=\\\"$UART1_PATH_RX\\\" "; } else { $IVL_OPTIONS .= " -DUART1_FILE_PATH_RX=\\\"/dev/null\\\" "; } - -# CPU / TB configuration related parameters. -$IVL_OPTIONS .= " -Pzap_test.RAM_SIZE=$RAM_SIZE -Pzap_test.START=$DUMP_START -Pzap_test.COUNT=$DUMP_SIZE -DLINUX -Pzap_test.STORE_BUFFER_DEPTH=$SBUF_DEPTH "; -$IVL_OPTIONS .= " -Pzap_test.BP_ENTRIES=$BP -Pzap_test.FIFO_DEPTH=$FIFO "; -$IVL_OPTIONS .= " -Pzap_test.DATA_SECTION_TLB_ENTRIES=$DATA_SECTION_TLB_ENTRIES "; -$IVL_OPTIONS .= " -Pzap_test.DATA_LPAGE_TLB_ENTRIES=$DATA_LPAGE_TLB_ENTRIES -Pzap_test.DATA_SPAGE_TLB_ENTRIES=$DATA_SPAGE_TLB_ENTRIES -Pzap_test.DATA_CACHE_SIZE=$DATA_CACHE_SIZE "; -$IVL_OPTIONS .= " -Pzap_test.CODE_SECTION_TLB_ENTRIES=$CODE_SECTION_TLB_ENTRIES -Pzap_test.CODE_LPAGE_TLB_ENTRIES=$CODE_LPAGE_TLB_ENTRIES -Pzap_test.CODE_SPAGE_TLB_ENTRIES=$CODE_SPAGE_TLB_ENTRIES "; -$IVL_OPTIONS .= " -Pzap_test.CODE_CACHE_SIZE=$CODE_CACHE_SIZE "; - -# Defines -if ( 1 ) { $IVL_OPTIONS .= " -DMAX_CLOCK_CYCLES=$MAX_CLOCK_CYCLES " } -if ( $IRQ_EN ) { $IVL_OPTIONS .= "-DIRQ_EN "; } -if ( $FIQ_EN ) { $IVL_OPTIONS .= "-DFIQ_EN "; } -if ( $SYNTHESIS ) { $IVL_OPTIONS .= "-DSYNTHESIS "; } -if ( $TLB_DEBUG ) { $IVL_OPTIONS .= "-DTLB_DEBUG "; } -if ( $WAVES ) { $IVL_OPTIONS .= "-DWAVES "; } - -########################################################################################################################################### -# Create checker assertion verilog include file. -########################################################################################################################################### - -open(HH, ">$ZAP_HOME/obj/ts/$TEST/zap_check.vh") or die "Could not write to ../../../obj/ts/$TEST/zap_check.vh"; - -my $REG_HIER = "u_chip_top.u_zap_top.u_zap_core.u_zap_writeback.u_zap_register_file"; -my $RAM_HIER = "u_chip_top.u_ram.ram"; -my $X = $Config{'FINAL_CHECK'}; - -foreach(keys (%$X)) { - my $string = "$_, $$X{$_}, ${RAM_HIER}[$_/4]"; - print "if ( ${RAM_HIER}[$_/4] != ", $$X{"$_"}, ') begin $display("Error: Memory values not matched. PTR = %d EXP = %x REC = %x", ', $string , ' ); $finish; end else $display("RAM check passed!");',"\n"; - print HH "if ( ${RAM_HIER}[$_/4] != ", $$X{"$_"}, ') begin $display("Error: Memory values not matched. PTR = %d EXP = %x REC = %x", ', $string , ' ); $finish; end else $display("RAM check passed!");',"\n"; -} - -$X = $Config{'REG_CHECK'}; - -foreach(keys (%$X)) { - my $string = "\"$_\", $$X{$_}, $REG_HIER.$_"; - print "if ( $REG_HIER.$_ != ", $$X{"$_"}, ') begin $display("Error: Register values not matched. PTR = %s EXP = %x REC = %x", ', $string , ' ); $finish; end else $display("Reg check passed!");',"\n"; - print HH "if ( $REG_HIER.$_ != ", $$X{"$_"}, ') begin $display("Error: Register values not matched. PTR = %s EXP = %x REC = %x", ', $string , ' ); $finish; end else $display("Reg check passed!");',"\n"; -} - -print HH '$display("Simulation Complete. All checks (if any) passed.");$finish;'; - -############################################################################################################################################ -# Set up UART terminals -############################################################################################################################################ - -if ( $TX_TERM0 ) { - system1("rm -f $UART0_PATH_TX"); # Remove UART file. - system1("mknod $UART0_PATH_TX p"); # Create a UART output FIFO file. -} - -if ( $TX_TERM1 ) { - system1("rm -f $UART1_PATH_TX"); # Remove UART file. - system1("mknod $UART1_PATH_TX p"); # Create a UART output FIFO file. -} - -if ( $RX_TERM0 ) { - system1("rm -f $UART0_PATH_RX"); # Remove UART file. - system1("touch $UART0_PATH_RX"); # Create file. -} - -if ( $RX_TERM1 ) { - system1("rm -f $UART1_PATH_RX"); # Remove UART file. - system1("touch $UART1_PATH_RX"); # Create file. -} - -die "Error: XTerm could not be found!" if system("which xterm"); - -if ( $TX_TERM0 ) { die "Failed to open UART TX terminal 0." if system1("xterm -T 'TB UART Output' -hold -e 'cat $UART0_PATH_TX' &"); } -if ( $TX_TERM1 ) { die "Failed to open UART TX terminal 1." if system1("xterm -T 'TB UART Output' -hold -e 'cat $UART1_PATH_TX' &"); } -if ( $RX_TERM0 ) { die "Failed to open UART RX terminal 0." if system1("xterm -T 'TB UART Input' -hold -e 'bash $ZAP_HOME/src/scripts/uart_input.bash $UART0_PATH_RX' &"); } -if ( $RX_TERM1 ) { die "Failed to open UART RX terminal 1." if system1("xterm -T 'TB UART Input' -hold -e 'bash $ZAP_HOME/src/scripts/uart_input.bash $UART1_PATH_RX' &"); } - -############################################################################################################################################# -# Compile using VVP -############################################################################################################################################# - -die "*E: Verilog Compilation Failed!\n" if system1("iverilog $IVL_OPTIONS"); -die "*E: Failed to read out Log FIFO!\n" if system1("rm -f $LOG_FILE_PATH ; mkfifo $LOG_FILE_PATH ; cat $LOG_FILE_PATH | gzip > $COMPRESSED_LOG_FILE_PATH &"); - -if ( $WAVES ) { - die "*E: Failed to read out VCD FIFO!\n" if system1("rm -f $VCD_PATH ; mkfifo $VCD_PATH ; cat $VCD_PATH | gzip > $COMPRESSED_VCD_PATH &"); -} - -die "*E: VVP execution error!\n" if system1("vvp $VVP_PATH | tee $LOG_FILE_PATH"); - -############################################################################################################################################### -# Scan for errors and warnings. -############################################################################################################################################### - -die "*E: Errors occurred! Please grep for Errors in $COMPRESSED_LOG_FILE_PATH\n" unless system("zcat $COMPRESSED_LOG_FILE_PATH | grep Error"); -die "*E: There were Warnings! Please grep for Warnings in $COMPRESSED_LOG_FILE_PATH\n" unless system("zcat $COMPRESSED_LOG_FILE_PATH | grep Warning"); - -############################################################################################################################################### -# Functions -############################################################################################################################################### - -sub system1 { - my $x = $_[0]; - print "#SystemCommand: $x\n"; - system("$x"); -} - -exit 0; - - Index: trunk/src/scripts/bin2vlog.pl =================================================================== --- trunk/src/scripts/bin2vlog.pl (revision 57) +++ trunk/src/scripts/bin2vlog.pl (nonexistent) @@ -1,79 +0,0 @@ -#!/usr/bin/perl -w - -#// ----------------------------------------------------------------------------- -#// -- -- -#// -- (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. -- -#// -- -- -#// ----------------------------------------------------------------------------- - -############################################################################### -# Perl script to translate GCC generated binary files into Verilog memory -# files. -# -# Usage: perl bin2vlog.pl -############################################################################### - -use strict; -use warnings; - -# Read command line arguments. -my $bin_file = $ARGV[0]; -my $target_verilog_file = $ARGV[1]; - -# Generate Verilog file. -die "*E: Verilog file creation error...\n" if - system("rm -f $target_verilog_file ; touch $target_verilog_file"); - -# Open the binary and Verilog file using different file handles. -open(my $fh, "<$bin_file") or die - "Bin file $ARGV[0] could not be opened for reading...!\n"; - -open(GH, ">$target_verilog_file") or die - "Target verilog file could not be opened for writing...\n"; - -# Read file in binary mode. -binmode $fh; - -# Memory pointer. -my $counter = 0; - -# -# As long as there are bytes to read from the binary file, we will write out -# those bytes. The ord function returns to numeric value of the byte from 0 -# to 255 corresponding to bytes 8'b0000_0000 to 8'b1111_1111. -# -while (read($fh, my $buf, 1) == 1) { # Get a byte from the file. - - # Print the numeric value of the byte. - my $line = sprintf("mem[$counter] = 8'h%x;\n", ord $buf); - - # Print to the Verilog file. - print GH $line; - - # Increment memory pointer by 1 since we are dealing with bytes. - $counter++; -} - -# Close both the files. -close($fh); -close(GH); - -print "Done...\n"; -exit 0; Index: trunk/src/scripts/makefile =================================================================== --- trunk/src/scripts/makefile (revision 57) +++ trunk/src/scripts/makefile (nonexistent) @@ -1,99 +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 common makefile to be used for all # -# testcases. Note that all paths are relative # -# to the testcase directory. Do a make c2asm # -# if you need the assembly version of C files. # -# # -################################################## - -.DEFAULT_GOAL = all - -.PHONY: clean -.PHONY: c2asm -.PHONY: compiler -.PHONY: dirs - -ARCH := armv5t -TC := $(shell basename `pwd`) -SCRIPT_PATH := ../../scripts/ -C_FILES := $(wildcard *.c) -S_FILES := $(wildcard *.s) -H_FILES := $(wildcard *.h) -LD_FILE := $(wildcard *.ld) -COBJFILES := $(patsubst %.c,../../../obj/ts/$(TC)/%_c.o,$(C_FILES)) -AOBJFILES := $(patsubst %.s,../../../obj/ts/$(TC)/%_s.o,$(S_FILES)) -CFLAGS := -c -msoft-float -mfloat-abi=soft -march=$(ARCH) -g -SFLAGS := -march=$(ARCH) -g -LFLAGS := -T -OFLAGS := -O binary -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -LD := arm-none-eabi-ld -OB := arm-none-eabi-objcopy - -# This rule will convert every ASM to file its corresponding object file. -../../../obj/ts/$(TC)/%_s.o: %.s - $(AS) $(SFLAGS) $^ -o $@ - -# This rule will convert every C file to its corresponding object file. -../../../obj/ts/$(TC)/%_c.o: %.c $(H_FILES) - $(CC) $(CFLAGS) $< -o $@ - -# Rule to convert the object files to an ELF file. -../../../obj/ts/$(TC)/$(TC).elf: $(LD_FILE) $(AOBJFILES) $(COBJFILES) - $(LD) $(LFLAGS) $^ -o $@ - -# Rule to generate a BIN file. -../../../obj/ts/$(TC)/$(TC).bin: ../../../obj/ts/$(TC)/$(TC).elf - $(OB) $(OFLAGS) $^ $@ - -# Rule to convert the bin file to a Verilog image. -../../../obj/ts/$(TC)/zap_mem.v: ../../../obj/ts/$(TC)/$(TC).bin - perl $(SCRIPT_PATH)/bin2vlog.pl $< $@ - -# Rule to run the simulation. -all: dirs $(CC) ../../../obj/ts/$(TC)/zap_mem.v - perl $(SCRIPT_PATH)/run_sim.pl +test+$(TC) - -$(CC): -$(AS): -$(LD): -$(OB): - -dirs: - mkdir -p ../../../obj/ts/$(TC)/ - touch ../../../obj/ts/$(TC)/ - -clean: - mkdir -p ../../../obj/ts/$(TC)/ - rm -fv ../../../obj/ts/$(TC)/* - -c2asm: - $(CC) -S $(CFLAGS) $(X) -o ../../../obj/ts/$(TC)/$(X).asm - -print-% : ; @echo $* = $($*) - Index: trunk/src/scripts/Config.cfg_template =================================================================== --- trunk/src/scripts/Config.cfg_template (revision 57) +++ trunk/src/scripts/Config.cfg_template (nonexistent) @@ -1,58 +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. -- -#// -- -- -#// ----------------------------------------------------------------------------- - - -# Basic template for use in other TCs. - -%Config = ( - # CPU configuration. - DATA_CACHE_SIZE => 4096, # Data cache size in bytes - CODE_CACHE_SIZE => 4096, # Instruction cache size in bytes - CODE_SECTION_TLB_ENTRIES => 8, # Instruction section TLB entries. - CODE_SPAGE_TLB_ENTRIES => 32, # Instruction small page TLB entries. - CODE_LPAGE_TLB_ENTRIES => 16, # Instruction large page TLB entries. - DATA_SECTION_TLB_ENTRIES => 8, # Data section TLB entries. - DATA_SPAGE_TLB_ENTRIES => 32, # Data small page TLB entries. - DATA_LPAGE_TLB_ENTRIES => 16, # Data large page TLB entries. - BP_DEPTH => 1024, # Branch predictor depth. - INSTR_FIFO_DEPTH => 4, # Instruction buffer depth. - STORE_BUFFER_DEPTH => 8, # Store buffer depth. - SYNTHESIS => 1, # Make this to 1 to simulate compile from a synthesis perspective. - - # Testbench configuration. - WAVES => 0, # 1 Enables wave logging. - UART0_TX_TERMINAL => 1, # 1 Enables UART TX terminal 0. 0 disables it. - UART1_TX_TERMINAL => 1, # 1 Enables UART TX terminal 1. 0 disables it. - UART0_RX_TERMINAL => 1, # RX terminal 0. Characters typed go to UART RX. - UART1_RX_TERMINAL => 1, # RX terminal 1. Characters typed go to UART RX. - EXT_RAM_SIZE => 32768, # External RAM size. - SEED => -1, # Seed. Use -1 to use random seed. - DUMP_START => 2000, # Starting memory address from which to dump. - DUMP_SIZE => 200, # Length of dump in bytes. - MAX_CLOCK_CYCLES => 100000, # Clock cycles to run the simulation for. - REG_CHECK => {"r1" => "32'h4", - "r2" => "32'd3"}, # Make this an anonymous has with entries like "r10" => "32'h0" etc. - FINAL_CHECK => {"32'h100" => "32'd4", - "32'h66" => "32'h4"} # Make this an anonymous hash with entries like verilog_address => verilog_value etc. -); - Index: trunk/makefile =================================================================== --- trunk/makefile (revision 57) +++ 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: trunk/README.md =================================================================== --- trunk/README.md (revision 57) +++ 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.