/*
|
/*
|
PSS
|
PSS
|
|
|
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
|
Copyright (c) 2016 Alexander Antonov <153287@niuitmo.ru>
|
All rights reserved.
|
All rights reserved.
|
|
|
Version 0.9
|
Version 0.99
|
|
|
The FreeBSD license
|
The FreeBSD license
|
|
|
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
are met:
|
are met:
|
|
|
1. Redistributions of source code must retain the above copyright
|
1. Redistributions of source code must retain the above copyright
|
notice, this list of conditions and the following disclaimer.
|
notice, this list of conditions and the following disclaimer.
|
2. Redistributions in binary form must reproduce the above
|
2. Redistributions in binary form must reproduce the above
|
copyright notice, this list of conditions and the following
|
copyright notice, this list of conditions and the following
|
disclaimer in the documentation and/or other materials
|
disclaimer in the documentation and/or other materials
|
provided with the distribution.
|
provided with the distribution.
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
PSS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
*/
|
*/
|
|
|
|
|
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
|
|
`define HALF_PERIOD 10 //external 50 MHZ
|
`define HALF_PERIOD 10 //external 50 MHZ
|
`define DIVIDER_115200 32'd8680
|
`define DIVIDER_115200 32'd8680
|
`define DIVIDER_19200 32'd52083
|
`define DIVIDER_19200 32'd52083
|
`define DIVIDER_9600 32'd104166
|
`define DIVIDER_9600 32'd104166
|
`define DIVIDER_4800 32'd208333
|
`define DIVIDER_4800 32'd208333
|
`define DIVIDER_2400 32'd416666
|
`define DIVIDER_2400 32'd416666
|
|
|
// udm interface
|
// udm interface
|
`define SYNC_BYTE 8'h55
|
`define SYNC_BYTE 8'h55
|
`define ESCAPE_BYTE 8'h5a
|
`define ESCAPE_BYTE 8'h5a
|
`define IDCODE_CMD 8'h00 // check udm accessibility
|
`define IDCODE_CMD 8'h00 // check udm accessibility
|
`define RST_CMD 8'h80 // Reset slave
|
`define RST_CMD 8'h80 // Reset slave
|
`define WR_CMD 8'h81 // Write slave with autoincrement
|
`define WR_CMD 8'h81 // Write slave with autoincrement
|
`define RD_CMD 8'h82 // Read slave with autoincrement
|
`define RD_CMD 8'h82 // Read slave with autoincrement
|
`define WR_CMD_NOINC 8'h83 // Write slave without autoincrement
|
`define WR_CMD_NOINC 8'h83 // Write slave without autoincrement
|
`define RD_CMD_NOINC 8'h84 // Read slave without autoincrement
|
`define RD_CMD_NOINC 8'h84 // Read slave without autoincrement
|
|
|
module PSS_SoC_tb ();
|
module PSS_SoC_tb ();
|
//
|
//
|
localparam REG_CPU_CONTROL_ADDR = 32'h40000000;
|
localparam REG_CPU_CONTROL_ADDR = 32'h40000000;
|
localparam REG_CPU_PC_ADDR = 32'h40000004;
|
localparam REG_CPU_PC_ADDR = 32'h40000004;
|
localparam REG_CPU_A31 = 32'h40000008;
|
localparam REG_CPU_A31 = 32'h40000008;
|
localparam REG_DBG_A31 = 32'h4000000C;
|
localparam REG_DBG_A31 = 32'h4000000C;
|
|
|
localparam REG_INTC_CONTROL_ADDR = 32'h40000010;
|
localparam REG_INTC_CONTROL_ADDR = 32'h40000010;
|
localparam REG_INTC_MASK_ADDR = 32'h40000014;
|
localparam REG_INTC_MASK_ADDR = 32'h40000014;
|
localparam REG_INTC_REQ_ADDR = 32'h40000018;
|
localparam REG_INTC_REQ_ADDR = 32'h40000018;
|
localparam REG_MEM_SIZE_KB = 32'h4000001C;
|
localparam REG_MEM_SIZE_KB = 32'h4000001C;
|
|
|
localparam REG_DMA_CONTROL_ADDR = 32'h40000020;
|
localparam REG_DMA_CONTROL_ADDR = 32'h40000020;
|
localparam REG_DMA_SOURCEADDR_ADDR = 32'h40000024;
|
localparam REG_DMA_SOURCEADDR_ADDR = 32'h40000024;
|
localparam REG_DMA_DESTADDR_ADDR = 32'h40000028;
|
localparam REG_DMA_DESTADDR_ADDR = 32'h40000028;
|
localparam REG_DMA_SIZE_ADDR = 32'h4000002C;
|
localparam REG_DMA_SIZE_ADDR = 32'h4000002C;
|
|
|
localparam REG_SGI_ADDR = 32'h40000030;
|
localparam REG_SGI_ADDR = 32'h40000030;
|
|
|
localparam REG_BUS_ERROR_ADDR_ADDR = 32'h40000038;
|
localparam REG_BUS_ERROR_ADDR_ADDR = 32'h40000038;
|
localparam REG_BUS_ERROR_PC_ADDR = 32'h4000003C;
|
localparam REG_BUS_ERROR_PC_ADDR = 32'h4000003C;
|
|
|
localparam REG_TRAP_CONTROL_ADDR = 32'h40000040;
|
localparam REG_TRAP_CONTROL_ADDR = 32'h40000040;
|
localparam REG_TRAP_ADDR_ADDR = 32'h40000044;
|
localparam REG_TRAP_ADDR_ADDR = 32'h40000044;
|
//
|
//
|
reg CLK_50MHZ, RST, rx;
|
reg CLK_50MHZ, RST, rx;
|
reg [7:0] SW;
|
reg [7:0] SW;
|
wire [7:0] LED;
|
wire [7:0] LED;
|
|
|
//instantiating PSS
|
//instantiating PSS
|
pss_soc_top DUT(
|
pss_soc_top DUT(
|
.clk_i(CLK_50MHZ),
|
.clk_i(CLK_50MHZ),
|
.rst_i(RST),
|
.rst_i(RST),
|
.rx_i(rx),
|
.rx_i(rx),
|
.ext_int_i(0),
|
.ext_int_i(0),
|
.SW(SW),
|
.SW(SW),
|
.LED(LED));
|
.LED(LED));
|
//////////////////////////
|
//////////////////////////
|
/////////tasks////////////
|
/////////tasks////////////
|
//////////////////////////
|
//////////////////////////
|
|
|
reg parity;
|
reg parity;
|
integer i, j, k;
|
integer i, j, k;
|
|
|
reg [32:0] rate;
|
reg [32:0] rate;
|
reg [1:0] configuration;
|
reg [1:0] configuration;
|
|
|
|
|
////wait////
|
////wait////
|
task WAIT
|
task WAIT
|
(
|
(
|
input reg [15:0] periods
|
input reg [15:0] periods
|
);
|
);
|
begin
|
begin
|
for (i=0; i<periods; i=i+1)
|
for (i=0; i<periods; i=i+1)
|
begin
|
begin
|
#(`HALF_PERIOD*2);
|
#(`HALF_PERIOD*2);
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////reset all////
|
////reset all////
|
task RESET_ALL ();
|
task RESET_ALL ();
|
begin
|
begin
|
CLK_50MHZ = 1'b0;
|
CLK_50MHZ = 1'b0;
|
RST = 1'b1;
|
RST = 1'b1;
|
rx = 1'b1;
|
rx = 1'b1;
|
#(`HALF_PERIOD/2);
|
#(`HALF_PERIOD/2);
|
RST = 1;
|
RST = 1;
|
#(`HALF_PERIOD*6);
|
#(`HALF_PERIOD*6);
|
RST = 0;
|
RST = 0;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task UART_CFG
|
task UART_CFG
|
(
|
(
|
input reg [32:0] rate_i,
|
input reg [32:0] rate_i,
|
input reg [1:0] configuration_i
|
input reg [1:0] configuration_i
|
);
|
);
|
begin
|
begin
|
rate = rate_i;
|
rate = rate_i;
|
configuration = configuration_i;
|
configuration = configuration_i;
|
end
|
end
|
endtask
|
endtask
|
|
|
////Send byte to UART////
|
////Send byte to UART////
|
|
|
task UART_SEND
|
task UART_SEND
|
(
|
(
|
input reg [7:0] send_byte
|
input reg [7:0] send_byte
|
);
|
);
|
begin
|
begin
|
parity = 0;
|
parity = 0;
|
//start
|
//start
|
rx = 1'b0;
|
rx = 1'b0;
|
#rate;
|
#rate;
|
//sending data
|
//sending data
|
for (i=0; i<8; i=i+1)
|
for (i=0; i<8; i=i+1)
|
begin
|
begin
|
rx = send_byte[0];
|
rx = send_byte[0];
|
#rate;
|
#rate;
|
parity = parity ^ send_byte[0];
|
parity = parity ^ send_byte[0];
|
send_byte = send_byte >> 1;
|
send_byte = send_byte >> 1;
|
end
|
end
|
//parity
|
//parity
|
if (configuration != 2'b00)
|
if (configuration != 2'b00)
|
begin
|
begin
|
if (configuration == 2'b10)
|
if (configuration == 2'b10)
|
begin
|
begin
|
rx = parity;
|
rx = parity;
|
#rate;
|
#rate;
|
end
|
end
|
else if (configuration == 2'b01)
|
else if (configuration == 2'b01)
|
begin
|
begin
|
rx = ~parity;
|
rx = ~parity;
|
#rate;
|
#rate;
|
end
|
end
|
end
|
end
|
//stop;
|
//stop;
|
rx = 1'b1;
|
rx = 1'b1;
|
#rate;
|
#rate;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_hreset ();
|
task pss_hreset ();
|
begin
|
begin
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`RST_CMD);
|
UART_SEND(`RST_CMD);
|
end
|
end
|
endtask
|
endtask
|
|
|
task pss_sendbyte
|
task pss_sendbyte
|
(
|
(
|
input reg [7:0] databyte
|
input reg [7:0] databyte
|
);
|
);
|
begin
|
begin
|
if ((databyte == `SYNC_BYTE) || (databyte == `ESCAPE_BYTE))
|
if ((databyte == `SYNC_BYTE) || (databyte == `ESCAPE_BYTE))
|
UART_SEND(`ESCAPE_BYTE);
|
UART_SEND(`ESCAPE_BYTE);
|
end
|
end
|
UART_SEND(databyte);
|
UART_SEND(databyte);
|
endtask
|
endtask
|
|
|
|
|
task pss_sendword_le
|
task pss_sendword_le
|
(
|
(
|
input reg [31:0] dataword
|
input reg [31:0] dataword
|
);
|
);
|
begin
|
begin
|
pss_sendbyte(dataword[7:0]);
|
pss_sendbyte(dataword[7:0]);
|
pss_sendbyte(dataword[15:8]);
|
pss_sendbyte(dataword[15:8]);
|
pss_sendbyte(dataword[23:16]);
|
pss_sendbyte(dataword[23:16]);
|
pss_sendbyte(dataword[31:24]);
|
pss_sendbyte(dataword[31:24]);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_sendword_be
|
task pss_sendword_be
|
(
|
(
|
input reg [31:0] dataword
|
input reg [31:0] dataword
|
);
|
);
|
begin
|
begin
|
pss_sendbyte(dataword[31:24]);
|
pss_sendbyte(dataword[31:24]);
|
pss_sendbyte(dataword[23:16]);
|
pss_sendbyte(dataword[23:16]);
|
pss_sendbyte(dataword[15:8]);
|
pss_sendbyte(dataword[15:8]);
|
pss_sendbyte(dataword[7:0]);
|
pss_sendbyte(dataword[7:0]);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_wr_single
|
task pss_wr_single
|
(
|
(
|
input reg [31:0] wr_addr,
|
input reg [31:0] wr_addr,
|
input reg [31:0] wr_data
|
input reg [31:0] wr_data
|
);
|
);
|
begin
|
begin
|
|
|
// header
|
// header
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`WR_CMD);
|
UART_SEND(`WR_CMD);
|
|
|
// address
|
// address
|
pss_sendword_le(wr_addr);
|
pss_sendword_le(wr_addr);
|
|
|
// length
|
// length
|
pss_sendword_le(32'h4);
|
pss_sendword_le(32'h4);
|
|
|
// data
|
// data
|
pss_sendword_le(wr_data);
|
pss_sendword_le(wr_data);
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_rd_single
|
task pss_rd_single
|
(
|
(
|
input reg [31:0] wr_addr
|
input reg [31:0] wr_addr
|
);
|
);
|
begin
|
begin
|
|
|
// header
|
// header
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`RD_CMD);
|
UART_SEND(`RD_CMD);
|
|
|
// address
|
// address
|
pss_sendword_le(wr_addr);
|
pss_sendword_le(wr_addr);
|
|
|
// length
|
// length
|
pss_sendword_le(32'h4);
|
pss_sendword_le(32'h4);
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_reset ();
|
task pss_reset ();
|
begin
|
begin
|
pss_wr_single(REG_CPU_CONTROL_ADDR, 32'h1);
|
pss_wr_single(REG_CPU_CONTROL_ADDR, 32'h1);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_start ();
|
task pss_start ();
|
begin
|
begin
|
pss_wr_single(REG_CPU_CONTROL_ADDR, 32'h0);
|
pss_wr_single(REG_CPU_CONTROL_ADDR, 32'h0);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_restart ();
|
task pss_restart ();
|
begin
|
begin
|
pss_reset();
|
pss_reset();
|
pss_start();
|
pss_start();
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task pss_sgi ();
|
task pss_sgi ();
|
begin
|
begin
|
pss_wr_single(REG_SGI_ADDR, 32'h0);
|
pss_wr_single(REG_SGI_ADDR, 32'h0);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task dma_test_wr ();
|
task dma_test_wr ();
|
begin
|
begin
|
// data
|
// data
|
pss_wr_single(32'h00000008, 32'h123455aa);
|
pss_wr_single(32'h00000008, 32'h123455aa);
|
pss_wr_single(32'h0000000C, 32'h07bb07bb);
|
pss_wr_single(32'h0000000C, 32'h07bb07bb);
|
pss_wr_single(32'h00000010, 32'h23344556);
|
pss_wr_single(32'h00000010, 32'h23344556);
|
pss_wr_single(32'h00000014, 32'h89abcdef);
|
pss_wr_single(32'h00000014, 32'h89abcdef);
|
|
|
// source address
|
// source address
|
pss_wr_single(REG_DMA_SOURCEADDR_ADDR, 32'h00000008);
|
pss_wr_single(REG_DMA_SOURCEADDR_ADDR, 32'h00000008);
|
|
|
// dest address
|
// dest address
|
pss_wr_single(REG_DMA_DESTADDR_ADDR, 32'h8a000000);
|
pss_wr_single(REG_DMA_DESTADDR_ADDR, 32'h8a000000);
|
|
|
// size
|
// size
|
pss_wr_single(REG_DMA_SIZE_ADDR, 32'd16);
|
pss_wr_single(REG_DMA_SIZE_ADDR, 32'd16);
|
|
|
// command
|
// command
|
pss_wr_single(REG_DMA_CONTROL_ADDR, 32'h00000006);
|
pss_wr_single(REG_DMA_CONTROL_ADDR, 32'h00000006);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task dma_test_rd ();
|
task dma_test_rd ();
|
begin
|
begin
|
// source address
|
// source address
|
pss_wr_single(REG_DMA_SOURCEADDR_ADDR, 32'h8C000000);
|
pss_wr_single(REG_DMA_SOURCEADDR_ADDR, 32'h8C000000);
|
|
|
// dest address
|
// dest address
|
pss_wr_single(REG_DMA_DESTADDR_ADDR, 32'h00000010);
|
pss_wr_single(REG_DMA_DESTADDR_ADDR, 32'h00000010);
|
|
|
// size
|
// size
|
pss_wr_single(REG_DMA_SIZE_ADDR, 32'd16);
|
pss_wr_single(REG_DMA_SIZE_ADDR, 32'd16);
|
|
|
// command
|
// command
|
pss_wr_single(REG_DMA_CONTROL_ADDR, 32'h00000004);
|
pss_wr_single(REG_DMA_CONTROL_ADDR, 32'h00000004);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
//////////////////////////
|
//////////////////////////
|
//initial block
|
//initial block
|
initial
|
initial
|
begin
|
begin
|
$display ("### SIMULATION STARTED ###");
|
$display ("### SIMULATION STARTED ###");
|
|
|
SW = 8'h0;
|
SW = 8'h0;
|
RESET_ALL();
|
RESET_ALL();
|
UART_CFG(`DIVIDER_115200, 2'b00);
|
UART_CFG(`DIVIDER_115200, 2'b00);
|
WAIT(50000);
|
WAIT(50000);
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`SYNC_BYTE);
|
UART_SEND(`IDCODE_CMD);
|
UART_SEND(`IDCODE_CMD);
|
pss_hreset();
|
pss_hreset();
|
|
|
dma_test_rd();
|
//dma_test_rd();
|
/*
|
|
pss_restart();
|
pss_restart();
|
pss_sgi();
|
//pss_sgi();
|
pss_sgi();
|
//pss_sgi();
|
pss_sgi();
|
//pss_sgi();
|
pss_wr_single(32'h8a000000, 32'h5aaa5aaa);
|
pss_wr_single(32'h8a000000, 32'h5aaa5aaa);
|
WAIT(50000);
|
WAIT(50000);
|
$display ("### READING MEMORY ###");
|
$display ("### READING MEMORY ###");
|
pss_rd_single(32'h00000000);
|
pss_rd_single(32'h00000000);
|
pss_rd_single(32'h00000004);
|
pss_rd_single(32'h00000004);
|
pss_rd_single(32'h00000008);
|
pss_rd_single(32'h00000008);
|
pss_rd_single(32'h0000000C);
|
pss_rd_single(32'h0000000C);
|
WAIT(777);
|
WAIT(777);
|
pss_rd_single(32'h00000000);
|
pss_rd_single(32'h00000000);
|
pss_rd_single(32'h00000004);
|
pss_rd_single(32'h00000004);
|
pss_rd_single(32'h00000008);
|
pss_rd_single(32'h00000008);
|
pss_rd_single(32'h0000000C);
|
pss_rd_single(32'h0000000C);
|
*/
|
|
|
|
WAIT(50000);
|
WAIT(50000);
|
|
|
$display ("### TEST PROCEDURE FINISHED ###");
|
$display ("### TEST PROCEDURE FINISHED ###");
|
$stop;
|
$stop;
|
end
|
end
|
//
|
//
|
always #`HALF_PERIOD CLK_50MHZ = ~CLK_50MHZ;
|
always #`HALF_PERIOD CLK_50MHZ = ~CLK_50MHZ;
|
|
|
always #50000 SW = SW + 8'h1;
|
always #50000 SW = SW + 8'h1;
|
//
|
//
|
endmodule
|
endmodule
|
|
|