URL
https://opencores.org/ocsvn/pss/pss/trunk
Subversion Repositories pss
Compare Revisions
- This comparison shows the changes necessary to convert path
/pss
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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; |
/trunk/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; |
/trunk/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; |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |
/trunk/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 |