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

Subversion Repositories pss

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /pss/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/pss/hdl/pss_soc_top.v
0,0 → 1,128
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module pss_soc_top
(
input clk_i, rst_i,
 
input rx_i,
output tx_o,
 
input ext_int_i,
 
input [7:0] SW,
output reg [7:0] LED
);
 
wire sync_reset;
 
wire uc_bus_enb;
wire uc_bus_we;
wire [31:0] uc_bus_addr;
wire [31:0] uc_bus_wdata;
reg [31:0] uc_bus_rdata;
reg uc_bus_resp;
 
wire ext_int;
debouncer debouncer
(
.clk_i(clk_i),
.rst_i(rst_i),
 
.in_i(ext_int_i),
.out_o(ext_int)
);
 
wire [3:0] interrupts;
assign interrupts = {3'h0, ext_int};
 
pss
#(
.CPU_PRESENT(1),
.CPU_RESET_DEFAULT(0),
.A31_DEFAULTS(1),
.MEM_DATA("D:/Research/Computer_Science/Projects/Practice/zpu/pss/pss/SW/onboard/Heartbeat/Heartbeat.hex"),
.MEM_SIZE_KB(8)
)
pss
(
.clk_i(clk_i),
.arst_i(rst_i),
.srst_o(sync_reset),
 
.rx_i(rx_i),
.tx_o(tx_o),
 
.INT_i(interrupts),
 
.xport_req_o(uc_bus_enb),
.xport_ack_i(1'b1),
.xport_err_i(1'b0),
.xport_we_o(uc_bus_we),
.xport_addr_bo(uc_bus_addr),
.xport_wdata_bo(uc_bus_wdata),
.xport_resp_i(uc_bus_resp),
.xport_rdata_bi(uc_bus_rdata)
);
 
always @(posedge clk_i)
begin
if (rst_i) uc_bus_rdata <= 32'h0;
else if (uc_bus_addr == 32'h8A000000) uc_bus_rdata <= SW;
else uc_bus_rdata <= uc_bus_addr;
end
 
always @(posedge clk_i)
begin
if (rst_i)
uc_bus_resp <= 1'b0;
else if ( (uc_bus_enb == 1'b1) && (uc_bus_we == 1'b0) )
uc_bus_resp <= 1'b1;
else
uc_bus_resp <= 1'b0;
end
 
always @(posedge clk_i)
begin
if (sync_reset)
LED <= 8'hAA;
else if (uc_bus_we)
LED <= uc_bus_wdata;
end
 
//assign uc_bus_rdata = uc_bus_addr;
 
endmodule
/pss/hdl/pss/udm/uart_rx.v
0,0 → 1,205
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module uart_rx
(
input clk_i, rst_i,
 
input rx_i,
output reg rx_done_tick_o,
output reg [7:0] dout_bo,
 
output reg locked_o,
output reg [28:0] bitperiod_o
);
 
localparam ST_NOSYNC = 4'h0;
localparam ST_NOSYNC_WAIT1_1 = 4'h1;
localparam ST_NOSYNC_WAIT0_2 = 4'h2;
localparam ST_NOSYNC_WAIT1_3 = 4'h3;
localparam ST_NOSYNC_WAIT0_4 = 4'h4;
localparam ST_NOSYNC_WAIT1_5 = 4'h5;
localparam ST_NOSYNC_WAIT0_6 = 4'h6;
localparam ST_NOSYNC_WAIT1_7 = 4'h7;
localparam ST_NOSYNC_WAIT0_8 = 4'h8;
localparam ST_NOSYNC_WAIT_STOP = 4'h9;
localparam ST_SYNC = 4'hA;
localparam ST_SYNC_WAIT_START = 4'hB;
localparam ST_SYNC_RX_DATA = 4'hC;
localparam ST_SYNC_WAIT_STOP = 4'hD;
 
reg [4:0] state;
reg [31:0] clk_counter;
reg [2:0] bit_counter;
 
reg rx_buf;
always @(posedge clk_i)
begin
if (rst_i) rx_buf <= 1'b1;
else rx_buf <= rx_i;
end
 
always @(posedge clk_i)
begin
if (rst_i)
begin
state <= ST_NOSYNC;
clk_counter <= 32'h0;
bit_counter <= 3'h0;
locked_o <= 1'b0;
bitperiod_o <= 32'h0;
rx_done_tick_o <= 1'b0;
dout_bo <= 8'h0;
end
else
begin
 
rx_done_tick_o <= 1'b0;
 
case (state)
 
ST_NOSYNC:
begin
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_1;
end
 
ST_NOSYNC_WAIT1_1:
begin
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_2;
end
 
ST_NOSYNC_WAIT0_2:
begin
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_3;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT1_3:
begin
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_4;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT0_4:
begin
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_5;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT1_5:
begin
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_6;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT0_6:
begin
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT1_7;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT1_7:
begin
if (rx_buf == 1'b1) state <= ST_NOSYNC_WAIT0_8;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT0_8:
begin
if (rx_buf == 1'b0) state <= ST_NOSYNC_WAIT_STOP;
clk_counter <= clk_counter + 32'h1;
end
 
ST_NOSYNC_WAIT_STOP:
begin
if (rx_buf == 1'b1)
begin
state <= ST_SYNC;
locked_o <= 1'b1;
bitperiod_o <= clk_counter[31:3]; // clk_counter / 8
dout_bo <= 32'h55;
rx_done_tick_o <= 1'b1;
end
clk_counter <= clk_counter + 32'h1;
end
 
ST_SYNC:
begin
if (rx_buf == 1'b0)
begin
state <= ST_SYNC_WAIT_START;
clk_counter <= 32'h0;
end
end
 
ST_SYNC_WAIT_START:
begin
clk_counter <= clk_counter + 32'h1;
if (clk_counter == {4'h0, bitperiod_o[28:1]})
begin
state <= ST_SYNC_RX_DATA;
clk_counter <= 32'h0;
bit_counter <= 3'h0;
end
end
 
ST_SYNC_RX_DATA:
begin
clk_counter <= clk_counter + 32'h1;
if (clk_counter == {3'h0, bitperiod_o})
begin
dout_bo <= {rx_buf, dout_bo[7:1]};
clk_counter <= 32'h0;
bit_counter <= bit_counter + 3'h1;
if (bit_counter == 3'h7)
begin
rx_done_tick_o <= 1'b1;
state <= ST_SYNC_WAIT_STOP;
end
end
end
 
ST_SYNC_WAIT_STOP:
begin
if (rx_buf == 1'b1) state <= ST_SYNC;
end
 
endcase
 
end
end
 
endmodule
/pss/hdl/pss/udm/udm.v
0,0 → 1,117
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module udm
(
input clk_i, rst_i,
 
input rx_i,
output tx_o,
 
output rst_o,
output bus_enb_o,
output bus_we_o,
output [31:0] bus_addr_bo,
output [31:0] bus_wdata_bo,
 
input bus_ack_i,
input [31:0] bus_rdata_bi
);
 
wire rx_done_tick;
wire [7:0] rx_data;
wire [7:0] tx_data;
wire tx_start;
wire tx_done_tick;
 
wire locked;
wire [28:0] bitperiod;
 
uart_rx uart_rx
(
.clk_i(clk_i),
.rst_i(rst_i),
 
.rx_i(rx_i),
.rx_done_tick_o(rx_done_tick),
.dout_bo(rx_data),
 
.locked_o(locked),
.bitperiod_o(bitperiod)
);
 
uart_tx uart_tx
(
.clk_i(clk_i),
.rst_i(rst_i),
 
.tx_start_i(tx_start),
.din_bi(tx_data),
 
.locked_i(locked),
.bitperiod_i(bitperiod),
 
.tx_done_tick_o(tx_done_tick),
.tx_o(tx_o)
);
 
 
udm_controller udm_controller
(
.clk_i(clk_i),
.reset_i(rst_i),
 
// uart rx
.rx_done_tick_i(rx_done_tick),
.rx_din_bi(rx_data),
 
// uart tx
.tx_dout_bo(tx_data),
.tx_start_o(tx_start),
.tx_done_tick_i(tx_done_tick),
// bus
.rst_o(rst_o),
.bus_enb_o(bus_enb_o),
.bus_we_o(bus_we_o),
.bus_addr_bo(bus_addr_bo),
.bus_wdata_bo(bus_wdata_bo),
 
.bus_ack_i(bus_ack_i),
.bus_rdata_bi(bus_rdata_bi)
);
 
endmodule
/pss/hdl/pss/udm/uart_tx.v
0,0 → 1,139
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module uart_tx
(
input clk_i, rst_i,
 
input tx_start_i,
input [7:0] din_bi,
 
input locked_i,
input [28:0] bitperiod_i,
 
output reg tx_done_tick_o,
output reg tx_o
);
 
reg [7:0] databuf;
reg [3:0] state;
reg [31:0] clk_counter;
reg [2:0] bit_counter;
 
localparam ST_IDLE = 8'h0;
localparam ST_START = 8'h1;
localparam ST_TX_DATA = 8'h2;
localparam ST_STOP = 8'h3;
 
always @(posedge clk_i)
begin
if (rst_i)
begin
state <= ST_IDLE;
databuf <= 8'h0;
clk_counter <= 32'h0;
tx_o <= 1'b1;
tx_done_tick_o <= 1'b0;
end
else
begin
tx_done_tick_o <= 1'b0;
 
case (state)
 
ST_IDLE:
begin
tx_o <= 1'b1;
if ((tx_start_i == 1'b1) && (locked_i == 1'b1))
begin
tx_o <= 1'b0;
state <= ST_START;
databuf <= din_bi;
clk_counter <= 32'h0;
end
end
 
ST_START:
begin
clk_counter <= clk_counter + 32'h1;
if (clk_counter == {3'h0, bitperiod_i})
begin
state <= ST_TX_DATA;
clk_counter <= 32'h0;
bit_counter <= 3'h0;
tx_o <= databuf[0];
databuf <= {1'b0, databuf[7:1]};
end
end
 
ST_TX_DATA:
begin
clk_counter <= clk_counter + 32'h1;
if (clk_counter == {3'h0, bitperiod_i})
begin
clk_counter <= 32'h0;
bit_counter <= bit_counter + 3'h1;
if (bit_counter == 3'h7)
begin
tx_o <= 1'b1;
state <= ST_STOP;
end
else
begin
tx_o <= databuf[0];
databuf <= {1'b0, databuf[7:1]};
end
end
end
 
ST_STOP:
begin
clk_counter <= clk_counter + 32'h1;
if (clk_counter == {2'h0, bitperiod_i, 1'b0}) // 2 * bit
begin
tx_o <= 1'b1;
tx_done_tick_o <= 1'b1;
state <= ST_IDLE;
end
end
 
endcase
 
end
end
 
endmodule
/pss/hdl/pss/udm/udm_controller.v
0,0 → 1,368
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module udm_controller
(
input clk_i, reset_i,
 
// uart rx
input rx_done_tick_i,
input [7:0] rx_din_bi,
 
// uart tx
output reg [7:0] tx_dout_bo,
output reg tx_start_o,
input tx_done_tick_i,
// bus
output reg rst_o,
output reg bus_enb_o,
output reg bus_we_o,
output reg [31:0] bus_addr_bo,
output reg [31:0] bus_wdata_bo,
 
input bus_ack_i,
input [31:0] bus_rdata_bi
);
 
// control bytes
localparam SYNC_BYTE = 8'h55;
localparam ESCAPE_BYTE = 8'h5a;
 
// commands
localparam IDCODE_CMD = 8'h00; // check udm accessibility
localparam RST_CMD = 8'h80; // Reset slave
localparam WR_INC_CMD = 8'h81; // Write slave with autoincrement
localparam RD_INC_CMD = 8'h82; // Read slave with autoincrement
localparam WR_NOINC_CMD = 8'h83; // Write slave without autoincrement
localparam RD_NOINC_CMD = 8'h84; // Read slave without autoincrement
 
 
reg rx_req, rx_sync;
reg [7:0] r_data;
 
// rx sync logic
reg escape_received;
always @(posedge clk_i)
begin
if (reset_i)
begin
rx_req <= 1'b0;
rx_sync <= 1'b0;
r_data <= 8'hx;
escape_received <= 1'b0;
end
else
begin
rx_req <= 1'b0;
rx_sync <= 1'b0;
r_data <= 8'hx;
 
if (escape_received == 1'b0)
begin
if (rx_done_tick_i == 1'b1)
begin
if (rx_din_bi == SYNC_BYTE)
rx_sync <= 1'b1;
else if (rx_din_bi == ESCAPE_BYTE)
escape_received <= 1'b1;
else
begin
rx_req <= 1'b1;
r_data <= rx_din_bi;
end
end
end
else
begin
if (rx_done_tick_i == 1'b1)
begin
rx_req <= 1'b1;
r_data <= rx_din_bi;
escape_received <= 1'b0;
end
end
end
end
 
// states
localparam IDLE = 8'h00;
localparam FETCH_ADDR = 8'h01;
localparam FETCH_LENGTH = 8'h02;
localparam FETCH_DATA = 8'h03;
localparam WAIT_ACCEPT = 8'h04;
localparam RD_DATA = 8'h05;
localparam TX_DATA = 8'h06;
localparam WAIT_TX = 8'h07;
 
reg [7:0] state;
reg [1:0] counter;
reg cmd_ff, autoinc_ff;
reg [31:0] RD_DATA_reg;
reg [31:0] tr_length;
 
always @(posedge clk_i, posedge reset_i)
begin
if (reset_i == 1'b1)
begin
rst_o <= 1'b0;
 
state <= IDLE;
tx_start_o <= 1'b0;
bus_enb_o <= 1'b0;
bus_we_o <= 1'bx;
bus_addr_bo <= 32'hxxxxxxxx;
bus_wdata_bo <= 32'hxxxxxxxx;
 
end
else
begin
if (rx_sync == 1'b1)
begin
state <= IDLE;
tx_start_o <= 1'b0;
bus_enb_o <= 1'b0;
bus_we_o <= 1'bx;
bus_addr_bo <= 32'hxxxxxxxx;
bus_wdata_bo <= 32'hxxxxxxxx;
tr_length <= 32'h0;
end
 
else
begin
rst_o <= 1'b0;
 
tx_start_o <= 1'b0;
case (state)
IDLE:
begin
if (rx_req)
begin
case (r_data)
IDCODE_CMD:
begin
tx_start_o <= 1'b1;
tx_dout_bo <= SYNC_BYTE;
end
RST_CMD:
begin
rst_o <= 1'b1;
end
WR_INC_CMD:
begin
cmd_ff <= 1'b1;
autoinc_ff <= 1'b1;
state <= FETCH_ADDR;
counter <= 2'b00;
end
RD_INC_CMD:
begin
cmd_ff <= 1'b0;
autoinc_ff <= 1'b1;
state <= FETCH_ADDR;
counter <= 2'b00;
end
WR_NOINC_CMD:
begin
cmd_ff <= 1'b1;
autoinc_ff <= 1'b0;
state <= FETCH_ADDR;
counter <= 2'b00;
end
 
RD_NOINC_CMD:
begin
cmd_ff <= 1'b0;
autoinc_ff <= 1'b0;
state <= FETCH_ADDR;
counter <= 2'b00;
end
 
default:
state <= IDLE;
endcase
end
end
FETCH_ADDR:
begin
if (rx_req)
begin
bus_addr_bo <= {r_data, bus_addr_bo[31:8]};
if (counter == 2'b11)
begin
state <= FETCH_LENGTH;
counter <= 2'b00;
end
else
begin
counter <= counter + 2'b01;
end
end
end
FETCH_LENGTH:
begin
if (rx_req)
begin
tr_length <= {r_data, tr_length[31:8]};
if (counter == 2'b11)
begin
if (cmd_ff == 1'b1)
begin
state <= FETCH_DATA;
counter <= 2'b00;
end
else
begin
bus_enb_o <= 1'b1;
bus_we_o <= 1'b0;
bus_wdata_bo <= 32'hx;
state <= WAIT_ACCEPT;
counter <= 2'b00;
end
end
else
begin
counter <= counter + 2'b01;
end
end
end
 
FETCH_DATA:
begin
if (rx_req)
begin
bus_wdata_bo <= {r_data, bus_wdata_bo[31:8]};
if (counter == 2'b11)
begin
bus_enb_o <= 1'b1;
bus_we_o <= 1'b1;
state <= WAIT_ACCEPT;
end
else
begin
counter <= counter + 2'b01;
end
end
end
WAIT_ACCEPT:
begin
if (bus_ack_i == 1'b1)
begin
bus_enb_o <= 1'b0;
bus_we_o <= 1'bx;
bus_wdata_bo <= 32'hx;
RD_DATA_reg <= bus_rdata_bi;
if (cmd_ff == 1'b0)
begin
state <= TX_DATA;
end
else
begin
if (tr_length == 32'h4) state <= IDLE;
else
begin
if (autoinc_ff == 1'b1) bus_addr_bo <= bus_addr_bo + 32'h4;
state <= FETCH_DATA;
counter <= 2'b00;
end
tr_length <= tr_length - 32'h4;
end
end
end
TX_DATA:
begin
tx_start_o <= 1'b1;
tx_dout_bo <= RD_DATA_reg[7:0];
RD_DATA_reg <= {8'h0, RD_DATA_reg[31:8]};
counter <= 2'b00;
state <= WAIT_TX;
end
 
WAIT_TX:
begin
if (tx_done_tick_i == 1'b1)
begin
if (counter == 2'b11)
begin
if (tr_length == 32'h4) state <= IDLE;
else
begin
if (autoinc_ff == 1'b1) bus_addr_bo <= bus_addr_bo + 32'h4;
bus_enb_o <= 1'b1;
bus_we_o <= 1'b0;
bus_wdata_bo <= 32'hx;
state <= WAIT_ACCEPT;
counter <= 2'b00;
end
tr_length <= tr_length - 32'h4;
end
else
begin
tx_start_o <= 1'b1;
tx_dout_bo <= RD_DATA_reg[7:0];
RD_DATA_reg <= {8'h0, RD_DATA_reg[31:8]};
end
counter <= counter + 2'b01;
end
end
 
default:
begin
state <= IDLE;
end
endcase
end
end
end
 
endmodule
/pss/hdl/pss/zpu_uc/ram/ram.v
0,0 → 1,22
module ram
#(
parameter dat_width=32, adr_width=32, mem_size=1024
)
(
input [dat_width-1:0] dat_i,
input [adr_width-1:0] adr_i,
input we_i,
output reg [dat_width-1:0] dat_o,
input clk
);
 
reg [dat_width-1:0] ram [0:mem_size - 1] /* synthesis ram_style = no_rw_check */;
always @ (posedge clk)
begin
dat_o <= ram[adr_i];
if (we_i)
ram[adr_i] <= dat_i;
end
 
endmodule // ram
/pss/hdl/pss/zpu_uc/ram/ram_dual.v
0,0 → 1,42
module ram_dual
#(
parameter mem_data="data.hex", dat_width=32, adr_width=32, mem_size=1024
)
(
input [dat_width-1:0] dat0_i,
input [adr_width-1:0] adr0_i,
input we0_i,
output reg [dat_width-1:0] dat0_o,
 
input [dat_width-1:0] dat1_i,
input [adr_width-1:0] adr1_i,
input we1_i,
output reg [dat_width-1:0] dat1_o,
 
input clk
);
 
//(* ram_style="block" *)
reg [dat_width-1:0] ram [0:mem_size - 1] ;
always @ (posedge clk)
begin
dat0_o <= ram[adr0_i];
if (we0_i)
ram[adr0_i] <= dat0_i;
end
 
always @ (posedge clk)
begin
dat1_o <= ram[adr1_i];
if (we1_i)
ram[adr1_i] <= dat1_i;
end
 
initial
begin
$readmemh(mem_data, ram, 0) ;
end
 
 
endmodule // ram
/pss/hdl/pss/zpu_uc/zpu_uc_systemcontroller.v
0,0 → 1,736
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module ZPU_uC_SystemController
#(
parameter A31_DEFAULTS = 1,
parameter CPU_RESET_DEFAULT = 1,
parameter MEM_SIZE_KB = 1
)
(
input clk_i,
input rst_i,
 
//// Masters ////
// Debug bus //
input dbg_enb_i,
input dbg_we_i,
input [31:0] dbg_addr_bi,
input [31:0] dbg_wdata_bi,
output dbg_ack_o,
output reg [31:0] dbg_rdata_bo,
 
// ZPU bus //
input cpu_enb_i,
input cpu_we_i,
input [31:0] cpu_wdata_bi,
input [31:0] cpu_addr_bi,
input [3:0] cpu_writemask_bi,
output cpu_ack_o,
output reg [31:0] cpu_rdata_bo,
 
//// Slaves ////
// RAM0 bus //
output reg [31:0] ram0_addr_bo,
output reg ram0_we_o,
output reg [31:0] ram0_wdata_bo,
input [31:0] ram0_rdata_bi,
 
// RAM1 bus //
output reg [31:0] ram1_addr_bo,
output reg ram1_we_o,
output reg [31:0] ram1_wdata_bo,
input [31:0] ram1_rdata_bi,
 
// Expansion bus //
output reg xport_req_o,
input xport_ack_i,
input xport_err_i,
output reg xport_we_o,
output reg [31:0] xport_addr_bo,
output reg [31:0] xport_wdata_bo,
input xport_resp_i,
input [31:0] xport_rdata_bi,
 
// INTC bus //
input wire intc_ie_i,
output reg intc_ie_we_o,
output reg intc_ie_data_o,
output reg [7:0] intc_mask_bo,
input wire [7:0] intc_pending_bi,
output reg intc_clr_cmd_o,
output reg [7:0] intc_clr_code_bo,
 
input cpu_present,
input [31:0] cpu_pc_bi,
input cpu_break_i,
output reg cpu_reset_o,
output cpu_enb_o,
 
output wire bus_error_int_o,
output reg trap_int_o,
output reg sgi_int_o,
output reg dma_int_o
);
 
 
//// System registers ////
localparam REG_CPU_CONTROL_ADDR = 8'h00;
localparam REG_CPU_PC_ADDR = 8'h04;
localparam REG_CPU_A31 = 8'h08;
localparam REG_DBG_A31 = 8'h0C;
 
localparam REG_INTC_CONTROL_ADDR = 8'h10;
localparam REG_INTC_MASK_ADDR = 8'h14;
localparam REG_INTC_REQ_ADDR = 8'h18;
localparam REG_MEM_SIZE_KB = 8'h1C;
 
localparam REG_DMA_CONTROL_ADDR = 8'h20;
localparam REG_DMA_SOURCEADDR_ADDR = 8'h24;
localparam REG_DMA_DESTADDR_ADDR = 8'h28;
localparam REG_DMA_SIZE_ADDR = 8'h2C;
 
localparam REG_SGI_ADDR = 8'h30;
 
localparam REG_BUS_ERROR_ADDR_ADDR = 8'h38;
localparam REG_BUS_ERROR_PC_ADDR = 8'h3C;
 
localparam REG_TRAP_CONTROL_ADDR = 8'h40;
localparam REG_TRAP_ADDR_ADDR = 8'h44;
 
reg trap_enable;
reg [31:0] trap_addr;
 
reg [31:0] bus_error_addr;
reg [31:0] bus_error_pc;
 
reg dbg_a31, cpu_a31;
 
reg dbg_ram_req, dbg_ext_req, dbg_sys_req, cpu_ram_req, cpu_ext_req, cpu_sys_req;
reg dbg_ram_ack, dbg_sys_ack, cpu_ram_ack, cpu_sys_ack;
reg cpu_err_req, cpu_err_ack;
reg dbg_ext_ack, cpu_ext_ack;
 
assign dbg_ack_o = dbg_ram_ack | dbg_ext_ack | dbg_sys_ack;
assign cpu_ack_o = cpu_ram_ack | cpu_ext_ack | cpu_sys_ack | cpu_err_ack;
 
wire dbg_ram_pending, cpu_ram_pending, dbg_sys_pending, cpu_sys_pending, dbg_ext_pending, cpu_ext_pending;
assign dbg_ram_pending = dbg_ram_req & (~dbg_ram_ack);
assign cpu_ram_pending = cpu_ram_req & (~cpu_ram_ack);
assign dbg_sys_pending = dbg_sys_req & (~dbg_sys_ack);
assign cpu_sys_pending = cpu_sys_req & (~cpu_sys_ack);
assign dbg_ext_pending = dbg_ext_req & (~dbg_ext_ack);
assign cpu_ext_pending = cpu_ext_req & (~cpu_ext_ack);
 
reg [31:0] sys_rdata;
 
reg [2:0] DMA_state;
 
assign cpu_enb_o = 1'b1;
 
 
reg [31:0] REG_DMA_SOURCEADDR;
reg [31:0] REG_DMA_DESTADDR;
reg [31:0] REG_DMA_SIZE;
 
reg dma_req;
reg dma_cmd, dma_autoinc;
reg [31:0] dma_sourceaddr;
reg [31:0] dma_destaddr;
reg [31:0] dma_size, dma_size_aux;
 
reg dma_ext_req_o;
reg dma_ext_ack_i;
reg dma_ext_we_o;
reg [31:0] dma_ext_addr_bo;
reg [31:0] dma_ext_wdata_bo;
reg dma_ext_resp_i;
reg [31:0] dma_ext_rdata_bi;
////////
 
localparam DMA_IDLE = 3'h0;
localparam DMA_WAIT = 3'h1;
localparam DMA_PRESTART = 3'h2;
localparam DMA_WORK = 3'h3;
localparam DMA_LOAD = 3'h4;
localparam DMA_STORE = 3'h5;
 
always @*
begin
dbg_ram_req = 1'b0;
dbg_ext_req = 1'b0;
dbg_sys_req = 1'b0;
cpu_ram_req = 1'b0;
cpu_ext_req = 1'b0;
cpu_sys_req = 1'b0;
cpu_err_req = 1'b0;
 
if (dbg_enb_i == 1'b1)
begin
if (dbg_addr_bi[31:10] < MEM_SIZE_KB)
dbg_ram_req = 1'b1;
else if (dbg_addr_bi[31:16] == 16'h4000)
dbg_sys_req = 1'b1;
else if (dbg_addr_bi[31] == 1'b1)
dbg_ext_req = 1'b1;
end
 
if (cpu_enb_i == 1'b1)
begin
if (cpu_addr_bi[31:10] < MEM_SIZE_KB)
cpu_ram_req = 1'b1;
else if (cpu_addr_bi[31:16] == 16'h4000)
cpu_sys_req = 1'b1;
else if (cpu_addr_bi[31] == 1'b1)
cpu_ext_req = 1'b1;
else
cpu_err_req = 1'b1;
end
end
 
// System access
reg [31:0] sys_acc_addr;
reg [31:0] sys_acc_wdata;
reg sys_acc_we;
 
always @*
begin
if ((dbg_sys_req == 1'b1) && (dbg_sys_ack != 1'b1))
begin
sys_acc_addr = dbg_addr_bi;
sys_acc_wdata = dbg_wdata_bi;
sys_acc_we = dbg_we_i;
end
else if ((cpu_sys_req == 1'b1) && (cpu_sys_ack != 1'b1))
begin
sys_acc_addr = cpu_addr_bi;
sys_acc_wdata = cpu_wdata_bi;
sys_acc_we = cpu_we_i;
end
else
begin
sys_acc_addr = 32'h0;
sys_acc_wdata = 32'h0;
sys_acc_we = 1'b0;
end
end
 
always @(posedge clk_i)
begin
if (rst_i)
begin
 
cpu_reset_o <= CPU_RESET_DEFAULT;
cpu_a31 <= A31_DEFAULTS;
dbg_a31 <= A31_DEFAULTS;
 
dbg_sys_ack <= 1'b0;
cpu_sys_ack <= 1'b0;
 
trap_enable <= 1'b0;
trap_addr <= 32'h0;
 
sgi_int_o <= 1'b0;
 
dma_req <= 1'b0;
dma_cmd <= 1'b0;
dma_autoinc <= 1'b0;
 
intc_ie_we_o <= 1'b0;
intc_ie_data_o <= 1'bx;
intc_mask_bo <= 8'h0;
intc_clr_cmd_o <= 1'b0;
intc_clr_code_bo <= 8'hx;
 
REG_DMA_SOURCEADDR <= 32'h0;
REG_DMA_DESTADDR <= 32'h0;
REG_DMA_SIZE <= 32'h0;
end
else
begin
dbg_sys_ack <= 1'b0;
cpu_sys_ack <= 1'b0;
 
sgi_int_o <= 1'b0;
 
intc_ie_we_o <= 1'b0;
intc_clr_cmd_o <= 1'b0;
sys_rdata <= 32'hx;
 
dma_req <= 1'b0;
 
if (dbg_sys_pending == 1'b1) dbg_sys_ack <= 1'b1;
if (cpu_sys_pending == 1'b1) cpu_sys_ack <= 1'b1;
 
if (sys_acc_we == 1'b0)
case (sys_acc_addr[7:0])
REG_CPU_CONTROL_ADDR: sys_rdata <= {cpu_present, 29'h0, cpu_break_i, cpu_reset_o};
REG_CPU_PC_ADDR: sys_rdata <= cpu_pc_bi;
REG_CPU_A31: sys_rdata <= {31'h0, cpu_a31};
REG_DBG_A31: sys_rdata <= {31'h0, dbg_a31};
 
REG_INTC_CONTROL_ADDR: sys_rdata <= {31'h0, intc_ie_i};
REG_INTC_MASK_ADDR: sys_rdata <= {24'h0, intc_mask_bo};
REG_INTC_REQ_ADDR: sys_rdata <= {24'h0, intc_pending_bi};
REG_MEM_SIZE_KB: sys_rdata <= MEM_SIZE_KB;
 
REG_DMA_SOURCEADDR_ADDR: sys_rdata <= REG_DMA_SOURCEADDR;
REG_DMA_DESTADDR_ADDR: sys_rdata <= REG_DMA_DESTADDR;
REG_DMA_SIZE_ADDR: sys_rdata <= REG_DMA_SIZE;
 
REG_TRAP_CONTROL_ADDR: sys_rdata <= {31'h0, trap_enable};
REG_TRAP_ADDR_ADDR: sys_rdata <= trap_addr;
 
REG_BUS_ERROR_ADDR_ADDR: sys_rdata <= bus_error_addr;
REG_BUS_ERROR_PC_ADDR: sys_rdata <= bus_error_pc;
endcase
else
case (sys_acc_addr[7:0])
REG_CPU_CONTROL_ADDR: cpu_reset_o <= sys_acc_wdata[0];
REG_CPU_A31: cpu_a31 <= sys_acc_wdata[0];
REG_DBG_A31: dbg_a31 <= sys_acc_wdata[0];
 
REG_INTC_CONTROL_ADDR: begin intc_ie_we_o <= 1'b1; intc_ie_data_o <= sys_acc_wdata[0]; end
REG_INTC_MASK_ADDR: intc_mask_bo <= sys_acc_wdata[7:0];
REG_INTC_REQ_ADDR: begin intc_clr_cmd_o <= 1'b1; intc_clr_code_bo <= sys_acc_wdata[7:0]; end
 
REG_DMA_CONTROL_ADDR: begin dma_req <= 1'b1; dma_cmd <= sys_acc_wdata[1]; dma_autoinc <= sys_acc_wdata[2]; end
REG_DMA_SOURCEADDR_ADDR: begin
if (dbg_sys_req == 1'b1)
begin
if (sys_acc_wdata[31] == 1'b1)
REG_DMA_SOURCEADDR <= {dbg_a31, sys_acc_wdata[30:0]};
else
REG_DMA_SOURCEADDR <= sys_acc_wdata;
end
else
begin
if (sys_acc_wdata[31] == 1'b1)
REG_DMA_SOURCEADDR <= {cpu_a31, sys_acc_wdata[30:0]};
else
REG_DMA_SOURCEADDR <= sys_acc_wdata;
end
end
REG_DMA_DESTADDR_ADDR: begin
if (dbg_sys_pending == 1'b1) // dbg access
begin
if (dbg_addr_bi[31] == 1'b1) // dbg xport access
REG_DMA_DESTADDR <= {dbg_a31, sys_acc_wdata[30:0]};
else
REG_DMA_DESTADDR <= sys_acc_wdata;
end
else // cpu access
begin
if (cpu_addr_bi[31] == 1'b1) // cpu xport access
REG_DMA_DESTADDR <= {cpu_a31, sys_acc_wdata[30:0]};
else
REG_DMA_DESTADDR <= sys_acc_wdata;
end
end
REG_DMA_SIZE_ADDR: REG_DMA_SIZE <= sys_acc_wdata;
REG_SGI_ADDR: sgi_int_o <= 1'b1;
 
REG_TRAP_CONTROL_ADDR: trap_enable <= sys_acc_wdata[0];
REG_TRAP_ADDR_ADDR: trap_addr <= sys_acc_wdata;
endcase
end
end
 
 
// trap logic
always @(posedge clk_i)
begin
if (rst_i)
trap_int_o <= 1'b0;
else
begin
trap_int_o <= 1'b0;
if (trap_enable == 1'b1)
if (cpu_enb_i == 1'b1)
if (cpu_addr_bi == trap_addr)
trap_int_o <= 1'b1;
end
end
 
 
// bus error logic
always @(posedge clk_i)
begin
if (rst_i)
begin
cpu_err_ack <= 1'b0;
bus_error_pc <= 32'h0;
bus_error_addr <= 32'h0;
end
else
begin
cpu_err_ack <= (cpu_err_req | xport_err_i) & (~cpu_err_ack);
if (cpu_err_ack == 1'b1)
begin
bus_error_addr <= cpu_addr_bi;
bus_error_pc <= cpu_pc_bi;
end
end
end
 
assign bus_error_int_o = cpu_err_ack;
 
 
// RAM0 access
always @*
begin
ram0_addr_bo = 32'hx;
ram0_we_o = 1'b0;
ram0_wdata_bo = 32'hx;
if (dbg_ram_pending == 1'b1)
begin
ram0_addr_bo = dbg_addr_bi;
ram0_we_o = dbg_we_i;
ram0_wdata_bo = dbg_wdata_bi;
end
else if (cpu_ram_pending == 1'b1)
begin
ram0_addr_bo = cpu_addr_bi;
ram0_we_o = cpu_we_i;
ram0_wdata_bo = cpu_wdata_bi;
end
end
 
always @(posedge clk_i)
begin
if (rst_i)
begin
dbg_ram_ack <= 1'b0;
cpu_ram_ack <= 1'b0;
end
else
begin
dbg_ram_ack <= 1'b0;
cpu_ram_ack <= 1'b0;
if (dbg_ram_pending == 1'b1)
dbg_ram_ack <= 1'b1;
else if (cpu_ram_pending == 1'b1)
cpu_ram_ack <= 1'b1;
end
end
 
always @*
begin
dbg_rdata_bo = 32'hx;
cpu_rdata_bo = 32'hx;
if (dbg_ram_ack == 1'b1)
dbg_rdata_bo = ram0_rdata_bi;
if (cpu_ram_ack == 1'b1)
cpu_rdata_bo = ram0_rdata_bi;
if (dbg_ext_ack == 1'b1)
dbg_rdata_bo = xport_rdata_bi;
if (cpu_ext_ack == 1'b1)
cpu_rdata_bo = xport_rdata_bi;
if (dbg_sys_ack == 1'b1)
dbg_rdata_bo = sys_rdata;
if (cpu_sys_ack == 1'b1)
cpu_rdata_bo = sys_rdata;
end
 
 
// bus conversion logic
reg dbg_rd_acknowledged, cpu_rd_acknowledged;
 
always @(posedge clk_i)
begin
if (rst_i)
begin
dbg_rd_acknowledged <= 1'b0;
cpu_rd_acknowledged <= 1'b0;
end
else
begin
if ((DMA_state == DMA_IDLE) || (DMA_state == DMA_WAIT))
begin
if ((dbg_rd_acknowledged == 1'b0) && (cpu_rd_acknowledged == 1'b0)) // no acknowledged transactions
begin
if ((dbg_ext_pending == 1'b1) && (dbg_we_i == 1'b0) && (xport_ack_i == 1'b1)) dbg_rd_acknowledged <= 1'b1;
else if ((cpu_ext_pending == 1'b1) && (cpu_we_i == 1'b0) && (xport_ack_i == 1'b1)) cpu_rd_acknowledged <= 1'b1;
end
else if (dbg_rd_acknowledged == 1'b1) // dbg read in progress
begin
if (xport_resp_i == 1'b1) dbg_rd_acknowledged <= 1'b0;
end
else if (cpu_rd_acknowledged == 1'b1) // cpu read in progress
begin
if (xport_resp_i == 1'b1) cpu_rd_acknowledged <= 1'b0;
end
end
end
end
 
 
// bus switch
always @*
begin
 
xport_req_o = 1'b0;
xport_we_o = 1'bx;
xport_addr_bo = 32'hx;
xport_wdata_bo = 32'hx;
 
dbg_ext_ack = 1'b0;
cpu_ext_ack = 1'b0;
 
dma_ext_ack_i = 1'b0;
dma_ext_rdata_bi = 32'hx;
dma_ext_resp_i = 1'b0;
 
if ((DMA_state == DMA_IDLE) || (DMA_state == DMA_WAIT))
begin
 
if ((dbg_rd_acknowledged == 1'b0) && (cpu_rd_acknowledged == 1'b0))
begin
if (dbg_ext_req == 1'b1)
begin
xport_req_o = 1'b1;
xport_we_o = dbg_we_i;
xport_addr_bo = {dbg_a31, dbg_addr_bi[30:0]};
xport_wdata_bo = dbg_wdata_bi;
if (dbg_we_i == 1'b1)
dbg_ext_ack = xport_ack_i;
else
dbg_ext_ack = 1'b0;
end
else if (cpu_ext_req == 1'b1)
begin
xport_req_o = 1'b1;
xport_we_o = cpu_we_i;
xport_addr_bo = {cpu_a31, cpu_addr_bi[30:0]};
xport_wdata_bo = cpu_wdata_bi;
if (cpu_we_i == 1'b1)
cpu_ext_ack = xport_ack_i;
else
cpu_ext_ack = 1'b0;
end
end
 
else if (dbg_rd_acknowledged == 1'b1)
dbg_ext_ack = xport_resp_i;
else if (cpu_rd_acknowledged == 1'b1)
cpu_ext_ack = xport_resp_i;
end
 
else
begin
xport_req_o = dma_ext_req_o;
dma_ext_ack_i = xport_ack_i;
xport_we_o = dma_ext_we_o;
xport_addr_bo = dma_ext_addr_bo;
xport_wdata_bo = dma_ext_wdata_bo;
dma_ext_rdata_bi = xport_rdata_bi;
dma_ext_resp_i = xport_resp_i;
end
end
 
// DMA data logic
reg [31:0] ram1_addr, ram1_addr_shadow;
 
always @*
begin
if (DMA_state != DMA_LOAD)
ram1_addr_bo = ram1_addr;
else if (dma_ext_ack_i == 1'b1)
ram1_addr_bo = ram1_addr;
else
ram1_addr_bo = ram1_addr_shadow;
end
 
always @(posedge clk_i)
begin
if (rst_i)
ram1_addr_shadow <= 32'h0;
else if (dma_ext_ack_i == 1'b1)
ram1_addr_shadow <= ram1_addr;
end
 
always @*
begin
dma_ext_req_o = 1'b0;
dma_ext_we_o = 1'b0;
dma_ext_addr_bo = 32'hx;
dma_ext_wdata_bo = 32'hx;
 
ram1_addr = dma_sourceaddr;
ram1_we_o = 1'b0;
ram1_wdata_bo = 32'hx;
 
if (DMA_state == DMA_LOAD)
begin
if (dma_size != 32'h0)
begin
dma_ext_req_o = 1'b1;
dma_ext_we_o = 1'b0;
dma_ext_addr_bo = dma_sourceaddr;
dma_ext_wdata_bo = 32'hx;
end
 
if (dma_size_aux != 32'h0)
begin
ram1_addr = dma_destaddr;
ram1_we_o = dma_ext_resp_i;
ram1_wdata_bo = dma_ext_rdata_bi;
end
end
 
else if (DMA_state == DMA_STORE)
begin
if (dma_size != 32'h0)
begin
dma_ext_req_o = 1'b1;
dma_ext_we_o = 1'b1;
dma_ext_addr_bo = dma_destaddr;
dma_ext_wdata_bo = ram1_rdata_bi;
end
 
end
 
end
 
// DMA control logic
always @(posedge clk_i)
begin
if (rst_i)
begin
DMA_state <= DMA_IDLE;
dma_sourceaddr <= 32'h0;
dma_destaddr <= 32'h0;
dma_size <= 32'h0;
dma_int_o <= 1'b0;
end
else
begin
 
dma_int_o <= 1'b0;
 
case (DMA_state)
DMA_IDLE:
begin
if (dma_req)
begin
dma_size <= REG_DMA_SIZE;
dma_size_aux <= REG_DMA_SIZE;
dma_sourceaddr <= REG_DMA_SOURCEADDR;
dma_destaddr <= REG_DMA_DESTADDR;
 
DMA_state <= DMA_WAIT;
 
/*
if ( (dbg_ext_pending == 1'b1) || (cpu_ext_pending == 1'b1) ) // pending requests
DMA_state <= DMA_WAIT;
else if (dma_cmd)
DMA_state <= DMA_STORE;
else
DMA_state <= DMA_LOAD;
*/
end
end
DMA_WAIT:
begin
if ( !((dbg_ext_pending == 1'b1) || (cpu_ext_pending == 1'b1)) ) // no pending requests
if (dma_cmd)
begin
dma_sourceaddr <= dma_sourceaddr + 32'h4;
DMA_state <= DMA_STORE;
end
else
DMA_state <= DMA_LOAD;
end
DMA_STORE:
begin
if (xport_ack_i == 1'b1)
if (dma_size == 32'h4)
begin
DMA_state <= DMA_IDLE;
dma_int_o <= 1'b1;
end
else
begin
dma_size <= dma_size - 32'h4;
dma_sourceaddr <= dma_sourceaddr + 32'h4;
if (dma_autoinc == 1'b1) dma_destaddr <= dma_destaddr + 32'h4;
end
end
DMA_LOAD:
begin
if ( (xport_ack_i == 1'b1) && (dma_size != 32'h0) )
begin
if (dma_autoinc == 1'b1) dma_sourceaddr <= dma_sourceaddr + 32'h4;
dma_size <= dma_size - 32'h4;
end
 
if ( (xport_resp_i == 1'b1) && (dma_size_aux != 32'h0) )
begin
dma_destaddr <= dma_destaddr + 32'h4;
dma_size_aux <= dma_size_aux - 32'h4;
end
 
if ( (dma_size == 32'h0) && (dma_size_aux == 32'h0) )
begin
DMA_state <= DMA_IDLE;
dma_int_o <= 1'b1;
end
 
end
default:
DMA_state <= DMA_IDLE;
 
endcase
end
end
 
endmodule
/pss/hdl/pss/zpu_uc/int_controller.v
0,0 → 1,109
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module int_controller
(
input clk_i, rst_i,
 
input [7:0] interrupt_bi,
 
// control interface
output ie_o,
input ie_we_i,
input ie_data_i,
input [7:0] mask_bi,
output [7:0] pending_bo,
input clr_cmd_i,
input [7:0] clr_code_bi,
 
// cpu interface
output reg cpu_req_o,
input cpu_ack_i
);
 
reg [7:0] int_req, int_req_next;
reg IE;
 
wire [7:0] interrupt_masked;
assign interrupt_masked = interrupt_bi & mask_bi;
assign pending_bo = int_req;
assign ie_o = IE;
 
 
always @*
begin
// default
int_req_next = int_req;
// deasserting from cpu
if (clr_cmd_i == 1'b1) int_req_next = int_req_next & ~clr_code_bi;
// asserting from external interrupts
int_req_next = int_req_next | interrupt_masked;
end
 
always @(posedge clk_i)
begin
if (rst_i)
int_req <= 8'h0;
else
int_req <= int_req_next;
end
 
 
always @(posedge clk_i)
begin
if (rst_i)
begin
IE <= 1'b0;
cpu_req_o <= 1'b0;
end
else
begin
if (ie_we_i == 1'b1)
IE <= ie_data_i;
 
if ((IE == 1'b1) && (int_req != 8'h0))
begin
cpu_req_o <= 1'b1;
IE <= 1'b0;
end
else if (cpu_ack_i == 1'b1)
cpu_req_o <= 1'b0;
 
end
end
endmodule
/pss/hdl/pss/zpu_uc/edge_detector.v
0,0 → 1,77
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module edge_detector
(
input clk_i, rst_i,
 
input in,
output reg out
);
 
reg edge_inv;
reg inbuf0, inbuf1, inbuf2;
 
always @(posedge in, posedge rst_i)
begin
if (rst_i)
edge_inv <= 1'b0;
else
edge_inv <= ~edge_inv;
end
 
always @(posedge clk_i)
begin
if (rst_i)
begin
inbuf0 <= 1'b0;
inbuf1 <= 1'b0;
inbuf2 <= 1'b0;
out <= 1'b0;
end
else
begin
inbuf0 <= edge_inv;
inbuf1 <= inbuf0;
inbuf2 <= inbuf1;
if (inbuf1 != inbuf2)
out <= 1'b1;
else
out <= 1'b0;
end
end
 
endmodule
/pss/hdl/pss/zpu_uc/zpu_core/zpupkg.vhd
0,0 → 1,208
-- ZPU
--
-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
 
library work;
use work.zpu_config.all;
 
 
package zpupkg is
 
-- This bit is set for read/writes to IO
-- FIX!!! eventually this should be set to wordSize-1 so as to
-- to make the address of IO independent of amount of memory
-- reserved for CPU. Requires trivial tweaks in toolchain/runtime
-- libraries.
constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
constant maxAddrBit : integer := maxAddrBitIncIO-1;
constant ioBit : integer := maxAddrBit+1;
constant wordSize : integer := 2**wordPower;
constant wordBytes : integer := wordSize/8;
constant minAddrBit : integer := byteBits;
-- configurable internal stack size. Probably going to be 16 after toolchain is done
constant stack_bits : integer := 5;
constant stack_size : integer := 2**stack_bits;
 
component dualport_ram is
port (clk : in std_logic;
memAWriteEnable : in std_logic;
memAAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
memAWrite : in std_logic_vector(wordSize-1 downto 0);
memARead : out std_logic_vector(wordSize-1 downto 0);
memBWriteEnable : in std_logic;
memBAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
memBWrite : in std_logic_vector(wordSize-1 downto 0);
memBRead : out std_logic_vector(wordSize-1 downto 0));
end component;
 
component dram is
port (clk : in std_logic;
areset : in std_logic;
mem_writeEnable : in std_logic;
mem_readEnable : in std_logic;
mem_addr : in std_logic_vector(maxAddrBit downto 0);
mem_write : in std_logic_vector(wordSize-1 downto 0);
mem_read : out std_logic_vector(wordSize-1 downto 0);
mem_busy : out std_logic;
mem_writeMask : in std_logic_vector(wordBytes-1 downto 0));
end component;
 
 
component trace is
port(
clk : in std_logic;
begin_inst : in std_logic;
pc : in std_logic_vector(maxAddrBitIncIO downto 0);
opcode : in std_logic_vector(7 downto 0);
sp : in std_logic_vector(maxAddrBitIncIO downto minAddrBit);
memA : in std_logic_vector(wordSize-1 downto 0);
memB : in std_logic_vector(wordSize-1 downto 0);
busy : in std_logic;
intSp : in std_logic_vector(stack_bits-1 downto 0)
);
end component;
 
component zpu_core is
generic (stack_address : integer := 1016);
port ( clk : in std_logic;
sreset : in std_logic;
enable : in std_logic;
pc_bo : out std_logic_vector(31 downto 0);
 
mem_req : out std_logic;
mem_we : out std_logic;
mem_ack : in std_logic;
mem_read : in std_logic_vector(wordSize-1 downto 0);
mem_write : out std_logic_vector(wordSize-1 downto 0);
out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
interrupt : in std_logic;
interrupt_ack : out std_logic;
break_o : out std_logic;
zpu_status : out std_logic_vector(63 downto 0));
end component;
 
 
component timer is
port(
clk : in std_logic;
areset : in std_logic;
sample : in std_logic;
reset : in std_logic;
counter : out std_logic_vector(63 downto 0));
end component;
 
component zpuio is
port ( areset : in std_logic;
cpu_clk : in std_logic;
clk_status : in std_logic_vector(2 downto 0);
cpu_din : in std_logic_vector(15 downto 0);
cpu_a : in std_logic_vector(20 downto 0);
cpu_we : in std_logic_vector(1 downto 0);
cpu_re : in std_logic;
cpu_dout : inout std_logic_vector(15 downto 0));
end component;
 
 
 
-- opcode decode constants
constant OpCode_Im : std_logic_vector(7 downto 7) := "1";
constant OpCode_StoreSP : std_logic_vector(7 downto 5) := "010";
constant OpCode_LoadSP : std_logic_vector(7 downto 5) := "011";
constant OpCode_Emulate : std_logic_vector(7 downto 5) := "001";
constant OpCode_AddSP : std_logic_vector(7 downto 4) := "0001";
constant OpCode_Short : std_logic_vector(7 downto 4) := "0000";
constant OpCode_Break : std_logic_vector(3 downto 0) := "0000";
constant OpCode_Shiftleft: std_logic_vector(3 downto 0) := "0001";
constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010";
constant OpCode_PushInt : std_logic_vector(3 downto 0) := "0011";
constant OpCode_PopPC : std_logic_vector(3 downto 0) := "0100";
constant OpCode_Add : std_logic_vector(3 downto 0) := "0101";
constant OpCode_And : std_logic_vector(3 downto 0) := "0110";
constant OpCode_Or : std_logic_vector(3 downto 0) := "0111";
constant OpCode_Load : std_logic_vector(3 downto 0) := "1000";
constant OpCode_Not : std_logic_vector(3 downto 0) := "1001";
constant OpCode_Flip : std_logic_vector(3 downto 0) := "1010";
constant OpCode_Nop : std_logic_vector(3 downto 0) := "1011";
constant OpCode_Store : std_logic_vector(3 downto 0) := "1100";
constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101";
constant OpCode_Compare : std_logic_vector(3 downto 0) := "1110";
constant OpCode_PopInt : std_logic_vector(3 downto 0) := "1111";
constant OpCode_Lessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(36, 6);
constant OpCode_Lessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(37, 6);
constant OpCode_Ulessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(38, 6);
constant OpCode_Ulessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(39, 6);
 
constant OpCode_Swap : std_logic_vector(5 downto 0) := conv_std_logic_vector(40, 6);
constant OpCode_Mult : std_logic_vector(5 downto 0) := conv_std_logic_vector(41, 6);
constant OpCode_Lshiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(42, 6);
constant OpCode_Ashiftleft : std_logic_vector(5 downto 0) := conv_std_logic_vector(43, 6);
constant OpCode_Ashiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(44, 6);
constant OpCode_Call : std_logic_vector(5 downto 0) := conv_std_logic_vector(45, 6);
 
constant OpCode_Eq : std_logic_vector(5 downto 0) := conv_std_logic_vector(46, 6);
constant OpCode_Neq : std_logic_vector(5 downto 0) := conv_std_logic_vector(47, 6);
 
constant OpCode_Sub : std_logic_vector(5 downto 0) := conv_std_logic_vector(49, 6);
constant OpCode_Loadb : std_logic_vector(5 downto 0) := conv_std_logic_vector(51, 6);
constant OpCode_Storeb : std_logic_vector(5 downto 0) := conv_std_logic_vector(52, 6);
 
constant OpCode_Eqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(55, 6);
constant OpCode_Neqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(56, 6);
constant OpCode_Poppcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(57, 6);
 
constant OpCode_Pushspadd : std_logic_vector(5 downto 0) := conv_std_logic_vector(61, 6);
constant OpCode_Mult16x16 : std_logic_vector(5 downto 0) := conv_std_logic_vector(62, 6);
constant OpCode_Callpcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(63, 6);
 
 
constant OpCode_Size : integer := 8;
 
 
end zpupkg;
/pss/hdl/pss/zpu_uc/zpu_core/zpu_config.vhd
0,0 → 1,55
-- ZPU
--
-- Copyright 2004-2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
package zpu_config is
-- generate trace output or not.
constant Generate_Trace : boolean := false;
constant wordPower : integer := 5;
-- during simulation, set this to '0' to get matching trace.txt
constant DontCareValue : std_logic := '0';
-- Clock frequency in MHz.
constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"40";
-- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
constant maxAddrBitIncIO : integer := 31;
-- start byte address of stack.
-- point to top of RAM - 2*words
-- constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) := x"00001ff8";
end zpu_config;
/pss/hdl/pss/zpu_uc/zpu_core/zpu_core.vhd
0,0 → 1,1013
-- ZPU
--
 
 
--
-- The FreeBSD license
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions
-- are met:
--
-- 1. Redistributions of source code must retain the above copyright
-- notice, this list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above
-- copyright notice, this list of conditions and the following
-- disclaimer in the documentation and/or other materials
-- provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE ZPU PROJECT ``AS IS'' AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-- ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-- The views and conclusions contained in the software and documentation
-- are those of the authors and should not be interpreted as representing
-- official policies, either expressed or implied, of the ZPU Project.
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use ieee.numeric_std.all;
 
library work;
use work.zpu_config.all;
use work.zpupkg.all;
 
 
-- mem_writeEnable - set to '1' for a single cycle to send off a write request.
-- mem_write is valid only while mem_writeEnable='1'.
-- mem_readEnable - set to '1' for a single cycle to send off a read request.
--
-- mem_busy - It is illegal to send off a read/write request when mem_busy='1'.
-- Set to '0' when mem_read is valid after a read request.
-- If it goes to '1'(busy), it is on the cycle after mem_read/writeEnable
-- is '1'.
-- mem_addr - address for read/write request
-- mem_read - read data. Valid only on the cycle after mem_busy='0' after
-- mem_readEnable='1' for a single cycle.
-- mem_write - data to write
-- mem_writeMask - set to '1' for those bits that are to be written to memory upon
-- write request
-- break - set to '1' when CPU hits break instruction
-- interrupt - set to '1' until interrupts are cleared by CPU.
 
 
 
entity zpu_core is
generic (
stack_address : integer := 1016
);
Port ( clk : in std_logic;
sreset : in std_logic;
enable : in std_logic;
cpu_present : out std_logic;
pc_bo : out std_logic_vector(31 downto 0);
 
mem_req : out std_logic;
mem_we : out std_logic;
mem_ack : in std_logic;
mem_read : in std_logic_vector(wordSize-1 downto 0);
mem_write : out std_logic_vector(wordSize-1 downto 0);
out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
 
interrupt : in std_logic;
interrupt_ack : out std_logic;
break_o : out std_logic;
zpu_status : out std_logic_vector(63 downto 0));
end zpu_core;
 
architecture behave of zpu_core is
 
type InsnType is
(
State_AddTop,
State_Dup,
State_DupStackB,
State_Pop,
State_Popdown,
State_Add,
State_Or,
State_And,
State_Store,
State_AddSP,
State_Shift,
State_Nop,
State_Im,
State_LoadSP,
State_StoreSP,
State_Emulate,
State_Load,
State_PushPC,
State_PushSP,
State_PopPC,
State_PopPCRel,
State_Not,
State_Flip,
State_PopSP,
State_Neqbranch,
State_Eq,
State_Loadb,
State_Mult,
State_Lessthan,
State_Lessthanorequal,
State_Ulessthanorequal,
State_Ulessthan,
State_Pushspadd,
State_Call,
State_Callpcrel,
State_Sub,
State_Break,
State_Storeb,
State_Interrupt,
State_InsnFetch
);
 
type StateType is
(
State_Idle, -- using first state first on the list out of paranoia
State_Load2,
State_Popped,
State_LoadSP2,
State_LoadSP3,
State_AddSP2,
State_Fetch,
State_Execute,
State_Decode,
State_Decode2,
State_Resync,
 
State_StoreSP2,
State_Resync2,
State_Resync3,
State_Loadb2,
State_Storeb2,
State_Mult2,
State_Mult3,
State_Mult5,
State_Mult6,
State_Mult4,
State_BinaryOpResult
);
 
signal sp_address_default : std_logic_vector(31 downto 0);
 
signal pc : std_logic_vector(maxAddrBitIncIO downto 0);
signal sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal incSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal incIncSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal decSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal stackA : std_logic_vector(wordSize-1 downto 0);
signal binaryOpResult : std_logic_vector(wordSize-1 downto 0);
signal multResult2 : std_logic_vector(wordSize-1 downto 0);
signal multResult3 : std_logic_vector(wordSize-1 downto 0);
signal multResult : std_logic_vector(wordSize-1 downto 0);
signal multA : std_logic_vector(wordSize-1 downto 0);
signal multB : std_logic_vector(wordSize-1 downto 0);
signal stackB : std_logic_vector(wordSize-1 downto 0);
signal idim_flag : std_logic;
signal busy : std_logic;
signal mem_readEnable : std_logic;
signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal mem_delayReadEnable : std_logic;
signal mem_busy : std_logic;
signal decodeWord : std_logic_vector(wordSize-1 downto 0);
 
 
signal state : StateType;
signal insn : InsnType;
type InsnArray is array(0 to wordBytes-1) of InsnType;
signal decodedOpcode : InsnArray;
 
type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
 
signal opcode : OpcodeArray;
 
 
 
 
signal begin_inst : std_logic;
signal trace_opcode : std_logic_vector(7 downto 0);
signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
 
signal out_mem_req : std_logic;
 
signal inInterrupt : std_logic;
 
-- state machine.
 
begin
cpu_present <= '1';
sp_address_default <= std_logic_vector(to_unsigned(stack_address, 32));
 
pc_bo <= pc;
interrupt_ack <= inInterrupt;
 
zpu_status(maxAddrBitIncIO downto 0) <= trace_pc;
--zpu_status(31) <= '1';
--zpu_status(39 downto 32) <= trace_opcode;
--zpu_status(40) <= '1' when (state = State_Idle) else '0';
--zpu_status(62) <= '1';
 
--traceFileGenerate:
--if Generate_Trace generate
--trace_file: trace port map (
-- clk => clk,
-- begin_inst => begin_inst,
-- pc => trace_pc,
-- opcode => trace_opcode,
-- sp => trace_sp,
-- memA => trace_topOfStack,
-- memB => trace_topOfStackB,
-- busy => busy,
-- intsp => (others => 'U')
-- );
--end generate;
 
-- the memory subsystem will tell us one cycle later whether or
-- not it is busy
out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
mem_req <= out_mem_req;
incSp <= sp + 1;
incIncSp <= sp + 2;
decSp <= sp - 1;
mem_busy <= out_mem_req and not mem_ack; -- '1' when the memory is busy
 
opcodeControl:
process(clk)
variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
variable spOffset : std_logic_vector(4 downto 0);
variable tSpOffset : std_logic_vector(4 downto 0);
variable nextPC : std_logic_vector(maxAddrBitIncIO downto 0);
variable tNextState : InsnType;
variable tDecodedOpcode : InsnArray;
variable tMultResult : std_logic_vector(wordSize*2-1 downto 0);
begin
if (clk'event and clk = '1') then
if sreset = '1' then
state <= State_Idle;
break_o <= '0';
sp <= sp_address_default(31 downto 2);
pc <= (others => '0');
idim_flag <= '0';
begin_inst <= '0';
mem_we <= '0';
multA <= (others => '0');
multB <= (others => '0');
mem_writeMask <= (others => '1');
out_mem_req <= '0';
mem_addr <= (others => DontCareValue);
mem_write <= (others => DontCareValue);
inInterrupt <= '0';
else
-- we must multiply unconditionally to get pipelined multiplication
tMultResult := multA * multB;
multResult3 <= multResult2;
multResult2 <= multResult;
multResult <= tMultResult(wordSize-1 downto 0);
spOffset(4):=not opcode(conv_integer(pc(byteBits-1 downto 0)))(4);
spOffset(3 downto 0):=opcode(conv_integer(pc(byteBits-1 downto 0)))(3 downto 0);
nextPC := pc + 1;
 
-- prepare trace snapshot
trace_opcode <= opcode(conv_integer(pc(byteBits-1 downto 0)));
--trace_pc <= pc;
trace_sp <= sp;
trace_topOfStack <= stackA;
trace_topOfStackB <= stackB;
begin_inst <= '0';
 
-- we terminate the requeset as soon as we get acknowledge
if mem_ack = '1' then
out_mem_req <= '0';
mem_we <= '0';
end if;
if interrupt='0' then
inInterrupt <= '0'; -- no longer in an interrupt
end if;
 
case state is
when State_Idle =>
if enable='1' then
state <= State_Resync;
end if;
-- Initial state of ZPU, fetch top of stack + first instruction
when State_Resync =>
if mem_busy='0' then
mem_addr <= sp;
out_mem_req <= '1';
state <= State_Resync2;
end if;
when State_Resync2 =>
if mem_busy='0' then
stackA <= mem_read;
mem_addr <= incSp;
out_mem_req <= '1';
state <= State_Resync3;
end if;
when State_Resync3 =>
if mem_busy='0' then
stackB <= mem_read;
mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
out_mem_req <= '1';
state <= State_Decode;
end if;
when State_Decode =>
if mem_busy='0' then
decodeWord <= mem_read;
state <= State_Decode2;
end if;
when State_Decode2 =>
-- decode 4 instructions in parallel
for i in 0 to wordBytes-1 loop
tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
 
tSpOffset(4):=not tOpcode(4);
tSpOffset(3 downto 0):=tOpcode(3 downto 0);
 
opcode(i) <= tOpcode;
if (tOpcode(7 downto 7)=OpCode_Im) then
tNextState:=State_Im;
elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
if tSpOffset = 0 then
tNextState := State_Pop;
elsif tSpOffset=1 then
tNextState := State_PopDown;
else
tNextState :=State_StoreSP;
end if;
elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
if tSpOffset = 0 then
tNextState :=State_Dup;
elsif tSpOffset = 1 then
tNextState :=State_DupStackB;
else
tNextState :=State_LoadSP;
end if;
elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
tNextState :=State_Emulate;
if tOpcode(5 downto 0)=OpCode_Neqbranch then
tNextState :=State_Neqbranch;
elsif tOpcode(5 downto 0)=OpCode_Eq then
tNextState :=State_Eq;
elsif tOpcode(5 downto 0)=OpCode_Lessthan then
tNextState :=State_Lessthan;
elsif tOpcode(5 downto 0)=OpCode_Lessthanorequal then
--tNextState :=State_Lessthanorequal;
elsif tOpcode(5 downto 0)=OpCode_Ulessthan then
tNextState :=State_Ulessthan;
elsif tOpcode(5 downto 0)=OpCode_Ulessthanorequal then
--tNextState :=State_Ulessthanorequal;
elsif tOpcode(5 downto 0)=OpCode_Loadb then
tNextState :=State_Loadb;
elsif tOpcode(5 downto 0)=OpCode_Mult then
tNextState :=State_Mult;
elsif tOpcode(5 downto 0)=OpCode_Storeb then
tNextState :=State_Storeb;
elsif tOpcode(5 downto 0)=OpCode_Pushspadd then
tNextState :=State_Pushspadd;
elsif tOpcode(5 downto 0)=OpCode_Callpcrel then
tNextState :=State_Callpcrel;
elsif tOpcode(5 downto 0)=OpCode_Call then
--tNextState :=State_Call;
elsif tOpcode(5 downto 0)=OpCode_Sub then
tNextState :=State_Sub;
elsif tOpcode(5 downto 0)=OpCode_PopPCRel then
--tNextState :=State_PopPCRel;
end if;
elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
if tSpOffset = 0 then
tNextState := State_Shift;
elsif tSpOffset = 1 then
tNextState := State_AddTop;
else
tNextState :=State_AddSP;
end if;
else
case tOpcode(3 downto 0) is
when OpCode_Nop =>
tNextState :=State_Nop;
when OpCode_PushSP =>
tNextState :=State_PushSP;
when OpCode_PopPC =>
tNextState :=State_PopPC;
when OpCode_Add =>
tNextState :=State_Add;
when OpCode_Or =>
tNextState :=State_Or;
when OpCode_And =>
tNextState :=State_And;
when OpCode_Load =>
tNextState :=State_Load;
when OpCode_Not =>
tNextState :=State_Not;
when OpCode_Flip =>
tNextState :=State_Flip;
when OpCode_Store =>
tNextState :=State_Store;
when OpCode_PopSP =>
tNextState :=State_PopSP;
when others =>
tNextState := State_Break;
 
end case;
end if;
tDecodedOpcode(i) := tNextState;
end loop;
insn <= tDecodedOpcode(conv_integer(pc(byteBits-1 downto 0)));
-- once we wrap, we need to fetch
tDecodedOpcode(0) := State_InsnFetch;
 
decodedOpcode <= tDecodedOpcode;
state <= State_Execute;
 
 
-- Each instruction must:
--
-- 1. set idim_flag
-- 2. increase pc if applicable
-- 3. set next state if appliable
-- 4. do it's operation
when State_Execute =>
insn <= decodedOpcode(conv_integer(nextPC(byteBits-1 downto 0)));
case insn is
when State_InsnFetch =>
state <= State_Fetch;
when State_Im =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '1';
pc <= pc + 1;
if idim_flag='1' then
stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
else
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
stackB <= stackA;
sp <= decSp;
for i in wordSize-1 downto 7 loop
stackA(i) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6);
end loop;
stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
end if;
else
insn <= insn;
end if;
when State_StoreSP =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_StoreSP2;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= sp+spOffset;
mem_write <= stackA;
stackA <= stackB;
sp <= incSp;
else
insn <= insn;
end if;
 
when State_LoadSP =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_LoadSP2;
sp <= decSp;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
else
insn <= insn;
end if;
when State_Emulate =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
sp <= decSp;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
stackA <= (others => DontCareValue);
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
stackB <= stackA;
-- The emulate address is:
-- 98 7654 3210
-- 0000 00aa aaa0 0000
pc <= (others => '0');
pc(9 downto 5) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(4 downto 0);
state <= State_Fetch;
else
insn <= insn;
end if;
when State_Callpcrel =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
stackA <= (others => DontCareValue);
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
pc <= pc + stackA(maxAddrBitIncIO downto 0);
state <= State_Fetch;
else
insn <= insn;
end if;
when State_Call =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
stackA <= (others => DontCareValue);
stackA(maxAddrBitIncIO downto 0) <= pc + 1;
pc <= stackA(maxAddrBitIncIO downto 0);
state <= State_Fetch;
else
insn <= insn;
end if;
when State_AddSP =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_AddSP2;
out_mem_req <= '1';
mem_addr <= sp+spOffset;
else
insn <= insn;
end if;
when State_PushSP =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
sp <= decSp;
stackA <= (others => '0');
stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
stackB <= stackA;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
else
insn <= insn;
end if;
when State_PopPC =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= stackA(maxAddrBitIncIO downto 0);
sp <= incSp;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
state <= State_Resync;
else
insn <= insn;
end if;
when State_PopPCRel =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= stackA(maxAddrBitIncIO downto 0) + pc;
sp <= incSp;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
state <= State_Resync;
else
insn <= insn;
end if;
when State_Add =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
stackA <= stackA + stackB;
out_mem_req <= '1';
mem_addr <= incIncSp;
sp <= incSp;
state <= State_Popped;
else
insn <= insn;
end if;
when State_Sub =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= stackB - stackA;
state <= State_BinaryOpResult;
when State_Pop =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
mem_addr <= incIncSp;
out_mem_req <= '1';
sp <= incSp;
stackA <= stackB;
state <= State_Popped;
else
insn <= insn;
end if;
when State_PopDown =>
if mem_busy='0' then
-- PopDown leaves top of stack unchanged
begin_inst <= '1';
idim_flag <= '0';
mem_addr <= incIncSp;
out_mem_req <= '1';
sp <= incSp;
state <= State_Popped;
else
insn <= insn;
end if;
when State_Or =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
stackA <= stackA or stackB;
out_mem_req <= '1';
mem_addr <= incIncSp;
sp <= incSp;
state <= State_Popped;
else
insn <= insn;
end if;
when State_And =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
stackA <= stackA and stackB;
out_mem_req <= '1';
mem_addr <= incIncSp;
sp <= incSp;
state <= State_Popped;
else
insn <= insn;
end if;
when State_Eq =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= (others => '0');
if (stackA=stackB) then
binaryOpResult(0) <= '1';
end if;
state <= State_BinaryOpResult;
when State_Ulessthan =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= (others => '0');
if (stackA<stackB) then
binaryOpResult(0) <= '1';
end if;
state <= State_BinaryOpResult;
when State_Ulessthanorequal =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= (others => '0');
if (stackA<=stackB) then
binaryOpResult(0) <= '1';
end if;
state <= State_BinaryOpResult;
when State_Lessthan =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= (others => '0');
if (ieee.std_logic_arith.signed(stackA)<ieee.std_logic_arith.signed(stackB)) then
binaryOpResult(0) <= '1';
end if;
state <= State_BinaryOpResult;
when State_Lessthanorequal =>
begin_inst <= '1';
idim_flag <= '0';
binaryOpResult <= (others => '0');
if (ieee.std_logic_arith.signed(stackA)<=ieee.std_logic_arith.signed(stackB)) then
binaryOpResult(0) <= '1';
end if;
state <= State_BinaryOpResult;
when State_Load =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_Load2;
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
out_mem_req <= '1';
else
insn <= insn;
end if;
 
when State_Dup =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
sp <= decSp;
stackB <= stackA;
mem_write <= stackB;
mem_addr <= incSp;
out_mem_req <= '1';
mem_we <= '1';
else
insn <= insn;
end if;
when State_DupStackB =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
sp <= decSp;
stackA <= stackB;
stackB <= stackA;
mem_write <= stackB;
mem_addr <= incSp;
out_mem_req <= '1';
mem_we <= '1';
else
insn <= insn;
end if;
when State_Store =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
mem_write <= stackB;
out_mem_req <= '1';
mem_we <= '1';
sp <= incIncSp;
state <= State_Resync;
else
insn <= insn;
end if;
when State_PopSP =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
mem_write <= stackB;
mem_addr <= incSp;
out_mem_req <= '1';
mem_we <= '1';
sp <= stackA(maxAddrBitIncIO downto minAddrBit);
state <= State_Resync;
else
insn <= insn;
end if;
when State_Nop =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
when State_Not =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
stackA <= not stackA;
when State_Flip =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
for i in 0 to wordSize-1 loop
stackA(i) <= stackA(wordSize-1-i);
end loop;
when State_AddTop =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
stackA <= stackA + stackB;
when State_Shift =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
stackA(0) <= '0';
when State_Pushspadd =>
begin_inst <= '1';
idim_flag <= '0';
pc <= pc + 1;
stackA <= (others => '0');
stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
when State_Neqbranch =>
-- branches are almost always taken as they form loops
begin_inst <= '1';
idim_flag <= '0';
sp <= incIncSp;
if (stackB/=0) then
pc <= stackA(maxAddrBitIncIO downto 0) + pc;
else
pc <= pc + 1;
end if;
-- need to fetch stack again.
state <= State_Resync;
when State_Mult =>
begin_inst <= '1';
idim_flag <= '0';
multA <= stackA;
multB <= stackB;
state <= State_Mult2;
when State_Break =>
report "Break instruction encountered" severity failure;
break_o <= '1';
 
when State_Loadb =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_Loadb2;
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
out_mem_req <= '1';
else
insn <= insn;
end if;
when State_Storeb =>
if mem_busy='0' then
begin_inst <= '1';
idim_flag <= '0';
state <= State_Storeb2;
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
out_mem_req <= '1';
else
insn <= insn;
end if;
when others =>
-- sp <= (others => DontCareValue);
report "Illegal instruction" severity failure;
break_o <= '1';
end case;
 
 
when State_StoreSP2 =>
if mem_busy='0' then
mem_addr <= incSp;
out_mem_req <= '1';
state <= State_Popped;
end if;
when State_LoadSP2 =>
if mem_busy='0' then
state <= State_LoadSP3;
out_mem_req <= '1';
mem_addr <= sp+spOffset+1;
end if;
when State_LoadSP3 =>
if mem_busy='0' then
pc <= pc + 1;
state <= State_Execute;
stackB <= stackA;
stackA <= mem_read;
end if;
when State_AddSP2 =>
if mem_busy='0' then
pc <= pc + 1;
state <= State_Execute;
stackA <= stackA + mem_read;
end if;
when State_Load2 =>
if mem_busy='0' then
stackA <= mem_read;
pc <= pc + 1;
state <= State_Execute;
end if;
when State_Loadb2 =>
if mem_busy='0' then
stackA <= (others => '0');
stackA(7 downto 0) <= mem_read(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8);
pc <= pc + 1;
state <= State_Execute;
end if;
when State_Storeb2 =>
if mem_busy='0' then
mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
mem_write <= mem_read;
mem_write(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8) <= stackB(7 downto 0) ;
out_mem_req <= '1';
mem_we <= '1';
pc <= pc + 1;
sp <= incIncSp;
state <= State_Resync;
end if;
when State_Fetch =>
if mem_busy='0' then
if interrupt='1' and inInterrupt='0' and idim_flag='0' then
-- We got an interrupt
inInterrupt <= '1';
sp <= decSp;
out_mem_req <= '1';
mem_we <= '1';
mem_addr <= incSp;
mem_write <= stackB;
stackA <= (others => DontCareValue);
stackA(maxAddrBitIncIO downto 0) <= pc;
stackB <= stackA;
pc <= conv_std_logic_vector(32, maxAddrBitIncIo+1); -- interrupt address
report "ZPU jumped to interrupt!" severity note;
else
mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
out_mem_req <= '1';
state <= State_Decode;
end if;
end if;
when State_Mult2 =>
state <= State_Mult3;
when State_Mult3 =>
state <= State_Mult4;
when State_Mult4 =>
state <= State_Mult5;
when State_Mult5 =>
stackA <= multResult3;
state <= State_Mult6;
when State_Mult6 =>
if mem_busy='0' then
out_mem_req <= '1';
mem_addr <= incIncSp;
sp <= incSp;
state <= State_Popped;
end if;
when State_BinaryOpResult =>
if mem_busy='0' then
-- NB!!!! we know that the memory isn't busy at this point!!!!
out_mem_req <= '1';
mem_addr <= incIncSp;
sp <= incSp;
stackA <= binaryOpResult;
state <= State_Popped;
end if;
when State_Popped =>
if mem_busy='0' then
pc <= pc + 1;
stackB <= mem_read;
state <= State_Execute;
end if;
when others =>
-- sp <= (others => DontCareValue);
report "Illegal state" severity failure;
break_o <= '1';
end case;
end if;
end if;
end process;
 
 
 
end behave;
/pss/hdl/pss/zpu_uc/zpu_core_stub.v
0,0 → 1,35
module zpu_core_stub
(
input clk,
input sreset,
input enable,
output cpu_present,
output [31:0] pc_bo,
 
output mem_req,
output mem_we,
input mem_ack,
input [31:0] mem_read,
output [31:0] mem_write,
output [31:0] out_mem_addr,
output [3:0] mem_writeMask,
 
input interrupt,
output interrupt_ack,
output break_o,
output [63:0] zpu_status
);
 
assign cpu_present = 1'b0;
assign pc_bo = 32'h0;
assign mem_req = 1'b0;
assign mem_we = 1'bx;
assign mem_write = 32'hx;
assign out_mem_addr = 32'hx;
assign mem_writeMask = 4'h0;
 
assign interrupt_ack = 1'b0;
assign break_o = 1'b0;
assign zpu_status = 64'h0;
 
endmodule
/pss/hdl/pss/zpu_uc/zpu_uc.v
0,0 → 1,297
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module ZPU_uC
#(
parameter CPU_PRESENT = 1,
parameter CPU_RESET_DEFAULT = 1,
parameter A31_DEFAULTS = 1,
parameter MEM_DATA = "data.bin",
parameter MEM_SIZE_KB = 1
)
(
input clk_i, rst_i,
input [3:0] INT_i,
 
// Expansion bus
output xport_req_o,
input xport_ack_i,
input xport_err_i,
output xport_we_o,
output [31:0] xport_addr_bo,
output [31:0] xport_wdata_bo,
input xport_resp_i,
input [31:0] xport_rdata_bi,
 
//Debug interface
input dbg_enb_i,
input dbg_wr_i,
input [31:0] dbg_addr_bi,
input [31:0] dbg_data_bi,
output dbg_resp_o,
output [31:0] dbg_data_bo
);
 
// ZPU system bus
wire cpu_bus_enb;
wire cpu_bus_we;
wire cpu_bus_ack;
wire [31:0] cpu_bus_read;
wire [31:0] cpu_bus_write;
wire [31:0] cpu_bus_addr;
wire [3:0] cpu_bus_writemask;
 
// MAU-RAM bus
wire [31:0] ram0_bus_addr;
wire ram0_bus_we;
wire [31:0] ram0_bus_rddata;
wire [31:0] ram0_bus_wrdata;
 
wire [31:0] ram1_bus_addr;
wire ram1_bus_we;
wire [31:0] ram1_bus_rddata;
wire [31:0] ram1_bus_wrdata;
 
// ZPU control
wire cpu_present;
wire [63:0] zpu_status;
wire cpu_break;
wire [31:0] cpu_pc;
 
wire cpu_interrupt;
wire cpu_interrupt_ack;
wire cpu_reset;
wire cpu_enb;
 
// INTC programming interface
wire intc_ie;
wire intc_ie_we;
wire intc_ie_data;
wire [7:0] intc_mask;
wire [7:0] intc_pending;
wire intc_clr_cmd;
wire [7:0] intc_clr_code;
 
// interrupts
wire [3:0] INT;
wire bus_error_int;
wire trap_int;
wire sgi_int;
wire dma_int;
 
generate
if (CPU_PRESENT == 1)
 
// Processor core
zpu_core
#(
.stack_address((MEM_SIZE_KB * 1024) - 8)
)
zpu_core
(
.clk(clk_i),
.sreset(rst_i | cpu_reset),
.enable(cpu_enb),
.cpu_present(cpu_present),
.pc_bo(cpu_pc),
 
.mem_req(cpu_bus_enb),
.mem_we(cpu_bus_we),
.mem_ack(cpu_bus_ack),
.mem_read(cpu_bus_read),
.mem_write(cpu_bus_write),
.out_mem_addr(cpu_bus_addr),
.mem_writeMask(cpu_bus_writemask),
 
.interrupt(cpu_interrupt),
.interrupt_ack(cpu_interrupt_ack),
.break_o(cpu_break),
.zpu_status(zpu_status)
);
 
else
 
zpu_core_stub zpu_core
(
.clk(clk_i),
.sreset(rst_i | cpu_reset),
.enable(cpu_enb),
.cpu_present(cpu_present),
.pc_bo(cpu_pc),
 
.mem_req(cpu_bus_enb),
.mem_we(cpu_bus_we),
.mem_ack(cpu_bus_ack),
.mem_read(cpu_bus_read),
.mem_write(cpu_bus_write),
.out_mem_addr(cpu_bus_addr),
.mem_writeMask(cpu_bus_writemask),
 
.interrupt(cpu_interrupt),
.interrupt_ack(cpu_interrupt_ack),
.break_o(cpu_break),
.zpu_status(zpu_status)
);
endgenerate
 
edge_detector edge_det0
( .clk_i(clk_i), .rst_i(rst_i), .in(INT_i[0]), .out(INT[0]) );
 
edge_detector edge_det1
( .clk_i(clk_i), .rst_i(rst_i), .in(INT_i[1]), .out(INT[1]) );
 
edge_detector edge_det2
( .clk_i(clk_i), .rst_i(rst_i), .in(INT_i[2]), .out(INT[2]) );
 
edge_detector edge_det3
( .clk_i(clk_i), .rst_i(rst_i), .in(INT_i[3]), .out(INT[3]) );
 
// Interrupt controller
int_controller int_controller
(
.clk_i(clk_i),
.rst_i(rst_i),
.interrupt_bi({INT, dma_int, sgi_int, trap_int, bus_error_int}),
 
.ie_o(intc_ie),
.ie_we_i(intc_ie_we),
.ie_data_i(intc_ie_data),
.mask_bi(intc_mask),
.pending_bo(intc_pending),
.clr_cmd_i(intc_clr_cmd),
.clr_code_bi(intc_clr_code),
 
.cpu_req_o(cpu_interrupt),
.cpu_ack_i(cpu_interrupt_ack)
);
 
ZPU_uC_SystemController
#(
.A31_DEFAULTS(A31_DEFAULTS),
.CPU_RESET_DEFAULT(CPU_RESET_DEFAULT),
.MEM_SIZE_KB(MEM_SIZE_KB)
)
SystemController
(
.clk_i(clk_i),
.rst_i(rst_i),
 
//// Masters ////
// Debug bus //
.dbg_enb_i(dbg_enb_i),
.dbg_we_i(dbg_wr_i),
.dbg_addr_bi(dbg_addr_bi),
.dbg_wdata_bi(dbg_data_bi),
.dbg_ack_o(dbg_resp_o),
.dbg_rdata_bo(dbg_data_bo),
 
// ZPU bus //
.cpu_enb_i(cpu_bus_enb),
.cpu_we_i(cpu_bus_we),
.cpu_ack_o(cpu_bus_ack),
.cpu_rdata_bo(cpu_bus_read),
.cpu_wdata_bi(cpu_bus_write),
.cpu_addr_bi(cpu_bus_addr),
.cpu_writemask_bi(cpu_bus_writemask),
 
//// Slaves ////
// RAM0 bus //
.ram0_addr_bo(ram0_bus_addr),
.ram0_we_o(ram0_bus_we),
.ram0_wdata_bo(ram0_bus_wrdata),
.ram0_rdata_bi(ram0_bus_rddata),
 
// RAM1 bus //
.ram1_addr_bo(ram1_bus_addr),
.ram1_we_o(ram1_bus_we),
.ram1_wdata_bo(ram1_bus_wrdata),
.ram1_rdata_bi(ram1_bus_rddata),
 
// Expansion port //
.xport_req_o(xport_req_o),
.xport_ack_i(xport_ack_i),
.xport_err_i(xport_err_i),
.xport_we_o(xport_we_o),
.xport_addr_bo(xport_addr_bo),
.xport_wdata_bo(xport_wdata_bo),
.xport_resp_i(xport_resp_i),
.xport_rdata_bi(xport_rdata_bi),
 
// INTC bus //
.intc_ie_i(intc_ie),
.intc_ie_we_o(intc_ie_we),
.intc_ie_data_o(intc_ie_data),
.intc_mask_bo(intc_mask),
.intc_pending_bi(intc_pending),
.intc_clr_cmd_o(intc_clr_cmd),
.intc_clr_code_bo(intc_clr_code),
 
.cpu_present(cpu_present),
.cpu_pc_bi(cpu_pc),
.cpu_break_i(cpu_break),
.cpu_reset_o(cpu_reset),
.cpu_enb_o(cpu_enb),
 
.bus_error_int_o(bus_error_int),
.trap_int_o(trap_int),
.dma_int_o(dma_int),
.sgi_int_o(sgi_int)
);
 
ram_dual
#(
.mem_data(MEM_DATA),
.dat_width(32),
.adr_width(32),
.mem_size((MEM_SIZE_KB * 1024) / 4 )
)
ram_dual_port
(
.clk(clk_i),
 
.dat0_i(ram0_bus_wrdata),
.adr0_i({2'h0, ram0_bus_addr[31:2]}),
.we0_i(ram0_bus_we),
.dat0_o(ram0_bus_rddata),
 
.dat1_i(ram1_bus_wrdata),
.adr1_i({2'h0, ram1_bus_addr[31:2]}),
.we1_i(ram1_bus_we),
.dat1_o(ram1_bus_rddata)
);
 
endmodule
/pss/hdl/pss/pss.v
0,0 → 1,133
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module pss
#(
parameter CPU_PRESENT = 1,
parameter CPU_RESET_DEFAULT = 1,
parameter A31_DEFAULTS = 1,
parameter MEM_SIZE_KB = 1,
parameter MEM_DATA = ""
)
(
input clk_i, arst_i,
output srst_o,
 
input rx_i,
output tx_o,
 
input [3:0] INT_i,
 
// Expansion bus
output xport_req_o,
input xport_ack_i,
input xport_err_i,
output xport_we_o,
output [31:0] xport_addr_bo,
output [31:0] xport_wdata_bo,
input xport_resp_i,
input [31:0] xport_rdata_bi
);
 
wire sync_rst, udm_rst;
as_reset_cntrl as_reset_cntrl
(
.clk_i(clk_i),
.rst_i(arst_i),
.rst_o(sync_rst)
);
 
assign srst_o = sync_rst | udm_rst;
 
wire dbg_bus_enb;
wire dbg_bus_we;
wire [31:0] dbg_bus_addr;
wire [31:0] dbg_bus_wdata;
wire [31:0] dbg_bus_rdata;
wire dbg_bus_resp;
 
udm udm
(
.clk_i(clk_i),
.rst_i(sync_rst),
 
.rx_i(rx_i),
.tx_o(tx_o),
 
.rst_o(udm_rst),
.bus_enb_o(dbg_bus_enb),
.bus_we_o(dbg_bus_we),
.bus_addr_bo(dbg_bus_addr),
.bus_wdata_bo(dbg_bus_wdata),
 
.bus_ack_i(dbg_bus_resp),
.bus_rdata_bi(dbg_bus_rdata)
);
 
ZPU_uC
#(
.CPU_PRESENT(CPU_PRESENT),
.CPU_RESET_DEFAULT(CPU_RESET_DEFAULT),
.A31_DEFAULTS(A31_DEFAULTS),
.MEM_DATA(MEM_DATA),
.MEM_SIZE_KB(MEM_SIZE_KB)
)
ZPU_uC
(
.clk_i(clk_i),
.rst_i(srst_o),
.INT_i(INT_i),
 
// Expansion bus
.xport_req_o(xport_req_o),
.xport_ack_i(xport_ack_i),
.xport_err_i(xport_err_i),
.xport_we_o(xport_we_o),
.xport_addr_bo(xport_addr_bo),
.xport_wdata_bo(xport_wdata_bo),
.xport_resp_i(xport_resp_i),
.xport_rdata_bi(xport_rdata_bi),
 
//Debug interface
.dbg_enb_i(dbg_bus_enb),
.dbg_wr_i(dbg_bus_we),
.dbg_addr_bi(dbg_bus_addr),
.dbg_data_bi(dbg_bus_wdata),
.dbg_resp_o(dbg_bus_resp),
.dbg_data_bo(dbg_bus_rdata)
);
 
endmodule
/pss/hdl/pss/as_reset_cntrl.v
0,0 → 1,60
/*
PSS
 
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
All rights reserved.
 
Version 0.9
 
The FreeBSD license
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
 
module as_reset_cntrl
(
input clk_i, rst_i,
output reg rst_o
);
 
reg [15:0] reset_counter;
 
always @(posedge clk_i, posedge rst_i)
begin
if (rst_i)
begin
reset_counter <= 16'h0;
rst_o <= 1'b1;
end
else
begin
reset_counter <= {1'b1, reset_counter[15:1]};
if (reset_counter == 16'hFFFF) rst_o <= 1'b0;
end
end
 
 
endmodule
/pss/hdl/debouncer.v
0,0 → 1,33
module debouncer
(
input clk_i, rst_i,
 
input in_i,
 
output out_o
);
 
reg [7:0] state;
assign out_o = state[7];
 
always @(posedge clk_i)
begin
if (rst_i)
begin
state <= 8'h0;
end
else
begin
 
if (in_i == 1'b1)
begin
if (state != 8'hFF) state <= state + 8'h1;
end
else
begin
if (state != 8'h00) state <= state - 8'h1;
end
end
end
 
endmodule

powered by: WebSVN 2.1.0

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