working with memory
This commit is contained in:
@@ -0,0 +1,954 @@
|
||||
$date
|
||||
Wed Sep 2 12:39:25 2026
|
||||
$end
|
||||
$version
|
||||
Icarus Verilog
|
||||
$end
|
||||
$timescale
|
||||
1ps
|
||||
$end
|
||||
$scope module tb $end
|
||||
$var wire 16 ! mem_rdata [15:0] $end
|
||||
$var wire 1 " mem_ready $end
|
||||
$var wire 1 # ready $end
|
||||
$var wire 8 $ rdata [7:0] $end
|
||||
$var wire 1 % mem_wr $end
|
||||
$var wire 16 & mem_wdata [15:0] $end
|
||||
$var wire 1 ' mem_ub_n $end
|
||||
$var wire 1 ( mem_req $end
|
||||
$var wire 1 ) mem_lb_n $end
|
||||
$var wire 22 * mem_addr [21:0] $end
|
||||
$var parameter 32 + ADDR_WIDTH $end
|
||||
$var real 1 , CLK_PERIOD $end
|
||||
$var reg 22 - addr [21:0] $end
|
||||
$var reg 1 . clk $end
|
||||
$var reg 16 / model_rdata [15:0] $end
|
||||
$var reg 1 0 model_ready $end
|
||||
$var reg 1 1 req $end
|
||||
$var reg 1 2 rst $end
|
||||
$var reg 8 3 wdata [7:0] $end
|
||||
$var reg 1 4 wr $end
|
||||
$var integer 32 5 i [31:0] $end
|
||||
$scope module dut $end
|
||||
$var wire 22 6 addr [21:0] $end
|
||||
$var wire 1 . clk $end
|
||||
$var wire 16 7 mem_rdata [15:0] $end
|
||||
$var wire 1 " mem_ready $end
|
||||
$var wire 1 1 req $end
|
||||
$var wire 1 2 rst $end
|
||||
$var wire 8 8 wdata [7:0] $end
|
||||
$var wire 1 4 wr $end
|
||||
$var parameter 32 9 ADDR_WIDTH $end
|
||||
$var parameter 2 : STATE_IDLE $end
|
||||
$var parameter 2 ; STATE_WAIT $end
|
||||
$var reg 22 < addr_reg [21:0] $end
|
||||
$var reg 22 = mem_addr [21:0] $end
|
||||
$var reg 1 ) mem_lb_n $end
|
||||
$var reg 1 ( mem_req $end
|
||||
$var reg 1 ' mem_ub_n $end
|
||||
$var reg 16 > mem_wdata [15:0] $end
|
||||
$var reg 1 % mem_wr $end
|
||||
$var reg 8 ? rdata [7:0] $end
|
||||
$var reg 1 # ready $end
|
||||
$var reg 2 @ state [1:0] $end
|
||||
$upscope $end
|
||||
$scope task read_byte $end
|
||||
$var reg 22 A byte_addr [21:0] $end
|
||||
$var reg 8 B expected [7:0] $end
|
||||
$upscope $end
|
||||
$scope task write_byte $end
|
||||
$var reg 22 C byte_addr [21:0] $end
|
||||
$var reg 8 D data [7:0] $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$comment Show the parameter values. $end
|
||||
$dumpall
|
||||
b1 ;
|
||||
b0 :
|
||||
b10110 9
|
||||
r12.5 ,
|
||||
b10110 +
|
||||
$end
|
||||
#0
|
||||
$dumpvars
|
||||
bx D
|
||||
bx C
|
||||
bx B
|
||||
bx A
|
||||
bx @
|
||||
bx ?
|
||||
bx >
|
||||
bx =
|
||||
bx <
|
||||
b0 8
|
||||
b0 7
|
||||
b0 6
|
||||
b10000000000 5
|
||||
04
|
||||
b0 3
|
||||
12
|
||||
01
|
||||
00
|
||||
b0 /
|
||||
0.
|
||||
b0 -
|
||||
bx *
|
||||
x)
|
||||
x(
|
||||
x'
|
||||
bx &
|
||||
x%
|
||||
bx $
|
||||
x#
|
||||
0"
|
||||
b0 !
|
||||
$end
|
||||
#6250
|
||||
1'
|
||||
1)
|
||||
b0 &
|
||||
b0 >
|
||||
b0 *
|
||||
b0 =
|
||||
0%
|
||||
0(
|
||||
0#
|
||||
b0 $
|
||||
b0 ?
|
||||
b0 <
|
||||
b0 @
|
||||
1.
|
||||
#12500
|
||||
0.
|
||||
#18750
|
||||
1.
|
||||
#25000
|
||||
0.
|
||||
#31250
|
||||
1.
|
||||
#37500
|
||||
0.
|
||||
#43750
|
||||
1.
|
||||
#50000
|
||||
0.
|
||||
#56250
|
||||
b10010 D
|
||||
b0 C
|
||||
02
|
||||
1.
|
||||
#62500
|
||||
0.
|
||||
#68750
|
||||
11
|
||||
14
|
||||
b10010 3
|
||||
b10010 8
|
||||
1.
|
||||
#75000
|
||||
0.
|
||||
#81250
|
||||
01
|
||||
b1 @
|
||||
b10010 &
|
||||
b10010 >
|
||||
0)
|
||||
1%
|
||||
1(
|
||||
1.
|
||||
#87500
|
||||
0.
|
||||
#93750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#100000
|
||||
0.
|
||||
#106250
|
||||
b0 @
|
||||
1#
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#112500
|
||||
0.
|
||||
#118750
|
||||
0#
|
||||
b110100 D
|
||||
b1 C
|
||||
1.
|
||||
#125000
|
||||
0.
|
||||
#131250
|
||||
11
|
||||
b110100 3
|
||||
b110100 8
|
||||
b1 -
|
||||
b1 6
|
||||
1.
|
||||
#137500
|
||||
0.
|
||||
#143750
|
||||
01
|
||||
b1 @
|
||||
b11010000000000 &
|
||||
b11010000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b1 <
|
||||
1.
|
||||
#150000
|
||||
0.
|
||||
#156250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#162500
|
||||
0.
|
||||
#168750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
1.
|
||||
#175000
|
||||
0.
|
||||
#181250
|
||||
0#
|
||||
b1010110 D
|
||||
b10 C
|
||||
1.
|
||||
#187500
|
||||
0.
|
||||
#193750
|
||||
11
|
||||
b1010110 3
|
||||
b1010110 8
|
||||
b10 -
|
||||
b10 6
|
||||
1.
|
||||
#200000
|
||||
0.
|
||||
#206250
|
||||
01
|
||||
b1 @
|
||||
b1010110 &
|
||||
b1010110 >
|
||||
1'
|
||||
0)
|
||||
b1 *
|
||||
b1 =
|
||||
1(
|
||||
b10 <
|
||||
1.
|
||||
#212500
|
||||
0.
|
||||
#218750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#225000
|
||||
0.
|
||||
#231250
|
||||
b0 @
|
||||
1#
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#237500
|
||||
0.
|
||||
#243750
|
||||
0#
|
||||
b1111000 D
|
||||
b11 C
|
||||
1.
|
||||
#250000
|
||||
0.
|
||||
#256250
|
||||
11
|
||||
b1111000 3
|
||||
b1111000 8
|
||||
b11 -
|
||||
b11 6
|
||||
1.
|
||||
#262500
|
||||
0.
|
||||
#268750
|
||||
01
|
||||
b1 @
|
||||
b111100000000000 &
|
||||
b111100000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b11 <
|
||||
1.
|
||||
#275000
|
||||
0.
|
||||
#281250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#287500
|
||||
0.
|
||||
#293750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
1.
|
||||
#300000
|
||||
0.
|
||||
#306250
|
||||
0#
|
||||
b10010 B
|
||||
b0 A
|
||||
1.
|
||||
#312500
|
||||
0.
|
||||
#318750
|
||||
11
|
||||
04
|
||||
b0 -
|
||||
b0 6
|
||||
1.
|
||||
#325000
|
||||
0.
|
||||
#331250
|
||||
01
|
||||
b1 @
|
||||
b1111000 &
|
||||
b1111000 >
|
||||
1'
|
||||
0)
|
||||
b0 *
|
||||
b0 =
|
||||
0%
|
||||
1(
|
||||
b0 <
|
||||
1.
|
||||
#337500
|
||||
0.
|
||||
#343750
|
||||
1"
|
||||
10
|
||||
b11010000010010 !
|
||||
b11010000010010 7
|
||||
b11010000010010 /
|
||||
0(
|
||||
1.
|
||||
#350000
|
||||
0.
|
||||
#356250
|
||||
b0 @
|
||||
1#
|
||||
b10010 $
|
||||
b10010 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#362500
|
||||
0.
|
||||
#368750
|
||||
0#
|
||||
b110100 B
|
||||
b1 A
|
||||
1.
|
||||
#375000
|
||||
0.
|
||||
#381250
|
||||
11
|
||||
b1 -
|
||||
b1 6
|
||||
1.
|
||||
#387500
|
||||
0.
|
||||
#393750
|
||||
01
|
||||
b1 @
|
||||
b111100000000000 &
|
||||
b111100000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b1 <
|
||||
1.
|
||||
#400000
|
||||
0.
|
||||
#406250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#412500
|
||||
0.
|
||||
#418750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b110100 $
|
||||
b110100 ?
|
||||
1.
|
||||
#425000
|
||||
0.
|
||||
#431250
|
||||
0#
|
||||
b1010110 B
|
||||
b10 A
|
||||
1.
|
||||
#437500
|
||||
0.
|
||||
#443750
|
||||
11
|
||||
b10 -
|
||||
b10 6
|
||||
1.
|
||||
#450000
|
||||
0.
|
||||
#456250
|
||||
01
|
||||
b1 @
|
||||
b1111000 &
|
||||
b1111000 >
|
||||
1'
|
||||
0)
|
||||
b1 *
|
||||
b1 =
|
||||
1(
|
||||
b10 <
|
||||
1.
|
||||
#462500
|
||||
0.
|
||||
#468750
|
||||
1"
|
||||
10
|
||||
b111100001010110 !
|
||||
b111100001010110 7
|
||||
b111100001010110 /
|
||||
0(
|
||||
1.
|
||||
#475000
|
||||
0.
|
||||
#481250
|
||||
b0 @
|
||||
1#
|
||||
b1010110 $
|
||||
b1010110 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#487500
|
||||
0.
|
||||
#493750
|
||||
0#
|
||||
b1111000 B
|
||||
b11 A
|
||||
1.
|
||||
#500000
|
||||
0.
|
||||
#506250
|
||||
11
|
||||
b11 -
|
||||
b11 6
|
||||
1.
|
||||
#512500
|
||||
0.
|
||||
#518750
|
||||
01
|
||||
b1 @
|
||||
b111100000000000 &
|
||||
b111100000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b11 <
|
||||
1.
|
||||
#525000
|
||||
0.
|
||||
#531250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#537500
|
||||
0.
|
||||
#543750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b1111000 $
|
||||
b1111000 ?
|
||||
1.
|
||||
#550000
|
||||
0.
|
||||
#556250
|
||||
0#
|
||||
b110100 D
|
||||
b10000 C
|
||||
1.
|
||||
#562500
|
||||
0.
|
||||
#568750
|
||||
11
|
||||
14
|
||||
b110100 3
|
||||
b110100 8
|
||||
b10000 -
|
||||
b10000 6
|
||||
1.
|
||||
#575000
|
||||
0.
|
||||
#581250
|
||||
01
|
||||
b1 @
|
||||
b110100 &
|
||||
b110100 >
|
||||
1'
|
||||
0)
|
||||
b1000 *
|
||||
b1000 =
|
||||
1%
|
||||
1(
|
||||
b10000 <
|
||||
1.
|
||||
#587500
|
||||
0.
|
||||
#593750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#600000
|
||||
0.
|
||||
#606250
|
||||
b0 @
|
||||
1#
|
||||
b1010110 $
|
||||
b1010110 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#612500
|
||||
0.
|
||||
#618750
|
||||
0#
|
||||
b10010 D
|
||||
b10001 C
|
||||
1.
|
||||
#625000
|
||||
0.
|
||||
#631250
|
||||
11
|
||||
b10010 3
|
||||
b10010 8
|
||||
b10001 -
|
||||
b10001 6
|
||||
1.
|
||||
#637500
|
||||
0.
|
||||
#643750
|
||||
01
|
||||
b1 @
|
||||
b1001000000000 &
|
||||
b1001000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b10001 <
|
||||
1.
|
||||
#650000
|
||||
0.
|
||||
#656250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#662500
|
||||
0.
|
||||
#668750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b1111000 $
|
||||
b1111000 ?
|
||||
1.
|
||||
#675000
|
||||
0.
|
||||
#681250
|
||||
0#
|
||||
b10101010 D
|
||||
b10000 C
|
||||
1.
|
||||
#687500
|
||||
0.
|
||||
#693750
|
||||
11
|
||||
b10101010 3
|
||||
b10101010 8
|
||||
b10000 -
|
||||
b10000 6
|
||||
1.
|
||||
#700000
|
||||
0.
|
||||
#706250
|
||||
01
|
||||
b1 @
|
||||
b10101010 &
|
||||
b10101010 >
|
||||
1'
|
||||
0)
|
||||
1(
|
||||
b10000 <
|
||||
1.
|
||||
#712500
|
||||
0.
|
||||
#718750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#725000
|
||||
0.
|
||||
#731250
|
||||
b0 @
|
||||
1#
|
||||
b1010110 $
|
||||
b1010110 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#737500
|
||||
0.
|
||||
#743750
|
||||
0#
|
||||
b10111011 D
|
||||
b10001 C
|
||||
1.
|
||||
#750000
|
||||
0.
|
||||
#756250
|
||||
11
|
||||
b10111011 3
|
||||
b10111011 8
|
||||
b10001 -
|
||||
b10001 6
|
||||
1.
|
||||
#762500
|
||||
0.
|
||||
#768750
|
||||
01
|
||||
b1 @
|
||||
b1011101100000000 &
|
||||
b1011101100000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b10001 <
|
||||
1.
|
||||
#775000
|
||||
0.
|
||||
#781250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#787500
|
||||
0.
|
||||
#793750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b1111000 $
|
||||
b1111000 ?
|
||||
1.
|
||||
#800000
|
||||
0.
|
||||
#806250
|
||||
0#
|
||||
b11111111 D
|
||||
b100000 C
|
||||
1.
|
||||
#812500
|
||||
0.
|
||||
#818750
|
||||
11
|
||||
b11111111 3
|
||||
b11111111 8
|
||||
b100000 -
|
||||
b100000 6
|
||||
1.
|
||||
#825000
|
||||
0.
|
||||
#831250
|
||||
01
|
||||
b1 @
|
||||
b11111111 &
|
||||
b11111111 >
|
||||
1'
|
||||
0)
|
||||
b10000 *
|
||||
b10000 =
|
||||
1(
|
||||
b100000 <
|
||||
1.
|
||||
#837500
|
||||
0.
|
||||
#843750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#850000
|
||||
0.
|
||||
#856250
|
||||
b0 @
|
||||
1#
|
||||
b1010110 $
|
||||
b1010110 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#862500
|
||||
0.
|
||||
#868750
|
||||
0#
|
||||
b10000000 D
|
||||
b100001 C
|
||||
1.
|
||||
#875000
|
||||
0.
|
||||
#881250
|
||||
11
|
||||
b10000000 3
|
||||
b10000000 8
|
||||
b100001 -
|
||||
b100001 6
|
||||
1.
|
||||
#887500
|
||||
0.
|
||||
#893750
|
||||
01
|
||||
b1 @
|
||||
b1000000000000000 &
|
||||
b1000000000000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b100001 <
|
||||
1.
|
||||
#900000
|
||||
0.
|
||||
#906250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
1.
|
||||
#912500
|
||||
0.
|
||||
#918750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b1111000 $
|
||||
b1111000 ?
|
||||
1.
|
||||
#925000
|
||||
0.
|
||||
#931250
|
||||
0#
|
||||
b1111111 D
|
||||
b100010 C
|
||||
1.
|
||||
#937500
|
||||
0.
|
||||
#943750
|
||||
11
|
||||
b1111111 3
|
||||
b1111111 8
|
||||
b100010 -
|
||||
b100010 6
|
||||
1.
|
||||
#950000
|
||||
0.
|
||||
#956250
|
||||
01
|
||||
b1 @
|
||||
b1111111 &
|
||||
b1111111 >
|
||||
1'
|
||||
0)
|
||||
b10001 *
|
||||
b10001 =
|
||||
1(
|
||||
b100010 <
|
||||
1.
|
||||
#962500
|
||||
0.
|
||||
#968750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#975000
|
||||
0.
|
||||
#981250
|
||||
b0 @
|
||||
1#
|
||||
b1010110 $
|
||||
b1010110 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#987500
|
||||
0.
|
||||
#993750
|
||||
0#
|
||||
b11111111 B
|
||||
b100000 A
|
||||
1.
|
||||
#1000000
|
||||
0.
|
||||
#1006250
|
||||
11
|
||||
04
|
||||
b100000 -
|
||||
b100000 6
|
||||
1.
|
||||
#1012500
|
||||
0.
|
||||
#1018750
|
||||
01
|
||||
b1 @
|
||||
b10000 *
|
||||
b10000 =
|
||||
0%
|
||||
1(
|
||||
b100000 <
|
||||
1.
|
||||
#1025000
|
||||
0.
|
||||
#1031250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
b1000000011111111 !
|
||||
b1000000011111111 7
|
||||
b1000000011111111 /
|
||||
1.
|
||||
#1037500
|
||||
0.
|
||||
#1043750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b11111111 $
|
||||
b11111111 ?
|
||||
1.
|
||||
#1050000
|
||||
0.
|
||||
#1056250
|
||||
0#
|
||||
b10000000 B
|
||||
b100001 A
|
||||
1.
|
||||
#1062500
|
||||
0.
|
||||
#1068750
|
||||
11
|
||||
b100001 -
|
||||
b100001 6
|
||||
1.
|
||||
#1075000
|
||||
0.
|
||||
#1081250
|
||||
01
|
||||
b1 @
|
||||
b111111100000000 &
|
||||
b111111100000000 >
|
||||
0'
|
||||
1)
|
||||
1(
|
||||
b100001 <
|
||||
1.
|
||||
#1087500
|
||||
0.
|
||||
#1093750
|
||||
1"
|
||||
10
|
||||
0(
|
||||
1.
|
||||
#1100000
|
||||
0.
|
||||
#1106250
|
||||
b0 @
|
||||
1#
|
||||
b10000000 $
|
||||
b10000000 ?
|
||||
0"
|
||||
00
|
||||
1.
|
||||
#1112500
|
||||
0.
|
||||
#1118750
|
||||
0#
|
||||
b1111111 B
|
||||
b100010 A
|
||||
1.
|
||||
#1125000
|
||||
0.
|
||||
#1131250
|
||||
11
|
||||
b100010 -
|
||||
b100010 6
|
||||
1.
|
||||
#1137500
|
||||
0.
|
||||
#1143750
|
||||
01
|
||||
b1 @
|
||||
b1111111 &
|
||||
b1111111 >
|
||||
1'
|
||||
0)
|
||||
b10001 *
|
||||
b10001 =
|
||||
1(
|
||||
b100010 <
|
||||
1.
|
||||
#1150000
|
||||
0.
|
||||
#1156250
|
||||
0(
|
||||
1"
|
||||
10
|
||||
b1111111 !
|
||||
b1111111 7
|
||||
b1111111 /
|
||||
1.
|
||||
#1162500
|
||||
0.
|
||||
#1168750
|
||||
0"
|
||||
00
|
||||
b0 @
|
||||
1#
|
||||
b1111111 $
|
||||
b1111111 ?
|
||||
1.
|
||||
#1175000
|
||||
0.
|
||||
#1181250
|
||||
0#
|
||||
1.
|
||||
Executable
+550
@@ -0,0 +1,550 @@
|
||||
#! /opt/homebrew/Cellar/icarus-verilog/13.0/bin/vvp
|
||||
:ivl_version "13.0 (stable)" "(v13_0)";
|
||||
:ivl_delay_selection "TYPICAL";
|
||||
:vpi_time_precision - 12;
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/system.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_sys.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_textio.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2005_math.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/va_math.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2009.vpi";
|
||||
S_0x102cce1c0 .scope package, "$unit" "$unit" 2 1;
|
||||
.timescale 0 0;
|
||||
S_0x102cc09e0 .scope module, "tb" "tb" 3 3;
|
||||
.timescale -9 -12;
|
||||
P_0x102ccf000 .param/l "ADDR_WIDTH" 1 3 5, +C4<00000000000000000000000000010110>;
|
||||
P_0x102ccf040 .param/real "CLK_PERIOD" 1 3 6, Cr<m6400000000000000gfc5>; value=12.5000
|
||||
L_0x102ccff60 .functor BUFZ 16, v0x74b08cdc0_0, C4<0000000000000000>, C4<0000000000000000>, C4<0000000000000000>;
|
||||
L_0x102ccf620 .functor BUFZ 1, v0x74b08ce60_0, C4<0>, C4<0>, C4<0>;
|
||||
v0x74b08c640_0 .var "addr", 21 0;
|
||||
v0x74b08c6e0_0 .var "clk", 0 0;
|
||||
v0x74b08c780_0 .var/i "i", 31 0;
|
||||
v0x74b08c820_0 .net "mem_addr", 21 0, v0x102ccd820_0; 1 drivers
|
||||
v0x74b08c8c0_0 .net "mem_lb_n", 0 0, v0x102ccf580_0; 1 drivers
|
||||
v0x74b08c960_0 .net "mem_rdata", 15 0, L_0x102ccff60; 1 drivers
|
||||
v0x74b08ca00_0 .net "mem_ready", 0 0, L_0x102ccf620; 1 drivers
|
||||
v0x74b08caa0_0 .net "mem_req", 0 0, v0x102ccfb40_0; 1 drivers
|
||||
v0x74b08cb40_0 .net "mem_ub_n", 0 0, v0x102ccfbe0_0; 1 drivers
|
||||
v0x74b08cbe0_0 .net "mem_wdata", 15 0, v0x102ccfc80_0; 1 drivers
|
||||
v0x74b08cc80_0 .net "mem_wr", 0 0, v0x102ccfd20_0; 1 drivers
|
||||
v0x74b08cd20 .array "memory", 1023 0, 15 0;
|
||||
v0x74b08cdc0_0 .var "model_rdata", 15 0;
|
||||
v0x74b08ce60_0 .var "model_ready", 0 0;
|
||||
v0x74b08cf00_0 .net/s "rdata", 7 0, v0x102ccfdc0_0; 1 drivers
|
||||
v0x74b08cfa0_0 .net "ready", 0 0, v0x74b08c000_0; 1 drivers
|
||||
v0x74b08d040_0 .var "req", 0 0;
|
||||
v0x74b08d0e0_0 .var "rst", 0 0;
|
||||
v0x74b08d180_0 .var/s "wdata", 7 0;
|
||||
v0x74b08d220_0 .var "wr", 0 0;
|
||||
S_0x102cc0b60 .scope module, "dut" "int8_memory_access" 3 43, 4 1 0, S_0x102cc09e0;
|
||||
.timescale -9 -12;
|
||||
.port_info 0 /INPUT 1 "clk";
|
||||
.port_info 1 /INPUT 1 "rst";
|
||||
.port_info 2 /INPUT 1 "req";
|
||||
.port_info 3 /INPUT 1 "wr";
|
||||
.port_info 4 /INPUT 22 "addr";
|
||||
.port_info 5 /INPUT 8 "wdata";
|
||||
.port_info 6 /OUTPUT 8 "rdata";
|
||||
.port_info 7 /OUTPUT 1 "ready";
|
||||
.port_info 8 /OUTPUT 1 "mem_req";
|
||||
.port_info 9 /OUTPUT 1 "mem_wr";
|
||||
.port_info 10 /OUTPUT 22 "mem_addr";
|
||||
.port_info 11 /OUTPUT 16 "mem_wdata";
|
||||
.port_info 12 /OUTPUT 1 "mem_lb_n";
|
||||
.port_info 13 /OUTPUT 1 "mem_ub_n";
|
||||
.port_info 14 /INPUT 16 "mem_rdata";
|
||||
.port_info 15 /INPUT 1 "mem_ready";
|
||||
P_0x102cce340 .param/l "ADDR_WIDTH" 0 4 2, +C4<00000000000000000000000000010110>;
|
||||
P_0x102cce380 .param/l "STATE_IDLE" 1 4 40, C4<00>;
|
||||
P_0x102cce3c0 .param/l "STATE_WAIT" 1 4 41, C4<01>;
|
||||
v0x102ccb170_0 .net "addr", 21 0, v0x74b08c640_0; 1 drivers
|
||||
v0x102ccd070_0 .var "addr_reg", 21 0;
|
||||
v0x102ccebc0_0 .net "clk", 0 0, v0x74b08c6e0_0; 1 drivers
|
||||
v0x102ccd820_0 .var "mem_addr", 21 0;
|
||||
v0x102ccf580_0 .var "mem_lb_n", 0 0;
|
||||
v0x102ccfa00_0 .net "mem_rdata", 15 0, L_0x102ccff60; alias, 1 drivers
|
||||
v0x102ccfaa0_0 .net "mem_ready", 0 0, L_0x102ccf620; alias, 1 drivers
|
||||
v0x102ccfb40_0 .var "mem_req", 0 0;
|
||||
v0x102ccfbe0_0 .var "mem_ub_n", 0 0;
|
||||
v0x102ccfc80_0 .var "mem_wdata", 15 0;
|
||||
v0x102ccfd20_0 .var "mem_wr", 0 0;
|
||||
v0x102ccfdc0_0 .var/s "rdata", 7 0;
|
||||
v0x74b08c000_0 .var "ready", 0 0;
|
||||
v0x74b08c0a0_0 .net "req", 0 0, v0x74b08d040_0; 1 drivers
|
||||
v0x74b08c140_0 .net "rst", 0 0, v0x74b08d0e0_0; 1 drivers
|
||||
v0x74b08c1e0_0 .var "state", 1 0;
|
||||
v0x74b08c280_0 .net/s "wdata", 7 0, v0x74b08d180_0; 1 drivers
|
||||
v0x74b08c320_0 .net "wr", 0 0, v0x74b08d220_0; 1 drivers
|
||||
E_0x74ac1b040 .event posedge, v0x102ccebc0_0;
|
||||
S_0x102cd1180 .scope task, "read_byte" "read_byte" 3 174, 3 174 0, S_0x102cc09e0;
|
||||
.timescale -9 -12;
|
||||
v0x74b08c3c0_0 .var "byte_addr", 21 0;
|
||||
v0x74b08c460_0 .var/s "expected", 7 0;
|
||||
E_0x74ac1b080 .event anyedge, v0x74b08c000_0;
|
||||
TD_tb.read_byte ;
|
||||
%wait E_0x74ac1b040;
|
||||
%load/vec4 v0x74b08c3c0_0;
|
||||
%assign/vec4 v0x74b08c640_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08d220_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x74b08d040_0, 0;
|
||||
%wait E_0x74ac1b040;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08d040_0, 0;
|
||||
T_0.0 ;
|
||||
%load/vec4 v0x74b08cfa0_0;
|
||||
%cmpi/ne 1, 0, 1;
|
||||
%jmp/0xz T_0.1, 6;
|
||||
%wait E_0x74ac1b080;
|
||||
%jmp T_0.0;
|
||||
T_0.1 ;
|
||||
%load/vec4 v0x74b08cf00_0;
|
||||
%load/vec4 v0x74b08c460_0;
|
||||
%cmp/ne;
|
||||
%jmp/0xz T_0.2, 6;
|
||||
%vpi_call/w 3 195 "$display", "READ BYTE addr=0x%08x FAIL got=0x%02x expected=0x%02x", v0x74b08c3c0_0, v0x74b08cf00_0, v0x74b08c460_0 {0 0 0};
|
||||
%vpi_call/w 3 202 "$fatal" {0 0 0};
|
||||
%jmp T_0.3;
|
||||
T_0.2 ;
|
||||
%vpi_call/w 3 206 "$display", "READ BYTE addr=0x%08x data=0x%02x PASS", v0x74b08c3c0_0, v0x74b08cf00_0 {0 0 0};
|
||||
T_0.3 ;
|
||||
%wait E_0x74ac1b040;
|
||||
%end;
|
||||
S_0x102cd1300 .scope task, "write_byte" "write_byte" 3 138, 3 138 0, S_0x102cc09e0;
|
||||
.timescale -9 -12;
|
||||
v0x74b08c500_0 .var "byte_addr", 21 0;
|
||||
v0x74b08c5a0_0 .var/s "data", 7 0;
|
||||
TD_tb.write_byte ;
|
||||
%wait E_0x74ac1b040;
|
||||
%load/vec4 v0x74b08c500_0;
|
||||
%assign/vec4 v0x74b08c640_0, 0;
|
||||
%load/vec4 v0x74b08c5a0_0;
|
||||
%assign/vec4 v0x74b08d180_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x74b08d220_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x74b08d040_0, 0;
|
||||
%wait E_0x74ac1b040;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08d040_0, 0;
|
||||
T_1.4 ;
|
||||
%load/vec4 v0x74b08cfa0_0;
|
||||
%cmpi/ne 1, 0, 1;
|
||||
%jmp/0xz T_1.5, 6;
|
||||
%wait E_0x74ac1b080;
|
||||
%jmp T_1.4;
|
||||
T_1.5 ;
|
||||
%vpi_call/w 3 158 "$display", "WRITE BYTE addr=0x%08x data=0x%02x PASS", v0x74b08c500_0, v0x74b08c5a0_0 {0 0 0};
|
||||
%wait E_0x74ac1b040;
|
||||
%end;
|
||||
.scope S_0x102cc0b60;
|
||||
T_2 ;
|
||||
%wait E_0x74ac1b040;
|
||||
%load/vec4 v0x74b08c140_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.0, 8;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x74b08c1e0_0, 0;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%assign/vec4 v0x102ccd070_0, 0;
|
||||
%pushi/vec4 0, 0, 8;
|
||||
%assign/vec4 v0x102ccfdc0_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08c000_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccfb40_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccfd20_0, 0;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%assign/vec4 v0x102ccd820_0, 0;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x102ccfc80_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccf580_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccfbe0_0, 0;
|
||||
%jmp T_2.1;
|
||||
T_2.0 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08c000_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccfb40_0, 0;
|
||||
%load/vec4 v0x74b08c1e0_0;
|
||||
%dup/vec4;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%cmp/u;
|
||||
%jmp/1 T_2.2, 6;
|
||||
%dup/vec4;
|
||||
%pushi/vec4 1, 0, 2;
|
||||
%cmp/u;
|
||||
%jmp/1 T_2.3, 6;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x74b08c1e0_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccfb40_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccf580_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccfbe0_0, 0;
|
||||
%jmp T_2.5;
|
||||
T_2.2 ;
|
||||
%load/vec4 v0x74b08c0a0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.6, 8;
|
||||
%load/vec4 v0x102ccb170_0;
|
||||
%assign/vec4 v0x102ccd070_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccfb40_0, 0;
|
||||
%load/vec4 v0x74b08c320_0;
|
||||
%assign/vec4 v0x102ccfd20_0, 0;
|
||||
%load/vec4 v0x102ccb170_0;
|
||||
%ix/load 4, 1, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%shiftr 4;
|
||||
%assign/vec4 v0x102ccd820_0, 0;
|
||||
%load/vec4 v0x102ccb170_0;
|
||||
%parti/s 1, 0, 2;
|
||||
%cmpi/e 0, 0, 1;
|
||||
%jmp/0xz T_2.8, 4;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccf580_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccfbe0_0, 0;
|
||||
%pushi/vec4 0, 0, 8;
|
||||
%load/vec4 v0x74b08c280_0;
|
||||
%concat/vec4; draw_concat_vec4
|
||||
%assign/vec4 v0x102ccfc80_0, 0;
|
||||
%jmp T_2.9;
|
||||
T_2.8 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x102ccf580_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x102ccfbe0_0, 0;
|
||||
%load/vec4 v0x74b08c280_0;
|
||||
%concati/vec4 0, 0, 8;
|
||||
%assign/vec4 v0x102ccfc80_0, 0;
|
||||
T_2.9 ;
|
||||
%pushi/vec4 1, 0, 2;
|
||||
%assign/vec4 v0x74b08c1e0_0, 0;
|
||||
T_2.6 ;
|
||||
%jmp T_2.5;
|
||||
T_2.3 ;
|
||||
%load/vec4 v0x102ccfaa0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.10, 8;
|
||||
%load/vec4 v0x102ccd070_0;
|
||||
%parti/s 1, 0, 2;
|
||||
%cmpi/e 0, 0, 1;
|
||||
%jmp/0xz T_2.12, 4;
|
||||
%load/vec4 v0x102ccfa00_0;
|
||||
%parti/s 8, 0, 2;
|
||||
%assign/vec4 v0x102ccfdc0_0, 0;
|
||||
%jmp T_2.13;
|
||||
T_2.12 ;
|
||||
%load/vec4 v0x102ccfa00_0;
|
||||
%parti/s 8, 8, 5;
|
||||
%assign/vec4 v0x102ccfdc0_0, 0;
|
||||
T_2.13 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x74b08c000_0, 0;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x74b08c1e0_0, 0;
|
||||
T_2.10 ;
|
||||
%jmp T_2.5;
|
||||
T_2.5 ;
|
||||
%pop/vec4 1;
|
||||
T_2.1 ;
|
||||
%jmp T_2;
|
||||
.thread T_2;
|
||||
.scope S_0x102cc09e0;
|
||||
T_3 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x74b08c6e0_0, 0, 1;
|
||||
T_3.0 ;
|
||||
%delay 6250, 0;
|
||||
%load/vec4 v0x74b08c6e0_0;
|
||||
%inv;
|
||||
%store/vec4 v0x74b08c6e0_0, 0, 1;
|
||||
%jmp T_3.0;
|
||||
T_3.1 ;
|
||||
%end;
|
||||
.thread T_3;
|
||||
.scope S_0x102cc09e0;
|
||||
T_4 ;
|
||||
%vpi_call/w 3 99 "$dumpfile", "sim/int8_memory_access.vcd" {0 0 0};
|
||||
%vpi_call/w 3 100 "$dumpvars", 32'sb00000000000000000000000000000000, S_0x102cc09e0 {0 0 0};
|
||||
%end;
|
||||
.thread T_4;
|
||||
.scope S_0x102cc09e0;
|
||||
T_5 ;
|
||||
%wait E_0x74ac1b040;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x74b08ce60_0, 0;
|
||||
%load/vec4 v0x74b08caa0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_5.0, 8;
|
||||
%load/vec4 v0x74b08cc80_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_5.2, 8;
|
||||
%load/vec4 v0x74b08c8c0_0;
|
||||
%nor/r;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_5.4, 8;
|
||||
%load/vec4 v0x74b08cbe0_0;
|
||||
%parti/s 8, 0, 2;
|
||||
%ix/getv 3, v0x74b08c820_0;
|
||||
%ix/load 4, 0, 0; Constant delay
|
||||
%assign/vec4/a/d v0x74b08cd20, 0, 4;
|
||||
T_5.4 ;
|
||||
%load/vec4 v0x74b08cb40_0;
|
||||
%nor/r;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_5.6, 8;
|
||||
%load/vec4 v0x74b08cbe0_0;
|
||||
%parti/s 8, 8, 5;
|
||||
%ix/getv 3, v0x74b08c820_0;
|
||||
%ix/load 4, 8, 0; part off
|
||||
%ix/load 5, 0, 0; Constant delay
|
||||
%assign/vec4/a/d v0x74b08cd20, 4, 5;
|
||||
T_5.6 ;
|
||||
%jmp T_5.3;
|
||||
T_5.2 ;
|
||||
%ix/getv 4, v0x74b08c820_0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%assign/vec4 v0x74b08cdc0_0, 0;
|
||||
T_5.3 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x74b08ce60_0, 0;
|
||||
T_5.0 ;
|
||||
%jmp T_5;
|
||||
.thread T_5;
|
||||
.scope S_0x102cc09e0;
|
||||
T_6 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x74b08d040_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x74b08d220_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%store/vec4 v0x74b08c640_0, 0, 22;
|
||||
%pushi/vec4 0, 0, 8;
|
||||
%store/vec4 v0x74b08d180_0, 0, 8;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%store/vec4 v0x74b08cdc0_0, 0, 16;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x74b08ce60_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 32;
|
||||
%store/vec4 v0x74b08c780_0, 0, 32;
|
||||
T_6.0 ; Top of for-loop
|
||||
%load/vec4 v0x74b08c780_0;
|
||||
%cmpi/s 1024, 0, 32;
|
||||
%jmp/0xz T_6.1, 5;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%ix/getv/s 4, v0x74b08c780_0;
|
||||
%store/vec4a v0x74b08cd20, 4, 0;
|
||||
T_6.2 ; for-loop step statement
|
||||
%load/vec4 v0x74b08c780_0;
|
||||
%addi 1, 0, 32;
|
||||
%store/vec4 v0x74b08c780_0, 0, 32;
|
||||
%jmp T_6.0;
|
||||
T_6.1 ; for-loop exit label
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%store/vec4 v0x74b08d0e0_0, 0, 1;
|
||||
%pushi/vec4 5, 0, 32;
|
||||
T_6.3 %dup/vec4;
|
||||
%cmpi/s 0, 0, 32;
|
||||
%jmp/1xz T_6.4, 5;
|
||||
%jmp/1 T_6.4, 4;
|
||||
%subi 1, 0, 32;
|
||||
%wait E_0x74ac1b040;
|
||||
%jmp T_6.3;
|
||||
T_6.4 ;
|
||||
%pop/vec4 1;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x74b08d0e0_0, 0, 1;
|
||||
%vpi_call/w 3 244 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 245 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 246 "$display", "INT8 MEMORY ACCESS TEST" {0 0 0};
|
||||
%vpi_call/w 3 247 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 248 "$display", "\000" {0 0 0};
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 18, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 1, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 52, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 2, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 86, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 3, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 120, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 18, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%pushi/vec4 1, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 52, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%pushi/vec4 2, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 86, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%pushi/vec4 3, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 120, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%ix/load 4, 0, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%cmpi/ne 13330, 0, 16;
|
||||
%jmp/0xz T_6.5, 6;
|
||||
%vpi_call/w 3 276 "$display", "PACKING ERROR word[0]=0x%04x expected=0x3412", &A<v0x74b08cd20, 0> {0 0 0};
|
||||
%vpi_call/w 3 281 "$fatal" {0 0 0};
|
||||
%jmp T_6.6;
|
||||
T_6.5 ;
|
||||
%vpi_call/w 3 285 "$display", "PACKING word[0] = 0x%04x PASS", &A<v0x74b08cd20, 0> {0 0 0};
|
||||
T_6.6 ;
|
||||
%ix/load 4, 1, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%cmpi/ne 30806, 0, 16;
|
||||
%jmp/0xz T_6.7, 6;
|
||||
%vpi_call/w 3 294 "$display", "PACKING ERROR word[1]=0x%04x expected=0x7856", &A<v0x74b08cd20, 1> {0 0 0};
|
||||
%vpi_call/w 3 299 "$fatal" {0 0 0};
|
||||
%jmp T_6.8;
|
||||
T_6.7 ;
|
||||
%vpi_call/w 3 303 "$display", "PACKING word[1] = 0x%04x PASS", &A<v0x74b08cd20, 1> {0 0 0};
|
||||
T_6.8 ;
|
||||
%pushi/vec4 16, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 52, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 17, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 18, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%ix/load 4, 8, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%cmpi/ne 4660, 0, 16;
|
||||
%jmp/0xz T_6.9, 6;
|
||||
%vpi_call/w 3 320 "$display", "INITIAL WORD ERROR = 0x%04x", &A<v0x74b08cd20, 8> {0 0 0};
|
||||
%vpi_call/w 3 325 "$fatal" {0 0 0};
|
||||
T_6.9 ;
|
||||
%pushi/vec4 16, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 170, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%ix/load 4, 8, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%cmpi/ne 4778, 0, 16;
|
||||
%jmp/0xz T_6.11, 6;
|
||||
%vpi_call/w 3 336 "$display", "LOW BYTE PRESERVE ERROR = 0x%04x expected=0x12AA", &A<v0x74b08cd20, 8> {0 0 0};
|
||||
%vpi_call/w 3 341 "$fatal" {0 0 0};
|
||||
%jmp T_6.12;
|
||||
T_6.11 ;
|
||||
%vpi_call/w 3 345 "$display", "LOW BYTE PRESERVE 0x1234 -> 0x12AA PASS" {0 0 0};
|
||||
T_6.12 ;
|
||||
%pushi/vec4 17, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 187, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%ix/load 4, 8, 0;
|
||||
%flag_set/imm 4, 0;
|
||||
%load/vec4a v0x74b08cd20, 4;
|
||||
%cmpi/ne 48042, 0, 16;
|
||||
%jmp/0xz T_6.13, 6;
|
||||
%vpi_call/w 3 358 "$display", "HIGH BYTE PRESERVE ERROR = 0x%04x expected=0xBBAA", &A<v0x74b08cd20, 8> {0 0 0};
|
||||
%vpi_call/w 3 363 "$fatal" {0 0 0};
|
||||
%jmp T_6.14;
|
||||
T_6.13 ;
|
||||
%vpi_call/w 3 367 "$display", "HIGH BYTE PRESERVE 0x12AA -> 0xBBAA PASS" {0 0 0};
|
||||
T_6.14 ;
|
||||
%pushi/vec4 32, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 255, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 33, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 128, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 34, 0, 22;
|
||||
%store/vec4 v0x74b08c500_0, 0, 22;
|
||||
%pushi/vec4 127, 0, 8;
|
||||
%store/vec4 v0x74b08c5a0_0, 0, 8;
|
||||
%fork TD_tb.write_byte, S_0x102cd1300;
|
||||
%join;
|
||||
%pushi/vec4 32, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 255, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%pushi/vec4 33, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 128, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%pushi/vec4 34, 0, 22;
|
||||
%store/vec4 v0x74b08c3c0_0, 0, 22;
|
||||
%pushi/vec4 127, 0, 8;
|
||||
%store/vec4 v0x74b08c460_0, 0, 8;
|
||||
%fork TD_tb.read_byte, S_0x102cd1180;
|
||||
%join;
|
||||
%vpi_call/w 3 389 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 390 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 391 "$display", "INT8 MEMORY ACCESS TEST PASSED" {0 0 0};
|
||||
%vpi_call/w 3 392 "$display", "BYTE ADDRESSING : PASS" {0 0 0};
|
||||
%vpi_call/w 3 393 "$display", "LOW BYTE : PASS" {0 0 0};
|
||||
%vpi_call/w 3 394 "$display", "HIGH BYTE : PASS" {0 0 0};
|
||||
%vpi_call/w 3 395 "$display", "INT8 PACKING : PASS" {0 0 0};
|
||||
%vpi_call/w 3 396 "$display", "BYTE PRESERVATION : PASS" {0 0 0};
|
||||
%vpi_call/w 3 397 "$display", "SIGNED INT8 : PASS" {0 0 0};
|
||||
%vpi_call/w 3 398 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 399 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 401 "$finish" {0 0 0};
|
||||
%end;
|
||||
.thread T_6;
|
||||
# The file index is used to find the file name in the following table.
|
||||
:file_names 5;
|
||||
"N/A";
|
||||
"<interactive>";
|
||||
"-";
|
||||
"sim/int8_memory_access_tb.v";
|
||||
"rtl/int8_memory_access.v";
|
||||
@@ -0,0 +1,405 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb;
|
||||
|
||||
localparam ADDR_WIDTH = 22;
|
||||
localparam CLK_PERIOD = 12.5;
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
// ============================================================
|
||||
// INT8 interface
|
||||
// ============================================================
|
||||
|
||||
reg req;
|
||||
reg wr;
|
||||
reg [ADDR_WIDTH-1:0] addr;
|
||||
reg signed [7:0] wdata;
|
||||
|
||||
wire signed [7:0] rdata;
|
||||
wire ready;
|
||||
|
||||
// ============================================================
|
||||
// Memory interface
|
||||
// ============================================================
|
||||
|
||||
wire mem_req;
|
||||
wire mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] mem_addr;
|
||||
wire [15:0] mem_wdata;
|
||||
wire mem_lb_n;
|
||||
wire mem_ub_n;
|
||||
|
||||
wire [15:0] mem_rdata;
|
||||
wire mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// DUT
|
||||
// ============================================================
|
||||
|
||||
int8_memory_access #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH)
|
||||
) dut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.req (req),
|
||||
.wr (wr),
|
||||
.addr (addr),
|
||||
.wdata (wdata),
|
||||
|
||||
.rdata (rdata),
|
||||
.ready (ready),
|
||||
|
||||
.mem_req (mem_req),
|
||||
.mem_wr (mem_wr),
|
||||
.mem_addr (mem_addr),
|
||||
.mem_wdata (mem_wdata),
|
||||
.mem_lb_n (mem_lb_n),
|
||||
.mem_ub_n (mem_ub_n),
|
||||
|
||||
.mem_rdata (mem_rdata),
|
||||
.mem_ready (mem_ready)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// Simple memory model
|
||||
// ============================================================
|
||||
|
||||
reg [15:0] memory [0:1023];
|
||||
|
||||
reg [15:0] model_rdata;
|
||||
reg model_ready;
|
||||
|
||||
integer i;
|
||||
|
||||
assign mem_rdata = model_rdata;
|
||||
assign mem_ready = model_ready;
|
||||
|
||||
// ============================================================
|
||||
// Clock
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
clk = 1'b0;
|
||||
|
||||
forever #(CLK_PERIOD / 2.0)
|
||||
clk = ~clk;
|
||||
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// VCD
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
$dumpfile("sim/int8_memory_access.vcd");
|
||||
$dumpvars(0, tb);
|
||||
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// Memory model
|
||||
// ============================================================
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
model_ready <= 1'b0;
|
||||
|
||||
if (mem_req) begin
|
||||
|
||||
if (mem_wr) begin
|
||||
|
||||
if (!mem_lb_n)
|
||||
memory[mem_addr][7:0] <= mem_wdata[7:0];
|
||||
|
||||
if (!mem_ub_n)
|
||||
memory[mem_addr][15:8] <= mem_wdata[15:8];
|
||||
|
||||
end else begin
|
||||
|
||||
model_rdata <= memory[mem_addr];
|
||||
|
||||
end
|
||||
|
||||
model_ready <= 1'b1;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// Write helper
|
||||
// ============================================================
|
||||
|
||||
task write_byte;
|
||||
|
||||
input [ADDR_WIDTH-1:0] byte_addr;
|
||||
input signed [7:0] data;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
addr <= byte_addr;
|
||||
wdata <= data;
|
||||
wr <= 1'b1;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
$display(
|
||||
"WRITE BYTE addr=0x%08x data=0x%02x PASS",
|
||||
byte_addr,
|
||||
data
|
||||
);
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Read helper
|
||||
// ============================================================
|
||||
|
||||
task read_byte;
|
||||
|
||||
input [ADDR_WIDTH-1:0] byte_addr;
|
||||
input signed [7:0] expected;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
addr <= byte_addr;
|
||||
wr <= 1'b0;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
if (rdata !== expected) begin
|
||||
|
||||
$display(
|
||||
"READ BYTE addr=0x%08x FAIL got=0x%02x expected=0x%02x",
|
||||
byte_addr,
|
||||
rdata,
|
||||
expected
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"READ BYTE addr=0x%08x data=0x%02x PASS",
|
||||
byte_addr,
|
||||
rdata
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Test
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
req = 1'b0;
|
||||
wr = 1'b0;
|
||||
addr = 0;
|
||||
wdata = 0;
|
||||
|
||||
model_rdata = 16'h0000;
|
||||
model_ready = 1'b0;
|
||||
|
||||
for (i = 0; i < 1024; i = i + 1)
|
||||
memory[i] = 16'h0000;
|
||||
|
||||
rst = 1'b1;
|
||||
|
||||
repeat (5)
|
||||
@(posedge clk);
|
||||
|
||||
rst = 1'b0;
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("INT8 MEMORY ACCESS TEST");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// Basic byte writes
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000000, 8'h12);
|
||||
write_byte(22'h000001, 8'h34);
|
||||
|
||||
write_byte(22'h000002, 8'h56);
|
||||
write_byte(22'h000003, 8'h78);
|
||||
|
||||
// ========================================================
|
||||
// Reads
|
||||
// ========================================================
|
||||
|
||||
read_byte(22'h000000, 8'h12);
|
||||
read_byte(22'h000001, 8'h34);
|
||||
|
||||
read_byte(22'h000002, 8'h56);
|
||||
read_byte(22'h000003, 8'h78);
|
||||
|
||||
// ========================================================
|
||||
// Verify physical packing
|
||||
// ========================================================
|
||||
|
||||
if (memory[0] !== 16'h3412) begin
|
||||
|
||||
$display(
|
||||
"PACKING ERROR word[0]=0x%04x expected=0x3412",
|
||||
memory[0]
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"PACKING word[0] = 0x%04x PASS",
|
||||
memory[0]
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
if (memory[1] !== 16'h7856) begin
|
||||
|
||||
$display(
|
||||
"PACKING ERROR word[1]=0x%04x expected=0x7856",
|
||||
memory[1]
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"PACKING word[1] = 0x%04x PASS",
|
||||
memory[1]
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
// ========================================================
|
||||
// Byte preservation test
|
||||
// ========================================================
|
||||
|
||||
// Start with 0x1234
|
||||
write_byte(22'h000010, 8'h34);
|
||||
write_byte(22'h000011, 8'h12);
|
||||
|
||||
if (memory[8] !== 16'h1234) begin
|
||||
|
||||
$display(
|
||||
"INITIAL WORD ERROR = 0x%04x",
|
||||
memory[8]
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end
|
||||
|
||||
// Change low byte only:
|
||||
// 0x1234 -> 0x12AA
|
||||
|
||||
write_byte(22'h000010, 8'hAA);
|
||||
|
||||
if (memory[8] !== 16'h12AA) begin
|
||||
|
||||
$display(
|
||||
"LOW BYTE PRESERVE ERROR = 0x%04x expected=0x12AA",
|
||||
memory[8]
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"LOW BYTE PRESERVE 0x1234 -> 0x12AA PASS"
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
// Change high byte only:
|
||||
// 0x12AA -> 0xBBAA
|
||||
|
||||
write_byte(22'h000011, 8'hBB);
|
||||
|
||||
if (memory[8] !== 16'hBBAA) begin
|
||||
|
||||
$display(
|
||||
"HIGH BYTE PRESERVE ERROR = 0x%04x expected=0xBBAA",
|
||||
memory[8]
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"HIGH BYTE PRESERVE 0x12AA -> 0xBBAA PASS"
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
// ========================================================
|
||||
// Signed INT8 values
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000020, -8'sd1);
|
||||
write_byte(22'h000021, -8'sd128);
|
||||
write_byte(22'h000022, 8'sd127);
|
||||
|
||||
read_byte(22'h000020, -8'sd1);
|
||||
read_byte(22'h000021, -8'sd128);
|
||||
read_byte(22'h000022, 8'sd127);
|
||||
|
||||
// ========================================================
|
||||
// Final result
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("INT8 MEMORY ACCESS TEST PASSED");
|
||||
$display("BYTE ADDRESSING : PASS");
|
||||
$display("LOW BYTE : PASS");
|
||||
$display("HIGH BYTE : PASS");
|
||||
$display("INT8 PACKING : PASS");
|
||||
$display("BYTE PRESERVATION : PASS");
|
||||
$display("SIGNED INT8 : PASS");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+22197
File diff suppressed because one or more lines are too long
@@ -0,0 +1,455 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb;
|
||||
|
||||
localparam ADDR_WIDTH = 22;
|
||||
localparam DATA_WIDTH = 16;
|
||||
localparam CLK_PERIOD = 12.5; // 80 MHz
|
||||
|
||||
// ============================================================
|
||||
// Clock / Reset
|
||||
// ============================================================
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
// ============================================================
|
||||
// INT8 interface
|
||||
// ============================================================
|
||||
|
||||
reg req;
|
||||
reg wr;
|
||||
reg [ADDR_WIDTH-1:0] addr;
|
||||
reg signed [7:0] wdata;
|
||||
|
||||
wire signed [7:0] rdata;
|
||||
wire ready;
|
||||
|
||||
// ============================================================
|
||||
// memory_interface
|
||||
// ============================================================
|
||||
|
||||
wire mem_req;
|
||||
wire mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] mem_addr;
|
||||
wire [DATA_WIDTH-1:0] mem_wdata;
|
||||
wire mem_lb_n;
|
||||
wire mem_ub_n;
|
||||
|
||||
wire [DATA_WIDTH-1:0] mem_rdata;
|
||||
wire mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// Memory interface -> PSRAM controller
|
||||
// ============================================================
|
||||
|
||||
wire psram_mem_req;
|
||||
wire psram_mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] psram_mem_addr;
|
||||
wire [DATA_WIDTH-1:0] psram_mem_wdata;
|
||||
wire psram_mem_lb_n;
|
||||
wire psram_mem_ub_n;
|
||||
|
||||
wire [DATA_WIDTH-1:0] psram_mem_rdata;
|
||||
wire psram_mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// PSRAM physical interface
|
||||
// ============================================================
|
||||
|
||||
wire [ADDR_WIDTH-1:0] psram_a;
|
||||
wire [DATA_WIDTH-1:0] psram_dq;
|
||||
|
||||
wire psram_ce_n;
|
||||
wire psram_oe_n;
|
||||
wire psram_we_n;
|
||||
wire psram_lb_n;
|
||||
wire psram_ub_n;
|
||||
wire psram_zz_n;
|
||||
|
||||
// ============================================================
|
||||
// INT8 MEMORY ACCESS
|
||||
// ============================================================
|
||||
|
||||
int8_memory_access #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH)
|
||||
) int8_access (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.req (req),
|
||||
.wr (wr),
|
||||
.addr (addr),
|
||||
.wdata (wdata),
|
||||
|
||||
.rdata (rdata),
|
||||
.ready (ready),
|
||||
|
||||
.mem_req (mem_req),
|
||||
.mem_wr (mem_wr),
|
||||
.mem_addr (mem_addr),
|
||||
.mem_wdata (mem_wdata),
|
||||
.mem_lb_n (mem_lb_n),
|
||||
.mem_ub_n (mem_ub_n),
|
||||
|
||||
.mem_rdata (mem_rdata),
|
||||
.mem_ready (mem_ready)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// MEMORY INTERFACE
|
||||
// ============================================================
|
||||
|
||||
memory_interface #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH)
|
||||
) memory_if (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.req (mem_req),
|
||||
.wr (mem_wr),
|
||||
.addr (mem_addr),
|
||||
.wdata (mem_wdata),
|
||||
.lb_n (mem_lb_n),
|
||||
.ub_n (mem_ub_n),
|
||||
|
||||
.rdata (mem_rdata),
|
||||
.ready (mem_ready),
|
||||
|
||||
.mem_req (psram_mem_req),
|
||||
.mem_wr (psram_mem_wr),
|
||||
.mem_addr (psram_mem_addr),
|
||||
.mem_wdata (psram_mem_wdata),
|
||||
.mem_lb_n (psram_mem_lb_n),
|
||||
.mem_ub_n (psram_mem_ub_n),
|
||||
|
||||
.mem_rdata (psram_mem_rdata),
|
||||
.mem_ready (psram_mem_ready)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PSRAM CONTROLLER
|
||||
// ============================================================
|
||||
|
||||
psram_controller #(
|
||||
.ADDR_WIDTH (ADDR_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.CLK_FREQ_MHZ (80)
|
||||
) psram_ctrl (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.mem_req (psram_mem_req),
|
||||
.mem_wr (psram_mem_wr),
|
||||
.mem_addr (psram_mem_addr),
|
||||
.mem_wdata (psram_mem_wdata),
|
||||
.mem_lb_n (psram_mem_lb_n),
|
||||
.mem_ub_n (psram_mem_ub_n),
|
||||
|
||||
.mem_rdata (psram_mem_rdata),
|
||||
.mem_ready (psram_mem_ready),
|
||||
|
||||
.psram_a (psram_a),
|
||||
.psram_dq (psram_dq),
|
||||
|
||||
.psram_ce_n(psram_ce_n),
|
||||
.psram_oe_n(psram_oe_n),
|
||||
.psram_we_n(psram_we_n),
|
||||
.psram_lb_n(psram_lb_n),
|
||||
.psram_ub_n(psram_ub_n),
|
||||
.psram_zz_n(psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PSRAM MODEL
|
||||
// ============================================================
|
||||
|
||||
psram_model #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.DEPTH(16384)
|
||||
) psram (
|
||||
.clk (clk),
|
||||
.a (psram_a),
|
||||
.dq (psram_dq),
|
||||
.ce_n (psram_ce_n),
|
||||
.oe_n (psram_oe_n),
|
||||
.we_n (psram_we_n),
|
||||
.lb_n (psram_lb_n),
|
||||
.ub_n (psram_ub_n),
|
||||
.zz_n (psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// Clock
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
clk = 1'b0;
|
||||
|
||||
forever #(CLK_PERIOD / 2.0)
|
||||
clk = ~clk;
|
||||
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// VCD
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
$dumpfile("sim/int8_psram_integration.vcd");
|
||||
$dumpvars(0, tb);
|
||||
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// Write INT8
|
||||
// ============================================================
|
||||
|
||||
task write_byte;
|
||||
|
||||
input [ADDR_WIDTH-1:0] byte_addr;
|
||||
input signed [7:0] data;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
addr <= byte_addr;
|
||||
wdata <= data;
|
||||
wr <= 1'b1;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
$display(
|
||||
"WRITE BYTE addr=0x%08x data=0x%02x PASS",
|
||||
byte_addr,
|
||||
data
|
||||
);
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Read INT8
|
||||
// ============================================================
|
||||
|
||||
task read_byte;
|
||||
|
||||
input [ADDR_WIDTH-1:0] byte_addr;
|
||||
input signed [7:0] expected;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
addr <= byte_addr;
|
||||
wr <= 1'b0;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
if (rdata !== expected) begin
|
||||
|
||||
$display(
|
||||
"READ BYTE addr=0x%08x FAIL got=0x%02x expected=0x%02x",
|
||||
byte_addr,
|
||||
rdata,
|
||||
expected
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"READ BYTE addr=0x%08x data=0x%02x PASS",
|
||||
byte_addr,
|
||||
rdata
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Test
|
||||
// ============================================================
|
||||
|
||||
integer i;
|
||||
integer test_addr;
|
||||
reg signed [7:0] test_data;
|
||||
|
||||
initial begin
|
||||
|
||||
req = 1'b0;
|
||||
wr = 1'b0;
|
||||
addr = 0;
|
||||
wdata = 0;
|
||||
|
||||
rst = 1'b1;
|
||||
|
||||
repeat (5)
|
||||
@(posedge clk);
|
||||
|
||||
rst = 1'b0;
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("INT8 + PSRAM FULL INTEGRATION TEST");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Wait for PSRAM initialization
|
||||
// --------------------------------------------------------
|
||||
|
||||
wait (psram_ctrl.state == psram_ctrl.STATE_IDLE);
|
||||
|
||||
$display("PSRAM initialization complete");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// BASIC INT8 PACKING
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000000, 8'h12);
|
||||
write_byte(22'h000001, 8'h34);
|
||||
|
||||
write_byte(22'h000002, 8'h56);
|
||||
write_byte(22'h000003, 8'h78);
|
||||
|
||||
read_byte(22'h000000, 8'h12);
|
||||
read_byte(22'h000001, 8'h34);
|
||||
read_byte(22'h000002, 8'h56);
|
||||
read_byte(22'h000003, 8'h78);
|
||||
|
||||
// ========================================================
|
||||
// BYTE PRESERVATION
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000010, 8'h34);
|
||||
write_byte(22'h000011, 8'h12);
|
||||
|
||||
write_byte(22'h000010, 8'hAA);
|
||||
|
||||
read_byte(22'h000010, 8'hAA);
|
||||
read_byte(22'h000011, 8'h12);
|
||||
|
||||
write_byte(22'h000011, 8'hBB);
|
||||
|
||||
read_byte(22'h000010, 8'hAA);
|
||||
read_byte(22'h000011, 8'hBB);
|
||||
|
||||
// ========================================================
|
||||
// SIGNED INT8
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000020, -8'sd1);
|
||||
write_byte(22'h000021, -8'sd128);
|
||||
write_byte(22'h000022, 8'sd127);
|
||||
|
||||
read_byte(22'h000020, -8'sd1);
|
||||
read_byte(22'h000021, -8'sd128);
|
||||
read_byte(22'h000022, 8'sd127);
|
||||
|
||||
// ========================================================
|
||||
// SPARSE ADDRESSES
|
||||
// ========================================================
|
||||
|
||||
write_byte(22'h000100, 8'h11);
|
||||
write_byte(22'h000101, 8'h22);
|
||||
|
||||
write_byte(22'h001000, 8'h33);
|
||||
write_byte(22'h001001, 8'h44);
|
||||
|
||||
write_byte(22'h003FFE, 8'h55);
|
||||
write_byte(22'h003FFF, 8'h66);
|
||||
|
||||
read_byte(22'h000100, 8'h11);
|
||||
read_byte(22'h000101, 8'h22);
|
||||
|
||||
read_byte(22'h001000, 8'h33);
|
||||
read_byte(22'h001001, 8'h44);
|
||||
|
||||
read_byte(22'h003FFE, 8'h55);
|
||||
read_byte(22'h003FFF, 8'h66);
|
||||
|
||||
// ========================================================
|
||||
// STRESS TEST
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("INT8 PSRAM STRESS TEST");
|
||||
$display("2048 WRITE + READ BYTE TRANSACTIONS");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
for (i = 0; i < 2048; i = i + 1) begin
|
||||
|
||||
test_addr =
|
||||
((i * 7919) ^ (i << 5)) & 16'h7FFF;
|
||||
|
||||
test_data =
|
||||
((i * 1237) ^ 8'hA5);
|
||||
|
||||
write_byte(
|
||||
test_addr,
|
||||
test_data
|
||||
);
|
||||
|
||||
read_byte(
|
||||
test_addr,
|
||||
test_data
|
||||
);
|
||||
|
||||
if ((i % 128) == 0)
|
||||
$display(
|
||||
"STRESS %0d / 2048 PASS",
|
||||
i
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
// ========================================================
|
||||
// Final result
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("INT8 + PSRAM INTEGRATION TEST PASSED");
|
||||
$display("BYTE ADDRESSING : PASS");
|
||||
$display("LB# / UB# : PASS");
|
||||
$display("INT8 PACKING : PASS");
|
||||
$display("BYTE PRESERVATION : PASS");
|
||||
$display("SIGNED INT8 : PASS");
|
||||
$display("SPARSE ADDRESSES : PASS");
|
||||
$display("2048 STRESS : PASS");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+504
@@ -0,0 +1,504 @@
|
||||
#! /opt/homebrew/Cellar/icarus-verilog/13.0/bin/vvp
|
||||
:ivl_version "13.0 (stable)" "(v13_0)";
|
||||
:ivl_delay_selection "TYPICAL";
|
||||
:vpi_time_precision - 12;
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/system.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_sys.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/vhdl_textio.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2005_math.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/va_math.vpi";
|
||||
:vpi_module "/opt/homebrew/Cellar/icarus-verilog/13.0/lib/ivl/v2009.vpi";
|
||||
S_0x1008dc9a0 .scope package, "$unit" "$unit" 2 1;
|
||||
.timescale 0 0;
|
||||
S_0x1008dbb60 .scope module, "memory_interface_tb" "memory_interface_tb" 3 3;
|
||||
.timescale -9 -12;
|
||||
P_0x1008dbce0 .param/l "ADDR_WIDTH" 0 3 5, +C4<00000000000000000000000000010110>;
|
||||
P_0x1008dbd20 .param/l "DATA_WIDTH" 0 3 6, +C4<00000000000000000000000000010000>;
|
||||
v0x83f094e60_0 .var "addr", 21 0;
|
||||
v0x83f094f00_0 .var "clk", 0 0;
|
||||
v0x83f094fa0_0 .net "mem_addr", 21 0, v0x1008cea80_0; 1 drivers
|
||||
v0x83f095040_0 .net "mem_rdata", 15 0, v0x83f094780_0; 1 drivers
|
||||
v0x83f0950e0_0 .net "mem_ready", 0 0, v0x83f094820_0; 1 drivers
|
||||
v0x83f095180_0 .net "mem_req", 0 0, v0x1008d8580_0; 1 drivers
|
||||
v0x83f095220_0 .net "mem_wdata", 15 0, v0x1008d8620_0; 1 drivers
|
||||
v0x83f0952c0_0 .net "mem_wr", 0 0, v0x1008d86c0_0; 1 drivers
|
||||
v0x83f095360_0 .net "rdata", 15 0, v0x1008d8760_0; 1 drivers
|
||||
v0x83f095400_0 .net "ready", 0 0, v0x1008d8800_0; 1 drivers
|
||||
v0x83f0954a0_0 .var "req", 0 0;
|
||||
v0x83f095540_0 .var "rst", 0 0;
|
||||
v0x83f0955e0_0 .var "wdata", 15 0;
|
||||
v0x83f095680_0 .var "wr", 0 0;
|
||||
S_0x1008d97e0 .scope module, "dut" "memory_interface" 3 46, 4 1 0, S_0x1008dbb60;
|
||||
.timescale -9 -12;
|
||||
.port_info 0 /INPUT 1 "clk";
|
||||
.port_info 1 /INPUT 1 "rst";
|
||||
.port_info 2 /INPUT 1 "req";
|
||||
.port_info 3 /INPUT 1 "wr";
|
||||
.port_info 4 /INPUT 22 "addr";
|
||||
.port_info 5 /INPUT 16 "wdata";
|
||||
.port_info 6 /OUTPUT 16 "rdata";
|
||||
.port_info 7 /OUTPUT 1 "ready";
|
||||
.port_info 8 /OUTPUT 1 "mem_req";
|
||||
.port_info 9 /OUTPUT 1 "mem_wr";
|
||||
.port_info 10 /OUTPUT 22 "mem_addr";
|
||||
.port_info 11 /OUTPUT 16 "mem_wdata";
|
||||
.port_info 12 /INPUT 16 "mem_rdata";
|
||||
.port_info 13 /INPUT 1 "mem_ready";
|
||||
P_0x1008dcb20 .param/l "ADDR_WIDTH" 0 4 2, +C4<00000000000000000000000000010110>;
|
||||
P_0x1008dcb60 .param/l "DATA_WIDTH" 0 4 3, +C4<00000000000000000000000000010000>;
|
||||
P_0x1008dcba0 .param/l "STATE_IDLE" 1 4 27, C4<00>;
|
||||
P_0x1008dcbe0 .param/l "STATE_WAIT" 1 4 28, C4<01>;
|
||||
v0x1008ce940_0 .net "addr", 21 0, v0x83f094e60_0; 1 drivers
|
||||
v0x1008ce9e0_0 .net "clk", 0 0, v0x83f094f00_0; 1 drivers
|
||||
v0x1008cea80_0 .var "mem_addr", 21 0;
|
||||
v0x1008ceb20_0 .net "mem_rdata", 15 0, v0x83f094780_0; alias, 1 drivers
|
||||
v0x1008cebc0_0 .net "mem_ready", 0 0, v0x83f094820_0; alias, 1 drivers
|
||||
v0x1008d8580_0 .var "mem_req", 0 0;
|
||||
v0x1008d8620_0 .var "mem_wdata", 15 0;
|
||||
v0x1008d86c0_0 .var "mem_wr", 0 0;
|
||||
v0x1008d8760_0 .var "rdata", 15 0;
|
||||
v0x1008d8800_0 .var "ready", 0 0;
|
||||
v0x1008de100_0 .net "req", 0 0, v0x83f0954a0_0; 1 drivers
|
||||
v0x1008de1a0_0 .net "rst", 0 0, v0x83f095540_0; 1 drivers
|
||||
v0x83f094000_0 .var "state", 1 0;
|
||||
v0x83f0940a0_0 .net "wdata", 15 0, v0x83f0955e0_0; 1 drivers
|
||||
v0x83f094140_0 .net "wr", 0 0, v0x83f095680_0; 1 drivers
|
||||
E_0x83ec14080 .event posedge, v0x1008ce9e0_0;
|
||||
S_0x1008de240 .scope module, "memory" "memory_model" 3 76, 5 1 0, S_0x1008dbb60;
|
||||
.timescale -9 -12;
|
||||
.port_info 0 /INPUT 1 "clk";
|
||||
.port_info 1 /INPUT 1 "rst";
|
||||
.port_info 2 /INPUT 1 "req";
|
||||
.port_info 3 /INPUT 1 "wr";
|
||||
.port_info 4 /INPUT 22 "addr";
|
||||
.port_info 5 /INPUT 16 "wdata";
|
||||
.port_info 6 /OUTPUT 16 "rdata";
|
||||
.port_info 7 /OUTPUT 1 "ready";
|
||||
P_0x1008de3c0 .param/l "ADDR_WIDTH" 0 5 2, +C4<00000000000000000000000000010110>;
|
||||
P_0x1008de400 .param/l "DATA_WIDTH" 0 5 3, +C4<00000000000000000000000000010000>;
|
||||
P_0x1008de440 .param/l "DEPTH" 0 5 4, +C4<00000000000000000001000000000000>;
|
||||
P_0x1008de480 .param/l "READ_LATENCY" 0 5 5, +C4<00000000000000000000000000000010>;
|
||||
v0x83f0941e0_0 .net "addr", 21 0, v0x1008cea80_0; alias, 1 drivers
|
||||
v0x83f094280_0 .var "busy", 0 0;
|
||||
v0x83f094320_0 .net "clk", 0 0, v0x83f094f00_0; alias, 1 drivers
|
||||
v0x83f0943c0_0 .var/i "delay_count", 31 0;
|
||||
v0x83f094460_0 .var/i "i", 31 0;
|
||||
v0x83f094500 .array "mem", 4095 0, 15 0;
|
||||
v0x83f0945a0_0 .var "pending_addr", 21 0;
|
||||
v0x83f094640_0 .var "pending_wdata", 15 0;
|
||||
v0x83f0946e0_0 .var "pending_wr", 0 0;
|
||||
v0x83f094780_0 .var "rdata", 15 0;
|
||||
v0x83f094820_0 .var "ready", 0 0;
|
||||
v0x83f0948c0_0 .net "req", 0 0, v0x1008d8580_0; alias, 1 drivers
|
||||
v0x83f094960_0 .net "rst", 0 0, v0x83f095540_0; alias, 1 drivers
|
||||
v0x83f094a00_0 .net "wdata", 15 0, v0x1008d8620_0; alias, 1 drivers
|
||||
v0x83f094aa0_0 .net "wr", 0 0, v0x1008d86c0_0; alias, 1 drivers
|
||||
S_0x1008ded00 .scope task, "read_mem" "read_mem" 3 120, 3 120 0, S_0x1008dbb60;
|
||||
.timescale -9 -12;
|
||||
v0x83f094b40_0 .var "address", 21 0;
|
||||
v0x83f094be0_0 .var "expected", 15 0;
|
||||
v0x83f094c80_0 .var "received", 15 0;
|
||||
E_0x83ec17000 .event anyedge, v0x1008d8800_0;
|
||||
TD_memory_interface_tb.read_mem ;
|
||||
%wait E_0x83ec14080;
|
||||
%load/vec4 v0x83f094b40_0;
|
||||
%assign/vec4 v0x83f094e60_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f095680_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x83f0954a0_0, 0;
|
||||
%wait E_0x83ec14080;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f0954a0_0, 0;
|
||||
T_0.0 ;
|
||||
%load/vec4 v0x83f095400_0;
|
||||
%cmpi/ne 1, 0, 1;
|
||||
%jmp/0xz T_0.1, 6;
|
||||
%wait E_0x83ec17000;
|
||||
%jmp T_0.0;
|
||||
T_0.1 ;
|
||||
%load/vec4 v0x83f095360_0;
|
||||
%store/vec4 v0x83f094c80_0, 0, 16;
|
||||
%wait E_0x83ec14080;
|
||||
%load/vec4 v0x83f094c80_0;
|
||||
%load/vec4 v0x83f094be0_0;
|
||||
%cmp/e;
|
||||
%jmp/0xz T_0.2, 6;
|
||||
%vpi_call/w 3 144 "$display", "READ addr=0x%08h data=0x%04h PASS", v0x83f094b40_0, v0x83f094c80_0 {0 0 0};
|
||||
%jmp T_0.3;
|
||||
T_0.2 ;
|
||||
%vpi_call/w 3 150 "$display", "READ addr=0x%08h got=0x%04h expected=0x%04h FAIL", v0x83f094b40_0, v0x83f094c80_0, v0x83f094be0_0 {0 0 0};
|
||||
%vpi_call/w 3 157 "$fatal" {0 0 0};
|
||||
T_0.3 ;
|
||||
%end;
|
||||
S_0x1008dee80 .scope task, "write_mem" "write_mem" 3 93, 3 93 0, S_0x1008dbb60;
|
||||
.timescale -9 -12;
|
||||
v0x83f094d20_0 .var "address", 21 0;
|
||||
v0x83f094dc0_0 .var "data", 15 0;
|
||||
TD_memory_interface_tb.write_mem ;
|
||||
%wait E_0x83ec14080;
|
||||
%load/vec4 v0x83f094d20_0;
|
||||
%assign/vec4 v0x83f094e60_0, 0;
|
||||
%load/vec4 v0x83f094dc0_0;
|
||||
%assign/vec4 v0x83f0955e0_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x83f095680_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x83f0954a0_0, 0;
|
||||
%wait E_0x83ec14080;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f0954a0_0, 0;
|
||||
T_1.4 ;
|
||||
%load/vec4 v0x83f095400_0;
|
||||
%cmpi/ne 1, 0, 1;
|
||||
%jmp/0xz T_1.5, 6;
|
||||
%wait E_0x83ec17000;
|
||||
%jmp T_1.4;
|
||||
T_1.5 ;
|
||||
%wait E_0x83ec14080;
|
||||
%vpi_call/w 3 112 "$display", "WRITE addr=0x%08h data=0x%04h PASS", v0x83f094d20_0, v0x83f094dc0_0 {0 0 0};
|
||||
%end;
|
||||
.scope S_0x1008d97e0;
|
||||
T_2 ;
|
||||
%wait E_0x83ec14080;
|
||||
%load/vec4 v0x1008de1a0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.0, 8;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x83f094000_0, 0;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x1008d8760_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x1008d8800_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x1008d8580_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x1008d86c0_0, 0;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%assign/vec4 v0x1008cea80_0, 0;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x1008d8620_0, 0;
|
||||
%jmp T_2.1;
|
||||
T_2.0 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x1008d8800_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x1008d8580_0, 0;
|
||||
%load/vec4 v0x83f094000_0;
|
||||
%dup/vec4;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%cmp/u;
|
||||
%jmp/1 T_2.2, 6;
|
||||
%dup/vec4;
|
||||
%pushi/vec4 1, 0, 2;
|
||||
%cmp/u;
|
||||
%jmp/1 T_2.3, 6;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x83f094000_0, 0;
|
||||
%jmp T_2.5;
|
||||
T_2.2 ;
|
||||
%load/vec4 v0x1008de100_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.6, 8;
|
||||
%load/vec4 v0x83f094140_0;
|
||||
%assign/vec4 v0x1008d86c0_0, 0;
|
||||
%load/vec4 v0x1008ce940_0;
|
||||
%assign/vec4 v0x1008cea80_0, 0;
|
||||
%load/vec4 v0x83f0940a0_0;
|
||||
%assign/vec4 v0x1008d8620_0, 0;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x1008d8580_0, 0;
|
||||
%pushi/vec4 1, 0, 2;
|
||||
%assign/vec4 v0x83f094000_0, 0;
|
||||
T_2.6 ;
|
||||
%jmp T_2.5;
|
||||
T_2.3 ;
|
||||
%load/vec4 v0x1008cebc0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.8, 8;
|
||||
%load/vec4 v0x1008d86c0_0;
|
||||
%nor/r;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_2.10, 8;
|
||||
%load/vec4 v0x1008ceb20_0;
|
||||
%assign/vec4 v0x1008d8760_0, 0;
|
||||
T_2.10 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x1008d8800_0, 0;
|
||||
%pushi/vec4 0, 0, 2;
|
||||
%assign/vec4 v0x83f094000_0, 0;
|
||||
T_2.8 ;
|
||||
%jmp T_2.5;
|
||||
T_2.5 ;
|
||||
%pop/vec4 1;
|
||||
T_2.1 ;
|
||||
%jmp T_2;
|
||||
.thread T_2;
|
||||
.scope S_0x1008de240;
|
||||
T_3 ;
|
||||
%wait E_0x83ec14080;
|
||||
%load/vec4 v0x83f094960_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_3.0, 8;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x83f094780_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f094820_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f094280_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f0946e0_0, 0;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%assign/vec4 v0x83f0945a0_0, 0;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x83f094640_0, 0;
|
||||
%pushi/vec4 0, 0, 32;
|
||||
%assign/vec4 v0x83f0943c0_0, 0;
|
||||
%pushi/vec4 0, 0, 32;
|
||||
%store/vec4 v0x83f094460_0, 0, 32;
|
||||
T_3.2 ; Top of for-loop
|
||||
%load/vec4 v0x83f094460_0;
|
||||
%cmpi/s 4096, 0, 32;
|
||||
%jmp/0xz T_3.3, 5;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%ix/getv/s 3, v0x83f094460_0;
|
||||
%ix/load 4, 0, 0; Constant delay
|
||||
%assign/vec4/a/d v0x83f094500, 0, 4;
|
||||
T_3.4 ; for-loop step statement
|
||||
%load/vec4 v0x83f094460_0;
|
||||
%addi 1, 0, 32;
|
||||
%store/vec4 v0x83f094460_0, 0, 32;
|
||||
%jmp T_3.2;
|
||||
T_3.3 ; for-loop exit label
|
||||
%jmp T_3.1;
|
||||
T_3.0 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f094820_0, 0;
|
||||
%load/vec4 v0x83f094280_0;
|
||||
%nor/r;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_3.5, 8;
|
||||
%load/vec4 v0x83f0948c0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_3.7, 8;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x83f094280_0, 0;
|
||||
%load/vec4 v0x83f094aa0_0;
|
||||
%assign/vec4 v0x83f0946e0_0, 0;
|
||||
%load/vec4 v0x83f0941e0_0;
|
||||
%assign/vec4 v0x83f0945a0_0, 0;
|
||||
%load/vec4 v0x83f094a00_0;
|
||||
%assign/vec4 v0x83f094640_0, 0;
|
||||
%pushi/vec4 2, 0, 32;
|
||||
%assign/vec4 v0x83f0943c0_0, 0;
|
||||
T_3.7 ;
|
||||
%jmp T_3.6;
|
||||
T_3.5 ;
|
||||
%load/vec4 v0x83f0943c0_0;
|
||||
%cmpi/s 0, 0, 32;
|
||||
%flag_or 5, 4; GT is !LE
|
||||
%flag_inv 5;
|
||||
%jmp/0xz T_3.9, 5;
|
||||
%load/vec4 v0x83f0943c0_0;
|
||||
%subi 1, 0, 32;
|
||||
%assign/vec4 v0x83f0943c0_0, 0;
|
||||
%jmp T_3.10;
|
||||
T_3.9 ;
|
||||
%load/vec4 v0x83f0946e0_0;
|
||||
%flag_set/vec4 8;
|
||||
%jmp/0xz T_3.11, 8;
|
||||
%load/vec4 v0x83f0945a0_0;
|
||||
%pad/u 32;
|
||||
%cmpi/u 4096, 0, 32;
|
||||
%jmp/0xz T_3.13, 5;
|
||||
%load/vec4 v0x83f094640_0;
|
||||
%ix/getv 3, v0x83f0945a0_0;
|
||||
%ix/load 4, 0, 0; Constant delay
|
||||
%assign/vec4/a/d v0x83f094500, 0, 4;
|
||||
T_3.13 ;
|
||||
%jmp T_3.12;
|
||||
T_3.11 ;
|
||||
%load/vec4 v0x83f0945a0_0;
|
||||
%pad/u 32;
|
||||
%cmpi/u 4096, 0, 32;
|
||||
%jmp/0xz T_3.15, 5;
|
||||
%ix/getv 4, v0x83f0945a0_0;
|
||||
%load/vec4a v0x83f094500, 4;
|
||||
%assign/vec4 v0x83f094780_0, 0;
|
||||
%jmp T_3.16;
|
||||
T_3.15 ;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%assign/vec4 v0x83f094780_0, 0;
|
||||
T_3.16 ;
|
||||
T_3.12 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%assign/vec4 v0x83f094820_0, 0;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%assign/vec4 v0x83f094280_0, 0;
|
||||
T_3.10 ;
|
||||
T_3.6 ;
|
||||
T_3.1 ;
|
||||
%jmp T_3;
|
||||
.thread T_3;
|
||||
.scope S_0x1008dbb60;
|
||||
T_4 ;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x83f094f00_0, 0, 1;
|
||||
T_4.0 ;
|
||||
%delay 5000, 0;
|
||||
%load/vec4 v0x83f094f00_0;
|
||||
%inv;
|
||||
%store/vec4 v0x83f094f00_0, 0, 1;
|
||||
%jmp T_4.0;
|
||||
T_4.1 ;
|
||||
%end;
|
||||
.thread T_4;
|
||||
.scope S_0x1008dbb60;
|
||||
T_5 ;
|
||||
%pushi/vec4 1, 0, 1;
|
||||
%store/vec4 v0x83f095540_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x83f0954a0_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x83f095680_0, 0, 1;
|
||||
%pushi/vec4 0, 0, 22;
|
||||
%store/vec4 v0x83f094e60_0, 0, 22;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%store/vec4 v0x83f0955e0_0, 0, 16;
|
||||
%pushi/vec4 3, 0, 32;
|
||||
T_5.0 %dup/vec4;
|
||||
%cmpi/s 0, 0, 32;
|
||||
%jmp/1xz T_5.1, 5;
|
||||
%jmp/1 T_5.1, 4;
|
||||
%subi 1, 0, 32;
|
||||
%wait E_0x83ec14080;
|
||||
%jmp T_5.0;
|
||||
T_5.1 ;
|
||||
%pop/vec4 1;
|
||||
%pushi/vec4 0, 0, 1;
|
||||
%store/vec4 v0x83f095540_0, 0, 1;
|
||||
%vpi_call/w 3 182 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 183 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 184 "$display", "MEMORY INTERFACE V1 TEST" {0 0 0};
|
||||
%vpi_call/w 3 185 "$display", "ADDR_WIDTH = %0d", P_0x1008dbce0 {0 0 0};
|
||||
%vpi_call/w 3 186 "$display", "DATA_WIDTH = %0d", P_0x1008dbd20 {0 0 0};
|
||||
%vpi_call/w 3 187 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 188 "$display", "\000" {0 0 0};
|
||||
%pushi/vec4 1, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 4660, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 1, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 4660, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 16, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 43981, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 16, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 43981, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 256, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 21930, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 256, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 21930, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 512, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 1, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 513, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 2, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 514, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 3, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 512, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 1, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 513, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 2, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 514, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 3, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 768, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 768, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 0, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%pushi/vec4 769, 0, 22;
|
||||
%store/vec4 v0x83f094d20_0, 0, 22;
|
||||
%pushi/vec4 65535, 0, 16;
|
||||
%store/vec4 v0x83f094dc0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.write_mem, S_0x1008dee80;
|
||||
%join;
|
||||
%pushi/vec4 769, 0, 22;
|
||||
%store/vec4 v0x83f094b40_0, 0, 22;
|
||||
%pushi/vec4 65535, 0, 16;
|
||||
%store/vec4 v0x83f094be0_0, 0, 16;
|
||||
%fork TD_memory_interface_tb.read_mem, S_0x1008ded00;
|
||||
%join;
|
||||
%vpi_call/w 3 301 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 302 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 303 "$display", "MEMORY INTERFACE V1 TEST PASSED" {0 0 0};
|
||||
%vpi_call/w 3 304 "$display", "========================================" {0 0 0};
|
||||
%vpi_call/w 3 305 "$display", "\000" {0 0 0};
|
||||
%vpi_call/w 3 307 "$finish" {0 0 0};
|
||||
%end;
|
||||
.thread T_5;
|
||||
.scope S_0x1008dbb60;
|
||||
T_6 ;
|
||||
%vpi_call/w 3 315 "$dumpfile", "sim/memory_interface.vcd" {0 0 0};
|
||||
%vpi_call/w 3 316 "$dumpvars", 32'sb00000000000000000000000000000000, S_0x1008dbb60 {0 0 0};
|
||||
%end;
|
||||
.thread T_6;
|
||||
# The file index is used to find the file name in the following table.
|
||||
:file_names 6;
|
||||
"N/A";
|
||||
"<interactive>";
|
||||
"-";
|
||||
"sim/memory_interface_tb.v";
|
||||
"rtl/memory_interface.v";
|
||||
"rtl/memory_model.v";
|
||||
@@ -0,0 +1,319 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module memory_interface_tb;
|
||||
|
||||
parameter ADDR_WIDTH = 22;
|
||||
parameter DATA_WIDTH = 16;
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
// Host side
|
||||
reg req;
|
||||
reg wr;
|
||||
reg [ADDR_WIDTH-1:0] addr;
|
||||
reg [DATA_WIDTH-1:0] wdata;
|
||||
|
||||
wire [DATA_WIDTH-1:0] rdata;
|
||||
wire ready;
|
||||
|
||||
// Memory side
|
||||
wire mem_req;
|
||||
wire mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] mem_addr;
|
||||
wire [DATA_WIDTH-1:0] mem_wdata;
|
||||
|
||||
wire [DATA_WIDTH-1:0] mem_rdata;
|
||||
wire mem_ready;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Clock
|
||||
// ------------------------------------------------------------
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// DUT: Memory Interface
|
||||
// ------------------------------------------------------------
|
||||
|
||||
memory_interface #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH)
|
||||
) dut (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(req),
|
||||
.wr(wr),
|
||||
.addr(addr),
|
||||
.wdata(wdata),
|
||||
|
||||
.rdata(rdata),
|
||||
.ready(ready),
|
||||
|
||||
.mem_req(mem_req),
|
||||
.mem_wr(mem_wr),
|
||||
.mem_addr(mem_addr),
|
||||
.mem_wdata(mem_wdata),
|
||||
|
||||
.mem_rdata(mem_rdata),
|
||||
.mem_ready(mem_ready)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Memory model
|
||||
// ------------------------------------------------------------
|
||||
|
||||
memory_model #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.DEPTH(4096),
|
||||
.READ_LATENCY(2)
|
||||
) memory (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(mem_req),
|
||||
.wr(mem_wr),
|
||||
.addr(mem_addr),
|
||||
.wdata(mem_wdata),
|
||||
|
||||
.rdata(mem_rdata),
|
||||
.ready(mem_ready)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Test utilities
|
||||
// ------------------------------------------------------------
|
||||
|
||||
task write_mem;
|
||||
input [ADDR_WIDTH-1:0] address;
|
||||
input [DATA_WIDTH-1:0] data;
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
addr <= address;
|
||||
wdata <= data;
|
||||
wr <= 1'b1;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
$display(
|
||||
"WRITE addr=0x%08h data=0x%04h PASS",
|
||||
address,
|
||||
data
|
||||
);
|
||||
end
|
||||
endtask
|
||||
|
||||
task read_mem;
|
||||
input [ADDR_WIDTH-1:0] address;
|
||||
input [DATA_WIDTH-1:0] expected;
|
||||
|
||||
reg [DATA_WIDTH-1:0] received;
|
||||
|
||||
begin
|
||||
@(posedge clk);
|
||||
|
||||
addr <= address;
|
||||
wr <= 1'b0;
|
||||
req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
req <= 1'b0;
|
||||
|
||||
wait (ready);
|
||||
|
||||
received = rdata;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
if (received === expected) begin
|
||||
$display(
|
||||
"READ addr=0x%08h data=0x%04h PASS",
|
||||
address,
|
||||
received
|
||||
);
|
||||
end else begin
|
||||
$display(
|
||||
"READ addr=0x%08h got=0x%04h expected=0x%04h FAIL",
|
||||
address,
|
||||
received,
|
||||
expected
|
||||
);
|
||||
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Test sequence
|
||||
// ------------------------------------------------------------
|
||||
|
||||
initial begin
|
||||
|
||||
// Defaults
|
||||
rst = 1'b1;
|
||||
|
||||
req = 1'b0;
|
||||
wr = 1'b0;
|
||||
addr = {ADDR_WIDTH{1'b0}};
|
||||
wdata = {DATA_WIDTH{1'b0}};
|
||||
|
||||
// Reset
|
||||
repeat (3)
|
||||
@(posedge clk);
|
||||
|
||||
rst = 1'b0;
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("MEMORY INTERFACE V1 TEST");
|
||||
$display("ADDR_WIDTH = %0d", ADDR_WIDTH);
|
||||
$display("DATA_WIDTH = %0d", DATA_WIDTH);
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 1
|
||||
// --------------------------------------------------------
|
||||
|
||||
write_mem(
|
||||
22'h000001,
|
||||
16'h1234
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000001,
|
||||
16'h1234
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 2
|
||||
// --------------------------------------------------------
|
||||
|
||||
write_mem(
|
||||
22'h000010,
|
||||
16'hABCD
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000010,
|
||||
16'hABCD
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 3
|
||||
// --------------------------------------------------------
|
||||
|
||||
write_mem(
|
||||
22'h000100,
|
||||
16'h55AA
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000100,
|
||||
16'h55AA
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 4
|
||||
// --------------------------------------------------------
|
||||
// Consecutive different addresses
|
||||
|
||||
write_mem(
|
||||
22'h000200,
|
||||
16'h0001
|
||||
);
|
||||
|
||||
write_mem(
|
||||
22'h000201,
|
||||
16'h0002
|
||||
);
|
||||
|
||||
write_mem(
|
||||
22'h000202,
|
||||
16'h0003
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000200,
|
||||
16'h0001
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000201,
|
||||
16'h0002
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000202,
|
||||
16'h0003
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 5
|
||||
// --------------------------------------------------------
|
||||
// Zero value
|
||||
|
||||
write_mem(
|
||||
22'h000300,
|
||||
16'h0000
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000300,
|
||||
16'h0000
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test 6
|
||||
// --------------------------------------------------------
|
||||
// Full 16-bit value
|
||||
|
||||
write_mem(
|
||||
22'h000301,
|
||||
16'hFFFF
|
||||
);
|
||||
|
||||
read_mem(
|
||||
22'h000301,
|
||||
16'hFFFF
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Finished
|
||||
// --------------------------------------------------------
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("MEMORY INTERFACE V1 TEST PASSED");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// VCD
|
||||
// ------------------------------------------------------------
|
||||
|
||||
initial begin
|
||||
$dumpfile("sim/memory_interface.vcd");
|
||||
$dumpvars(0, memory_interface_tb);
|
||||
end
|
||||
|
||||
endmodule
|
||||
+73405
File diff suppressed because it is too large
Load Diff
Executable
+23299
File diff suppressed because one or more lines are too long
@@ -0,0 +1,625 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb;
|
||||
|
||||
localparam ADDR_WIDTH = 22;
|
||||
localparam DATA_WIDTH = 16;
|
||||
localparam CLK_PERIOD = 12.5; // 80 MHz
|
||||
|
||||
// ============================================================
|
||||
// CLOCK / RESET
|
||||
// ============================================================
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
forever #(CLK_PERIOD / 2.0) clk = ~clk;
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// NEURON MEMORY
|
||||
// ============================================================
|
||||
|
||||
reg start;
|
||||
|
||||
reg [ADDR_WIDTH-1:0] x_base;
|
||||
reg [ADDR_WIDTH-1:0] w_base;
|
||||
reg [ADDR_WIDTH-1:0] bias_addr;
|
||||
|
||||
wire signed [7:0] y;
|
||||
wire busy;
|
||||
wire done;
|
||||
|
||||
// neuron_memory -> memory_interface
|
||||
wire neuron_mem_req;
|
||||
wire neuron_mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] neuron_mem_addr;
|
||||
wire signed [7:0] neuron_mem_wdata;
|
||||
|
||||
wire signed [7:0] neuron_mem_rdata;
|
||||
wire neuron_mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// TB PRELOAD MASTER
|
||||
//
|
||||
// Direct 16-bit master.
|
||||
// Used only before starting neuron_memory.
|
||||
// ============================================================
|
||||
|
||||
reg tb_mem_req;
|
||||
reg tb_mem_wr;
|
||||
reg [ADDR_WIDTH-1:0] tb_mem_addr;
|
||||
reg [DATA_WIDTH-1:0] tb_mem_wdata;
|
||||
reg tb_mem_lb_n;
|
||||
reg tb_mem_ub_n;
|
||||
|
||||
wire [DATA_WIDTH-1:0] tb_mem_rdata;
|
||||
wire tb_mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// SINGLE MASTER MUX
|
||||
//
|
||||
// 0 = TB preload master
|
||||
// 1 = neuron_memory master
|
||||
// ============================================================
|
||||
|
||||
reg use_neuron_master;
|
||||
|
||||
wire master_req;
|
||||
wire master_wr;
|
||||
wire [ADDR_WIDTH-1:0] master_addr;
|
||||
wire [DATA_WIDTH-1:0] master_wdata;
|
||||
wire master_lb_n;
|
||||
wire master_ub_n;
|
||||
|
||||
// ============================================================
|
||||
// MEMORY INTERFACE
|
||||
// ============================================================
|
||||
|
||||
wire [DATA_WIDTH-1:0] memory_rdata;
|
||||
wire memory_ready;
|
||||
|
||||
wire memory_mem_req;
|
||||
wire memory_mem_wr;
|
||||
wire [ADDR_WIDTH-1:0] memory_mem_addr;
|
||||
wire [DATA_WIDTH-1:0] memory_mem_wdata;
|
||||
wire memory_mem_lb_n;
|
||||
wire memory_mem_ub_n;
|
||||
|
||||
wire [DATA_WIDTH-1:0] psram_mem_rdata;
|
||||
wire psram_mem_ready;
|
||||
|
||||
assign master_req =
|
||||
use_neuron_master ? neuron_mem_req : tb_mem_req;
|
||||
|
||||
assign master_wr =
|
||||
use_neuron_master ? neuron_mem_wr : tb_mem_wr;
|
||||
|
||||
assign master_addr =
|
||||
use_neuron_master ? (neuron_mem_addr >> 1) : tb_mem_addr;
|
||||
|
||||
assign master_wdata =
|
||||
use_neuron_master
|
||||
? (neuron_mem_addr[0]
|
||||
? {neuron_mem_wdata, 8'h00}
|
||||
: {8'h00, neuron_mem_wdata})
|
||||
: tb_mem_wdata;
|
||||
|
||||
assign master_lb_n =
|
||||
use_neuron_master
|
||||
? (neuron_mem_addr[0] ? 1'b1 : 1'b0)
|
||||
: tb_mem_lb_n;
|
||||
|
||||
assign master_ub_n =
|
||||
use_neuron_master
|
||||
? (neuron_mem_addr[0] ? 1'b0 : 1'b1)
|
||||
: tb_mem_ub_n;
|
||||
|
||||
// Return path
|
||||
assign tb_mem_rdata = memory_rdata;
|
||||
assign tb_mem_ready = memory_ready;
|
||||
|
||||
assign neuron_mem_rdata =
|
||||
neuron_mem_addr[0]
|
||||
? memory_rdata[15:8]
|
||||
: memory_rdata[7:0];
|
||||
|
||||
assign neuron_mem_ready = memory_ready;
|
||||
|
||||
memory_interface #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH)
|
||||
) u_memory_if (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.req(master_req),
|
||||
.wr(master_wr),
|
||||
.addr(master_addr),
|
||||
.wdata(master_wdata),
|
||||
.lb_n(master_lb_n),
|
||||
.ub_n(master_ub_n),
|
||||
|
||||
.rdata(memory_rdata),
|
||||
.ready(memory_ready),
|
||||
|
||||
.mem_req(memory_mem_req),
|
||||
.mem_wr(memory_mem_wr),
|
||||
.mem_addr(memory_mem_addr),
|
||||
.mem_wdata(memory_mem_wdata),
|
||||
.mem_lb_n(memory_mem_lb_n),
|
||||
.mem_ub_n(memory_mem_ub_n),
|
||||
|
||||
.mem_rdata(psram_mem_rdata),
|
||||
.mem_ready(psram_mem_ready)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PSRAM PHYSICAL INTERFACE
|
||||
// ============================================================
|
||||
|
||||
wire [ADDR_WIDTH-1:0] psram_a;
|
||||
wire [DATA_WIDTH-1:0] psram_dq;
|
||||
|
||||
wire psram_ce_n;
|
||||
wire psram_oe_n;
|
||||
wire psram_we_n;
|
||||
wire psram_lb_n;
|
||||
wire psram_ub_n;
|
||||
wire psram_zz_n;
|
||||
|
||||
// ============================================================
|
||||
// PSRAM CONTROLLER
|
||||
// ============================================================
|
||||
|
||||
psram_controller #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.CLK_FREQ_MHZ(80)
|
||||
) u_psram_ctrl (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.mem_req(memory_mem_req),
|
||||
.mem_wr(memory_mem_wr),
|
||||
.mem_addr(memory_mem_addr),
|
||||
.mem_wdata(memory_mem_wdata),
|
||||
.mem_lb_n(memory_mem_lb_n),
|
||||
.mem_ub_n(memory_mem_ub_n),
|
||||
|
||||
.mem_rdata(psram_mem_rdata),
|
||||
.mem_ready(psram_mem_ready),
|
||||
|
||||
.psram_a(psram_a),
|
||||
.psram_dq(psram_dq),
|
||||
.psram_ce_n(psram_ce_n),
|
||||
.psram_oe_n(psram_oe_n),
|
||||
.psram_we_n(psram_we_n),
|
||||
.psram_lb_n(psram_lb_n),
|
||||
.psram_ub_n(psram_ub_n),
|
||||
.psram_zz_n(psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PSRAM MODEL
|
||||
// ============================================================
|
||||
|
||||
psram_model #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.DEPTH(16384)
|
||||
) u_psram (
|
||||
.clk(clk),
|
||||
.a(psram_a),
|
||||
.dq(psram_dq),
|
||||
.ce_n(psram_ce_n),
|
||||
.oe_n(psram_oe_n),
|
||||
.we_n(psram_we_n),
|
||||
.lb_n(psram_lb_n),
|
||||
.ub_n(psram_ub_n),
|
||||
.zz_n(psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// NEURON MEMORY
|
||||
// ============================================================
|
||||
|
||||
neuron_memory #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(8),
|
||||
.N_INPUTS(32),
|
||||
.PARALLEL(8),
|
||||
.ACC_WIDTH(32)
|
||||
) u_neuron (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.start(start),
|
||||
|
||||
.mem_req(neuron_mem_req),
|
||||
.mem_wr(neuron_mem_wr),
|
||||
.mem_addr(neuron_mem_addr),
|
||||
.mem_wdata(neuron_mem_wdata),
|
||||
|
||||
.mem_rdata(neuron_mem_rdata),
|
||||
.mem_ready(neuron_mem_ready),
|
||||
|
||||
.x_base(x_base),
|
||||
.w_base(w_base),
|
||||
.bias_addr(bias_addr),
|
||||
|
||||
.y(y),
|
||||
.busy(busy),
|
||||
.done(done)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// TB WORD WRITE
|
||||
//
|
||||
// Directly through:
|
||||
//
|
||||
// TB -> memory_interface -> psram_controller -> PSRAM
|
||||
//
|
||||
// No force.
|
||||
// ============================================================
|
||||
|
||||
task tb_write_word;
|
||||
|
||||
input [ADDR_WIDTH-1:0] addr_i;
|
||||
input [15:0] data_i;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
tb_mem_addr <= addr_i;
|
||||
tb_mem_wdata <= data_i;
|
||||
tb_mem_wr <= 1'b1;
|
||||
tb_mem_lb_n <= 1'b0;
|
||||
tb_mem_ub_n <= 1'b0;
|
||||
tb_mem_req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
tb_mem_req <= 1'b0;
|
||||
|
||||
wait (tb_mem_ready);
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// PRELOAD 32 INT8 VALUES
|
||||
//
|
||||
// Two INT8 values per PSRAM word.
|
||||
// ============================================================
|
||||
|
||||
task preload_vector;
|
||||
|
||||
input [ADDR_WIDTH-1:0] base;
|
||||
input signed [7:0] value;
|
||||
|
||||
integer k;
|
||||
|
||||
begin
|
||||
|
||||
for (k = 0; k < 32; k = k + 2) begin
|
||||
|
||||
tb_write_word(
|
||||
base + (k >> 1),
|
||||
{value, value}
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// PRELOAD WEIGHTS
|
||||
// ============================================================
|
||||
|
||||
task preload_weights;
|
||||
|
||||
input [ADDR_WIDTH-1:0] base;
|
||||
input signed [7:0] value;
|
||||
|
||||
integer k;
|
||||
|
||||
begin
|
||||
|
||||
for (k = 0; k < 32; k = k + 2) begin
|
||||
|
||||
tb_write_word(
|
||||
base + (k >> 1),
|
||||
{value, value}
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// PRELOAD BIAS
|
||||
// ============================================================
|
||||
|
||||
task preload_bias;
|
||||
|
||||
input [ADDR_WIDTH-1:0] addr_i;
|
||||
input signed [7:0] value;
|
||||
|
||||
begin
|
||||
|
||||
// Bias address is a BYTE address.
|
||||
// Write a full word containing bias in low byte.
|
||||
|
||||
tb_write_word(
|
||||
addr_i >> 1,
|
||||
{8'h00, value}
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// RUN NEURON
|
||||
// ============================================================
|
||||
|
||||
task run_neuron;
|
||||
|
||||
input signed [7:0] expected;
|
||||
input [127:0] test_name;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
start <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
start <= 1'b0;
|
||||
|
||||
wait (done);
|
||||
|
||||
if (y !== expected) begin
|
||||
|
||||
$display("");
|
||||
$display("FAIL %s", test_name);
|
||||
$display(
|
||||
" got = %0d (0x%02x)",
|
||||
y,
|
||||
y
|
||||
);
|
||||
$display(
|
||||
" expected = %0d (0x%02x)",
|
||||
expected,
|
||||
expected
|
||||
);
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"PASS %-16s y=%0d (0x%02x)",
|
||||
test_name,
|
||||
y,
|
||||
y
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// TEST
|
||||
// ============================================================
|
||||
|
||||
integer i;
|
||||
|
||||
initial begin
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Initial values
|
||||
// --------------------------------------------------------
|
||||
|
||||
start = 1'b0;
|
||||
|
||||
x_base = 22'h000000;
|
||||
w_base = 22'h000100;
|
||||
bias_addr = 22'h000200;
|
||||
|
||||
tb_mem_req = 1'b0;
|
||||
tb_mem_wr = 1'b0;
|
||||
tb_mem_addr = 0;
|
||||
tb_mem_wdata = 0;
|
||||
tb_mem_lb_n = 1'b1;
|
||||
tb_mem_ub_n = 1'b1;
|
||||
|
||||
use_neuron_master = 1'b0;
|
||||
|
||||
rst = 1'b1;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// VCD
|
||||
// --------------------------------------------------------
|
||||
|
||||
$dumpfile("sim/neuron_memory.vcd");
|
||||
$dumpvars(0, tb);
|
||||
|
||||
repeat (5)
|
||||
@(posedge clk);
|
||||
|
||||
rst = 1'b0;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Wait PSRAM initialization
|
||||
// --------------------------------------------------------
|
||||
|
||||
wait (u_psram_ctrl.state == u_psram_ctrl.STATE_IDLE);
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("NEURON MEMORY END-TO-END TEST");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// PRELOAD PHASE
|
||||
//
|
||||
// TB is the ONLY memory master.
|
||||
// ========================================================
|
||||
|
||||
$display("PRELOAD: X = 1");
|
||||
preload_vector(
|
||||
x_base,
|
||||
8'sd1
|
||||
);
|
||||
|
||||
$display("PRELOAD: W = 1");
|
||||
preload_weights(
|
||||
w_base,
|
||||
8'sd1
|
||||
);
|
||||
|
||||
$display("PRELOAD: BIAS = 0");
|
||||
preload_bias(
|
||||
bias_addr,
|
||||
8'sd0
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// HAND OVER MEMORY BUS
|
||||
//
|
||||
// From this point neuron_memory is the only master.
|
||||
// ========================================================
|
||||
|
||||
use_neuron_master = 1'b1;
|
||||
|
||||
$display("");
|
||||
$display("MEMORY MASTER -> neuron_memory");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// TEST 1
|
||||
//
|
||||
// 32 * 1 * 1 + 0 = 32
|
||||
// ========================================================
|
||||
|
||||
run_neuron(
|
||||
8'sd32,
|
||||
"SUM=32"
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// TEST 2
|
||||
//
|
||||
// 32 * 1 * 4 = 128
|
||||
// Saturated to 127.
|
||||
//
|
||||
// We must return control to TB to modify weights.
|
||||
// ========================================================
|
||||
|
||||
use_neuron_master = 1'b0;
|
||||
|
||||
preload_weights(
|
||||
w_base,
|
||||
8'sd4
|
||||
);
|
||||
|
||||
preload_bias(
|
||||
bias_addr,
|
||||
8'sd0
|
||||
);
|
||||
|
||||
use_neuron_master = 1'b1;
|
||||
|
||||
run_neuron(
|
||||
8'sd127,
|
||||
"SATURATION"
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// TEST 3
|
||||
//
|
||||
// 32 * 1 * (-1) = -32
|
||||
// ReLU -> 0
|
||||
// ========================================================
|
||||
|
||||
use_neuron_master = 1'b0;
|
||||
|
||||
preload_weights(
|
||||
w_base,
|
||||
-8'sd1
|
||||
);
|
||||
|
||||
preload_bias(
|
||||
bias_addr,
|
||||
8'sd0
|
||||
);
|
||||
|
||||
use_neuron_master = 1'b1;
|
||||
|
||||
run_neuron(
|
||||
8'sd0,
|
||||
"RELU"
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// TEST 4
|
||||
//
|
||||
// 32 * 1 * 1 + 10 = 42
|
||||
// ========================================================
|
||||
|
||||
use_neuron_master = 1'b0;
|
||||
|
||||
preload_weights(
|
||||
w_base,
|
||||
8'sd1
|
||||
);
|
||||
|
||||
preload_bias(
|
||||
bias_addr,
|
||||
8'sd10
|
||||
);
|
||||
|
||||
use_neuron_master = 1'b1;
|
||||
|
||||
run_neuron(
|
||||
8'sd42,
|
||||
"BIAS=10"
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// FINAL
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("NEURON MEMORY TEST PASSED");
|
||||
$display("========================================");
|
||||
$display("PSRAM -> INT8 -> NEURON : PASS");
|
||||
$display("SUM : PASS");
|
||||
$display("BIAS : PASS");
|
||||
$display("ReLU : PASS");
|
||||
$display("SATURATION : PASS");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
+3292
-1609
File diff suppressed because one or more lines are too long
Executable
+5430
File diff suppressed because it is too large
Load Diff
Executable
+4242
File diff suppressed because it is too large
Load Diff
Executable
+2238
File diff suppressed because it is too large
Load Diff
+1801
-1633
File diff suppressed because it is too large
Load Diff
Executable
+5404
File diff suppressed because it is too large
Load Diff
Executable
+3350
File diff suppressed because it is too large
Load Diff
Executable
+5478
File diff suppressed because it is too large
Load Diff
+99
-193
@@ -2,12 +2,11 @@
|
||||
|
||||
module tb;
|
||||
|
||||
parameter DATA_WIDTH = 16;
|
||||
parameter FRAC_BITS = 8;
|
||||
parameter N_INPUTS = 32;
|
||||
parameter DATA_WIDTH = 8;
|
||||
parameter N_INPUTS = 256;
|
||||
parameter N_NEURONS = 4;
|
||||
parameter PARALLEL = 8;
|
||||
parameter ACC_WIDTH = 40;
|
||||
parameter PARALLEL = 32;
|
||||
parameter ACC_WIDTH = 32;
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
@@ -21,20 +20,17 @@ module tb;
|
||||
reg signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||
bias_bus;
|
||||
|
||||
wire signed [DATA_WIDTH*N_NEURONS-1:0]
|
||||
y_bus;
|
||||
wire signed [DATA_WIDTH*N_NEURONS-1:0] y_bus;
|
||||
|
||||
wire busy;
|
||||
wire done;
|
||||
|
||||
integer i;
|
||||
integer n;
|
||||
integer errors;
|
||||
integer expected;
|
||||
|
||||
layer #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.FRAC_BITS(FRAC_BITS),
|
||||
.N_INPUTS(N_INPUTS),
|
||||
.N_NEURONS(N_NEURONS),
|
||||
.PARALLEL(PARALLEL),
|
||||
@@ -56,13 +52,6 @@ module tb;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
function signed [15:0] q8_8;
|
||||
input real value;
|
||||
begin
|
||||
q8_8 = $rtoi(value * 256.0);
|
||||
end
|
||||
endfunction
|
||||
|
||||
task run_layer;
|
||||
begin
|
||||
@(posedge clk);
|
||||
@@ -94,107 +83,81 @@ module tb;
|
||||
rst = 0;
|
||||
|
||||
/*
|
||||
* All inputs = 1.0
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
x_bus[i*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||
* Tutti gli input = 1
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
x_bus[i*DATA_WIDTH +: DATA_WIDTH] = 8'sd1;
|
||||
|
||||
/*
|
||||
* Neuron 0: weight = 1.0
|
||||
* result = N_INPUTS
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
0*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(1.0);
|
||||
/*
|
||||
* N0:
|
||||
* primi 32 pesi = 1
|
||||
* restanti 224 = 0
|
||||
*
|
||||
* Risultato = 32
|
||||
*
|
||||
* Questo verifica che l'accumulatore
|
||||
* attraversi correttamente tutti gli 8 gruppi.
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
0*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = (i < 32) ? 8'sd1 : 8'sd0;
|
||||
|
||||
/*
|
||||
* Neuron 1: weight = 0.5
|
||||
* result = N_INPUTS / 2
|
||||
*/
|
||||
if (N_NEURONS > 1)
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
1*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(0.5);
|
||||
/*
|
||||
* N1:
|
||||
* tutti i 256 pesi = 0
|
||||
* bias = 10
|
||||
*
|
||||
* Risultato = 10
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
1*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = 8'sd0;
|
||||
|
||||
/*
|
||||
* Neuron 2: weight = -0.5
|
||||
* ReLU -> 0
|
||||
*/
|
||||
if (N_NEURONS > 2)
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
2*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(-0.5);
|
||||
bias_bus[1*DATA_WIDTH +: DATA_WIDTH] = 8'sd10;
|
||||
|
||||
/*
|
||||
* Neuron 3: weight = 2.0
|
||||
* Large positive result -> saturation
|
||||
*/
|
||||
if (N_NEURONS > 3)
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
3*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(2.0);
|
||||
/*
|
||||
* N2:
|
||||
* tutti i pesi = -1
|
||||
*
|
||||
* Risultato = -256
|
||||
* ReLU -> 0
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
2*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = -8'sd1;
|
||||
|
||||
/*
|
||||
* Neuron 4: zero weights + bias +1
|
||||
*/
|
||||
if (N_NEURONS > 4)
|
||||
bias_bus[4*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||
|
||||
/*
|
||||
* Neuron 5: zero weights + bias -1
|
||||
* ReLU -> 0
|
||||
*/
|
||||
if (N_NEURONS > 5)
|
||||
bias_bus[5*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||
|
||||
/*
|
||||
* Neuron 6: weight 1.0 + bias -1.0
|
||||
* result = N_INPUTS - 1
|
||||
*/
|
||||
if (N_NEURONS > 6) begin
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
6*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(1.0);
|
||||
|
||||
bias_bus[6*DATA_WIDTH +: DATA_WIDTH] = q8_8(-1.0);
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 7: weight 0.25 + bias 1
|
||||
* result = N_INPUTS/4 + 1
|
||||
*/
|
||||
if (N_NEURONS > 7) begin
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
7*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = q8_8(0.25);
|
||||
|
||||
bias_bus[7*DATA_WIDTH +: DATA_WIDTH] = q8_8(1.0);
|
||||
end
|
||||
/*
|
||||
* N3:
|
||||
* primi 32 pesi = 4
|
||||
* restanti = 0
|
||||
*
|
||||
* Risultato = 128
|
||||
* Saturazione INT8 -> 127
|
||||
*/
|
||||
for (i = 0; i < N_INPUTS; i = i + 1)
|
||||
weights_bus[
|
||||
3*N_INPUTS*DATA_WIDTH +
|
||||
i*DATA_WIDTH +:
|
||||
DATA_WIDTH
|
||||
] = (i < 32) ? 8'sd4 : 8'sd0;
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PARAMETRIC LAYER TEST");
|
||||
$display("INT8 / INT32 PARAMETRIC LAYER TEST");
|
||||
$display("N_INPUTS = %0d", N_INPUTS);
|
||||
$display("N_NEURONS = %0d", N_NEURONS);
|
||||
$display("PARALLEL = %0d", PARALLEL);
|
||||
$display("DATA_WIDTH = %0d", DATA_WIDTH);
|
||||
$display("ACC_WIDTH = %0d", ACC_WIDTH);
|
||||
$display("========================================");
|
||||
|
||||
run_layer;
|
||||
@@ -202,40 +165,45 @@ module tb;
|
||||
/*
|
||||
* Neuron 0
|
||||
*/
|
||||
expected = N_INPUTS * 256;
|
||||
expected = 32;
|
||||
|
||||
if (y_bus[0*16 +: 16] !== expected[15:0]) begin
|
||||
if ($signed(y_bus[0*DATA_WIDTH +: DATA_WIDTH]) !== expected) begin
|
||||
$display("FAIL N0: got %0d expected %0d",
|
||||
y_bus[0*16 +: 16], expected);
|
||||
$signed(y_bus[0*DATA_WIDTH +: DATA_WIDTH]),
|
||||
expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N0: %0d", y_bus[0*16 +: 16]);
|
||||
$display("PASS N0: %0d", $signed(y_bus[0*DATA_WIDTH +: DATA_WIDTH]));
|
||||
|
||||
/*
|
||||
* Neuron 1
|
||||
*/
|
||||
if (N_NEURONS > 1) begin
|
||||
expected = (N_INPUTS * 128);
|
||||
|
||||
if (y_bus[1*16 +: 16] !== expected[15:0]) begin
|
||||
expected = 10;
|
||||
|
||||
if ($signed(y_bus[1*DATA_WIDTH +: DATA_WIDTH]) !== expected) begin
|
||||
$display("FAIL N1: got %0d expected %0d",
|
||||
y_bus[1*16 +: 16], expected);
|
||||
$signed(y_bus[1*DATA_WIDTH +: DATA_WIDTH]),
|
||||
expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N1: %0d", y_bus[1*16 +: 16]);
|
||||
$display("PASS N1: %0d",
|
||||
$signed(y_bus[1*DATA_WIDTH +: DATA_WIDTH]));
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 2
|
||||
*/
|
||||
if (N_NEURONS > 2) begin
|
||||
|
||||
expected = 0;
|
||||
|
||||
if (y_bus[2*16 +: 16] !== 16'sd0) begin
|
||||
if ($signed(y_bus[2*DATA_WIDTH +: DATA_WIDTH]) !== 0) begin
|
||||
$display("FAIL N2: got %0d expected 0",
|
||||
y_bus[2*16 +: 16]);
|
||||
$signed(y_bus[2*DATA_WIDTH +: DATA_WIDTH]));
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
@@ -243,86 +211,24 @@ module tb;
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 3:
|
||||
* weight = 2.0
|
||||
* result = N_INPUTS * 2.0
|
||||
*
|
||||
* Saturation only occurs when result > 127.996...
|
||||
*/
|
||||
* Neuron 3
|
||||
*
|
||||
* 32 * 4 = 128
|
||||
* INT8 positive saturation -> 127
|
||||
*/
|
||||
if (N_NEURONS > 3) begin
|
||||
|
||||
expected = N_INPUTS * 2 * 256;
|
||||
expected = 127;
|
||||
|
||||
if (expected > 32767)
|
||||
expected = 32767;
|
||||
|
||||
if (y_bus[3*16 +: 16] !== expected[15:0]) begin
|
||||
$display("FAIL N3: got %0d expected %0d",
|
||||
y_bus[3*16 +: 16], expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else begin
|
||||
if (expected == 32767)
|
||||
$display("PASS N3: %0d (saturation)", y_bus[3*16 +: 16]);
|
||||
else
|
||||
$display("PASS N3: %0d", y_bus[3*16 +: 16]);
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 4
|
||||
*/
|
||||
if (N_NEURONS > 4) begin
|
||||
if (y_bus[4*16 +: 16] !== 16'sd256) begin
|
||||
$display("FAIL N4: got %0d expected 256",
|
||||
y_bus[4*16 +: 16]);
|
||||
if ($signed(y_bus[3*DATA_WIDTH +: DATA_WIDTH]) !== expected) begin
|
||||
$display("FAIL N3: got %0d expected %0d",
|
||||
$signed(y_bus[3*DATA_WIDTH +: DATA_WIDTH]),
|
||||
expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N4: 256 (bias)");
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 5
|
||||
*/
|
||||
if (N_NEURONS > 5) begin
|
||||
if (y_bus[5*16 +: 16] !== 16'sd0) begin
|
||||
$display("FAIL N5: got %0d expected 0",
|
||||
y_bus[5*16 +: 16]);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N5: 0 (negative bias + ReLU)");
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 6
|
||||
*/
|
||||
if (N_NEURONS > 6) begin
|
||||
expected = (N_INPUTS - 1) * 256;
|
||||
|
||||
if (y_bus[6*16 +: 16] !== expected[15:0]) begin
|
||||
$display("FAIL N6: got %0d expected %0d",
|
||||
y_bus[6*16 +: 16], expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N6: %0d", y_bus[6*16 +: 16]);
|
||||
end
|
||||
|
||||
/*
|
||||
* Neuron 7
|
||||
*/
|
||||
if (N_NEURONS > 7) begin
|
||||
expected = (N_INPUTS / 4 + 1) * 256;
|
||||
|
||||
if (y_bus[7*16 +: 16] !== expected[15:0]) begin
|
||||
$display("FAIL N7: got %0d expected %0d",
|
||||
y_bus[7*16 +: 16], expected);
|
||||
errors = errors + 1;
|
||||
end
|
||||
else
|
||||
$display("PASS N7: %0d", y_bus[7*16 +: 16]);
|
||||
$display("PASS N3: %0d (saturation)",
|
||||
$signed(y_bus[3*DATA_WIDTH +: DATA_WIDTH]));
|
||||
end
|
||||
|
||||
if (busy !== 0) begin
|
||||
@@ -339,9 +245,9 @@ module tb;
|
||||
$display("========================================");
|
||||
|
||||
if (errors == 0)
|
||||
$display("PARAMETRIC TEST PASSED");
|
||||
$display("INT8 PARAMETRIC TEST PASSED");
|
||||
else
|
||||
$display("PARAMETRIC TEST FAILED: %0d errors", errors);
|
||||
$display("INT8 PARAMETRIC TEST FAILED: %0d errors", errors);
|
||||
|
||||
$display("========================================");
|
||||
$display("");
|
||||
@@ -349,4 +255,4 @@ module tb;
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
endmodule
|
||||
+427102
File diff suppressed because it is too large
Load Diff
Executable
+21957
File diff suppressed because one or more lines are too long
@@ -0,0 +1,498 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module tb;
|
||||
|
||||
localparam ADDR_WIDTH = 22;
|
||||
localparam DATA_WIDTH = 16;
|
||||
localparam CLK_PERIOD = 12.5; // 80 MHz
|
||||
|
||||
reg clk;
|
||||
reg rst;
|
||||
|
||||
// ============================================================
|
||||
// Memory Interface
|
||||
// ============================================================
|
||||
|
||||
reg mem_req;
|
||||
reg mem_wr;
|
||||
reg [ADDR_WIDTH-1:0] mem_addr;
|
||||
reg [DATA_WIDTH-1:0] mem_wdata;
|
||||
reg mem_lb_n;
|
||||
reg mem_ub_n;
|
||||
|
||||
wire [DATA_WIDTH-1:0] mem_rdata;
|
||||
wire mem_ready;
|
||||
|
||||
// ============================================================
|
||||
// PSRAM
|
||||
// ============================================================
|
||||
|
||||
wire [ADDR_WIDTH-1:0] psram_a;
|
||||
wire [DATA_WIDTH-1:0] psram_dq;
|
||||
|
||||
wire psram_ce_n;
|
||||
wire psram_oe_n;
|
||||
wire psram_we_n;
|
||||
wire psram_lb_n;
|
||||
wire psram_ub_n;
|
||||
wire psram_zz_n;
|
||||
|
||||
// ============================================================
|
||||
// Stress-test variables
|
||||
// ============================================================
|
||||
|
||||
integer stress_i;
|
||||
integer stress_addr;
|
||||
reg [15:0] stress_data;
|
||||
|
||||
// ============================================================
|
||||
// DUT
|
||||
// ============================================================
|
||||
|
||||
psram_controller #(
|
||||
.ADDR_WIDTH (ADDR_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.CLK_FREQ_MHZ (80)
|
||||
) dut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.mem_req (mem_req),
|
||||
.mem_wr (mem_wr),
|
||||
.mem_addr (mem_addr),
|
||||
.mem_wdata (mem_wdata),
|
||||
.mem_lb_n (mem_lb_n),
|
||||
.mem_ub_n (mem_ub_n),
|
||||
|
||||
.mem_rdata (mem_rdata),
|
||||
.mem_ready (mem_ready),
|
||||
|
||||
.psram_a (psram_a),
|
||||
.psram_dq (psram_dq),
|
||||
|
||||
.psram_ce_n(psram_ce_n),
|
||||
.psram_oe_n(psram_oe_n),
|
||||
.psram_we_n(psram_we_n),
|
||||
.psram_lb_n(psram_lb_n),
|
||||
.psram_ub_n(psram_ub_n),
|
||||
.psram_zz_n(psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PSRAM model
|
||||
// ============================================================
|
||||
|
||||
psram_model #(
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.DEPTH(16384)
|
||||
) memory (
|
||||
.clk (clk),
|
||||
.a (psram_a),
|
||||
.dq (psram_dq),
|
||||
.ce_n (psram_ce_n),
|
||||
.oe_n (psram_oe_n),
|
||||
.we_n (psram_we_n),
|
||||
.lb_n (psram_lb_n),
|
||||
.ub_n (psram_ub_n),
|
||||
.zz_n (psram_zz_n)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// Clock
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
|
||||
forever #(CLK_PERIOD / 2.0)
|
||||
clk = ~clk;
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// VCD
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
$dumpfile("sim/psram_controller.vcd");
|
||||
$dumpvars(0, tb);
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// Helper: write word with byte enables
|
||||
//
|
||||
// lb_n = 0 -> low byte enabled
|
||||
// ub_n = 0 -> high byte enabled
|
||||
// ============================================================
|
||||
|
||||
task write_word;
|
||||
input [ADDR_WIDTH-1:0] addr;
|
||||
input [DATA_WIDTH-1:0] data;
|
||||
input lb;
|
||||
input ub;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
mem_addr <= addr;
|
||||
mem_wdata <= data;
|
||||
mem_wr <= 1'b1;
|
||||
mem_lb_n <= lb;
|
||||
mem_ub_n <= ub;
|
||||
mem_req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
mem_req <= 1'b0;
|
||||
|
||||
wait (mem_ready);
|
||||
|
||||
$display(
|
||||
"WRITE addr=0x%08x data=0x%04x LB#=%b UB#=%b PASS",
|
||||
addr,
|
||||
data,
|
||||
lb,
|
||||
ub
|
||||
);
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Helper: read full word
|
||||
//
|
||||
// For normal word reads both bytes are enabled.
|
||||
// ============================================================
|
||||
|
||||
task read_word;
|
||||
input [ADDR_WIDTH-1:0] addr;
|
||||
input [DATA_WIDTH-1:0] expected;
|
||||
|
||||
begin
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
mem_addr <= addr;
|
||||
mem_wr <= 1'b0;
|
||||
mem_lb_n <= 1'b0;
|
||||
mem_ub_n <= 1'b0;
|
||||
mem_req <= 1'b1;
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
mem_req <= 1'b0;
|
||||
|
||||
wait (mem_ready);
|
||||
|
||||
if (mem_rdata !== expected) begin
|
||||
|
||||
$display(
|
||||
"READ addr=0x%08x FAIL got=0x%04x expected=0x%04x",
|
||||
addr,
|
||||
mem_rdata,
|
||||
expected
|
||||
);
|
||||
|
||||
$fatal;
|
||||
|
||||
end else begin
|
||||
|
||||
$display(
|
||||
"READ addr=0x%08x data=0x%04x PASS",
|
||||
addr,
|
||||
mem_rdata
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
@(posedge clk);
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
// ============================================================
|
||||
// Test
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
mem_req = 1'b0;
|
||||
mem_wr = 1'b0;
|
||||
mem_addr = 0;
|
||||
mem_wdata = 0;
|
||||
|
||||
// Both bytes disabled while idle
|
||||
mem_lb_n = 1'b1;
|
||||
mem_ub_n = 1'b1;
|
||||
|
||||
rst = 1'b1;
|
||||
|
||||
repeat (5)
|
||||
@(posedge clk);
|
||||
|
||||
rst = 1'b0;
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM CONTROLLER V1 TEST");
|
||||
$display("80 MHz");
|
||||
$display("4M x 16 PSRAM");
|
||||
$display("70 ns asynchronous timing");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
wait (dut.state == dut.STATE_IDLE);
|
||||
|
||||
$display("PSRAM initialization complete");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// Basic writes / reads
|
||||
// ========================================================
|
||||
|
||||
write_word(22'h000001, 16'h1234, 1'b0, 1'b0);
|
||||
read_word (22'h000001, 16'h1234);
|
||||
|
||||
write_word(22'h000010, 16'hABCD, 1'b0, 1'b0);
|
||||
read_word (22'h000010, 16'hABCD);
|
||||
|
||||
write_word(22'h000100, 16'h55AA, 1'b0, 1'b0);
|
||||
read_word (22'h000100, 16'h55AA);
|
||||
|
||||
// ========================================================
|
||||
// Consecutive words
|
||||
// ========================================================
|
||||
|
||||
write_word(22'h000200, 16'h0001, 1'b0, 1'b0);
|
||||
write_word(22'h000201, 16'h0002, 1'b0, 1'b0);
|
||||
write_word(22'h000202, 16'h0003, 1'b0, 1'b0);
|
||||
|
||||
read_word(22'h000200, 16'h0001);
|
||||
read_word(22'h000201, 16'h0002);
|
||||
read_word(22'h000202, 16'h0003);
|
||||
|
||||
// ========================================================
|
||||
// Edge values
|
||||
// ========================================================
|
||||
|
||||
write_word(22'h000300, 16'h0000, 1'b0, 1'b0);
|
||||
read_word (22'h000300, 16'h0000);
|
||||
|
||||
write_word(22'h000301, 16'hFFFF, 1'b0, 1'b0);
|
||||
read_word (22'h000301, 16'hFFFF);
|
||||
|
||||
// ========================================================
|
||||
// High address
|
||||
// ========================================================
|
||||
|
||||
write_word(22'h003FFF, 16'hCAFE, 1'b0, 1'b0);
|
||||
read_word (22'h003FFF, 16'hCAFE);
|
||||
|
||||
// ========================================================
|
||||
// Basic test passed
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM CONTROLLER BASIC TEST PASSED");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// BYTE ENABLE TEST
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM BYTE ENABLE TEST");
|
||||
$display("LB# / UB#");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Start from known value
|
||||
// --------------------------------------------------------
|
||||
|
||||
write_word(
|
||||
22'h000400,
|
||||
16'h1234,
|
||||
1'b0,
|
||||
1'b0
|
||||
);
|
||||
|
||||
read_word(
|
||||
22'h000400,
|
||||
16'h1234
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// LOW BYTE ONLY
|
||||
//
|
||||
// Initial: 0x1234
|
||||
// Write: 0x00AA
|
||||
//
|
||||
// LB# = 0 -> low byte written
|
||||
// UB# = 1 -> high byte preserved
|
||||
//
|
||||
// Expected: 0x12AA
|
||||
// --------------------------------------------------------
|
||||
|
||||
$display("");
|
||||
$display("LOW BYTE ONLY");
|
||||
$display("Initial = 0x1234");
|
||||
$display("Write = 0x00AA");
|
||||
$display("LB#=0 UB#=1");
|
||||
$display("Expected= 0x12AA");
|
||||
$display("");
|
||||
|
||||
write_word(
|
||||
22'h000400,
|
||||
16'h00AA,
|
||||
1'b0,
|
||||
1'b1
|
||||
);
|
||||
|
||||
read_word(
|
||||
22'h000400,
|
||||
16'h12AA
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// HIGH BYTE ONLY
|
||||
//
|
||||
// Current: 0x12AA
|
||||
// Write: 0xBB00
|
||||
//
|
||||
// LB# = 1 -> low byte preserved
|
||||
// UB# = 0 -> high byte written
|
||||
//
|
||||
// Expected: 0xBBAA
|
||||
// --------------------------------------------------------
|
||||
|
||||
$display("");
|
||||
$display("HIGH BYTE ONLY");
|
||||
$display("Initial = 0x12AA");
|
||||
$display("Write = 0xBB00");
|
||||
$display("LB#=1 UB#=0");
|
||||
$display("Expected= 0xBBAA");
|
||||
$display("");
|
||||
|
||||
write_word(
|
||||
22'h000400,
|
||||
16'hBB00,
|
||||
1'b1,
|
||||
1'b0
|
||||
);
|
||||
|
||||
read_word(
|
||||
22'h000400,
|
||||
16'hBBAA
|
||||
);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// FULL WORD
|
||||
//
|
||||
// Current: 0xBBAA
|
||||
// Write: 0xCCDD
|
||||
//
|
||||
// LB# = 0 -> low byte written
|
||||
// UB# = 0 -> high byte written
|
||||
//
|
||||
// Expected: 0xCCDD
|
||||
// --------------------------------------------------------
|
||||
|
||||
$display("");
|
||||
$display("FULL WORD");
|
||||
$display("Initial = 0xBBAA");
|
||||
$display("Write = 0xCCDD");
|
||||
$display("LB#=0 UB#=0");
|
||||
$display("Expected= 0xCCDD");
|
||||
$display("");
|
||||
|
||||
write_word(
|
||||
22'h000400,
|
||||
16'hCCDD,
|
||||
1'b0,
|
||||
1'b0
|
||||
);
|
||||
|
||||
read_word(
|
||||
22'h000400,
|
||||
16'hCCDD
|
||||
);
|
||||
|
||||
// ========================================================
|
||||
// BYTE ENABLE TEST PASSED
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM BYTE ENABLE TEST PASSED");
|
||||
$display("LOW BYTE : PASS");
|
||||
$display("HIGH BYTE : PASS");
|
||||
$display("FULL WORD : PASS");
|
||||
$display("PRESERVE : PASS");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
// ========================================================
|
||||
// STRESS TEST
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM STRESS TEST");
|
||||
$display("2048 WRITE + READ transactions");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
for (stress_i = 0;
|
||||
stress_i < 2048;
|
||||
stress_i = stress_i + 1) begin
|
||||
|
||||
stress_addr =
|
||||
((stress_i * 7919) ^ (stress_i << 5)) & 16'h3FFF;
|
||||
|
||||
stress_data =
|
||||
((stress_i * 1237) ^ 16'hA5A5);
|
||||
|
||||
write_word(
|
||||
stress_addr,
|
||||
stress_data,
|
||||
1'b0,
|
||||
1'b0
|
||||
);
|
||||
|
||||
read_word(
|
||||
stress_addr,
|
||||
stress_data
|
||||
);
|
||||
|
||||
if ((stress_i % 128) == 0)
|
||||
$display(
|
||||
"STRESS %0d / 2048 PASS",
|
||||
stress_i
|
||||
);
|
||||
|
||||
end
|
||||
|
||||
// ========================================================
|
||||
// Final result
|
||||
// ========================================================
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM CONTROLLER V1 TEST PASSED");
|
||||
$display("2048 WRITE + READ stress transactions");
|
||||
$display("BYTE ENABLE TEST PASSED");
|
||||
$display("========================================");
|
||||
$display("");
|
||||
|
||||
$finish;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,502 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module psram_model #(
|
||||
parameter ADDR_WIDTH = 22,
|
||||
parameter DATA_WIDTH = 16,
|
||||
parameter DEPTH = 16384
|
||||
)(
|
||||
input wire clk,
|
||||
input wire [ADDR_WIDTH-1:0] a,
|
||||
inout wire [DATA_WIDTH-1:0] dq,
|
||||
input wire ce_n,
|
||||
input wire oe_n,
|
||||
input wire we_n,
|
||||
input wire lb_n,
|
||||
input wire ub_n,
|
||||
input wire zz_n
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// IS66WVE4M16EBLL-70BLI - Rev. D3
|
||||
// ============================================================
|
||||
|
||||
localparam realtime TAA_NS = 70.0;
|
||||
localparam realtime TRC_NS = 70.0;
|
||||
localparam realtime TOE_NS = 20.0;
|
||||
localparam realtime TOH_NS = 5.0;
|
||||
|
||||
localparam realtime TLZ_NS = 10.0;
|
||||
localparam realtime THZ_NS = 8.0;
|
||||
|
||||
localparam realtime TWC_NS = 70.0;
|
||||
localparam realtime TAW_NS = 70.0;
|
||||
localparam realtime TCW_NS = 70.0;
|
||||
localparam realtime TWP_NS = 46.0;
|
||||
localparam realtime TDW_NS = 23.0;
|
||||
localparam realtime TDH_NS = 0.0;
|
||||
localparam realtime TWR_NS = 0.0;
|
||||
localparam realtime TWPH_NS = 10.0;
|
||||
|
||||
localparam realtime TPU_NS = 150000.0;
|
||||
|
||||
// ============================================================
|
||||
// Memory
|
||||
// ============================================================
|
||||
|
||||
reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
|
||||
|
||||
reg [DATA_WIDTH-1:0] dq_out;
|
||||
reg dq_oe;
|
||||
|
||||
integer i;
|
||||
|
||||
assign dq = dq_oe ? dq_out : {DATA_WIDTH{1'bz}};
|
||||
|
||||
// ============================================================
|
||||
// Timing state
|
||||
// ============================================================
|
||||
|
||||
realtime powerup_time;
|
||||
|
||||
realtime ce_low_time;
|
||||
realtime ce_high_time;
|
||||
|
||||
realtime oe_low_time;
|
||||
realtime oe_high_time;
|
||||
|
||||
realtime we_low_time;
|
||||
realtime we_high_time;
|
||||
|
||||
realtime last_read_start;
|
||||
realtime last_write_start;
|
||||
|
||||
realtime addr_valid_time;
|
||||
realtime data_valid_time;
|
||||
|
||||
reg read_active;
|
||||
reg write_active;
|
||||
|
||||
reg [ADDR_WIDTH-1:0] active_addr;
|
||||
reg [DATA_WIDTH-1:0] active_wdata;
|
||||
|
||||
// ============================================================
|
||||
// Initialization
|
||||
// ============================================================
|
||||
|
||||
initial begin
|
||||
|
||||
for (i = 0; i < DEPTH; i = i + 1)
|
||||
mem[i] = 16'h0000;
|
||||
|
||||
dq_out = 16'h0000;
|
||||
dq_oe = 1'b0;
|
||||
|
||||
powerup_time = $realtime;
|
||||
|
||||
ce_low_time = 0.0;
|
||||
ce_high_time = 0.0;
|
||||
|
||||
oe_low_time = 0.0;
|
||||
oe_high_time = 0.0;
|
||||
|
||||
we_low_time = 0.0;
|
||||
we_high_time = 0.0;
|
||||
|
||||
last_read_start = -1.0;
|
||||
last_write_start = -1.0;
|
||||
|
||||
addr_valid_time = 0.0;
|
||||
data_valid_time = 0.0;
|
||||
|
||||
read_active = 1'b0;
|
||||
write_active = 1'b0;
|
||||
|
||||
active_addr = 0;
|
||||
active_wdata = 0;
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// FUNCTIONAL READ MODEL
|
||||
// ============================================================
|
||||
|
||||
always @(*) begin
|
||||
|
||||
dq_oe = 1'b0;
|
||||
dq_out = 16'h0000;
|
||||
|
||||
if (zz_n &&
|
||||
!ce_n &&
|
||||
!oe_n &&
|
||||
we_n) begin
|
||||
|
||||
if (a < DEPTH) begin
|
||||
|
||||
dq_oe = 1'b1;
|
||||
|
||||
if (!lb_n && !ub_n)
|
||||
dq_out = mem[a];
|
||||
|
||||
else if (!lb_n)
|
||||
dq_out = {
|
||||
8'h00,
|
||||
mem[a][7:0]
|
||||
};
|
||||
|
||||
else if (!ub_n)
|
||||
dq_out = {
|
||||
mem[a][15:8],
|
||||
8'h00
|
||||
};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// CE# FALLING
|
||||
// ============================================================
|
||||
|
||||
always @(negedge ce_n) begin
|
||||
|
||||
if (!zz_n) begin
|
||||
$display("ERROR: CE# LOW while ZZ# LOW");
|
||||
$fatal;
|
||||
end
|
||||
|
||||
ce_low_time = $realtime;
|
||||
|
||||
addr_valid_time = $realtime;
|
||||
active_addr = a;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// READ START
|
||||
// --------------------------------------------------------
|
||||
|
||||
if (!oe_n && we_n) begin
|
||||
|
||||
if (($realtime - powerup_time) < TPU_NS) begin
|
||||
$display("ERROR: READ before tPU");
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (last_read_start >= 0.0) begin
|
||||
|
||||
if (($realtime - last_read_start) < TRC_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tRC violation");
|
||||
$display("required = %0.2f ns", TRC_NS);
|
||||
$display("actual = %0.2f ns",
|
||||
$realtime - last_read_start);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
|
||||
last_read_start = $realtime;
|
||||
|
||||
read_active = 1'b1;
|
||||
end
|
||||
|
||||
// --------------------------------------------------------
|
||||
// WRITE START
|
||||
// --------------------------------------------------------
|
||||
|
||||
if (oe_n && !we_n) begin
|
||||
|
||||
if (($realtime - powerup_time) < TPU_NS) begin
|
||||
$display("ERROR: WRITE before tPU");
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (last_write_start >= 0.0) begin
|
||||
|
||||
if (($realtime - last_write_start) < TWC_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tWC violation");
|
||||
$display("required = %0.2f ns", TWC_NS);
|
||||
$display("actual = %0.2f ns",
|
||||
$realtime - last_write_start);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
|
||||
last_write_start = $realtime;
|
||||
|
||||
write_active = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// CE# RISING
|
||||
// ============================================================
|
||||
|
||||
always @(posedge ce_n) begin
|
||||
|
||||
realtime access_time;
|
||||
|
||||
ce_high_time = $realtime;
|
||||
|
||||
access_time = $realtime - ce_low_time;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// READ END
|
||||
// --------------------------------------------------------
|
||||
|
||||
if (read_active) begin
|
||||
|
||||
// tAA
|
||||
if (access_time < TAA_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tAA violation");
|
||||
$display("required = %0.2f ns", TAA_NS);
|
||||
$display("actual = %0.2f ns", access_time);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
// tOE
|
||||
if (($realtime - oe_low_time) < TOE_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tOE violation");
|
||||
$display("required = %0.2f ns", TOE_NS);
|
||||
$display("actual = %0.2f ns",
|
||||
$realtime - oe_low_time);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
read_active = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// OE# FALLING
|
||||
// ============================================================
|
||||
|
||||
always @(negedge oe_n) begin
|
||||
|
||||
if (!zz_n) begin
|
||||
$display("ERROR: OE# LOW while ZZ# LOW");
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (!ce_n && we_n)
|
||||
oe_low_time = $realtime;
|
||||
|
||||
// Illegal combination
|
||||
if (!ce_n && !we_n) begin
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM PROTOCOL ERROR");
|
||||
$display("OE# and WE# LOW simultaneously");
|
||||
$display("========================================");
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// OE# RISING
|
||||
// ============================================================
|
||||
|
||||
always @(posedge oe_n) begin
|
||||
|
||||
oe_high_time = $realtime;
|
||||
|
||||
// Output must remain valid long enough for tOH
|
||||
// after address changes. This is checked by the
|
||||
// controller access window rather than by forcing
|
||||
// an artificial delay into the functional model.
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// WE# FALLING
|
||||
// ============================================================
|
||||
|
||||
always @(negedge we_n) begin
|
||||
|
||||
if (!zz_n) begin
|
||||
$display("ERROR: WE# LOW while ZZ# LOW");
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (!ce_n && oe_n) begin
|
||||
|
||||
we_low_time = $realtime;
|
||||
|
||||
active_addr = a;
|
||||
active_wdata = dq;
|
||||
|
||||
write_active = 1'b1;
|
||||
end
|
||||
|
||||
// Illegal combination
|
||||
if (!ce_n && !oe_n) begin
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM PROTOCOL ERROR");
|
||||
$display("OE# and WE# LOW simultaneously");
|
||||
$display("========================================");
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// WE# RISING
|
||||
// ============================================================
|
||||
|
||||
always @(posedge we_n) begin
|
||||
|
||||
realtime write_width;
|
||||
realtime data_setup;
|
||||
|
||||
we_high_time = $realtime;
|
||||
|
||||
if (write_active) begin
|
||||
|
||||
write_width = $realtime - we_low_time;
|
||||
|
||||
// ----------------------------------------------------
|
||||
// tWP
|
||||
// ----------------------------------------------------
|
||||
|
||||
if (write_width < TWP_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tWP violation");
|
||||
$display("required = %0.2f ns", TWP_NS);
|
||||
$display("actual = %0.2f ns", write_width);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
// ----------------------------------------------------
|
||||
// tAW
|
||||
// ----------------------------------------------------
|
||||
|
||||
if (($realtime - addr_valid_time) < TAW_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tAW violation");
|
||||
$display("required = %0.2f ns", TAW_NS);
|
||||
$display("actual = %0.2f ns",
|
||||
$realtime - addr_valid_time);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
// ----------------------------------------------------
|
||||
// tCW
|
||||
// ----------------------------------------------------
|
||||
|
||||
if (($realtime - ce_low_time) < TCW_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tCW violation");
|
||||
$display("required = %0.2f ns", TCW_NS);
|
||||
$display("actual = %0.2f ns",
|
||||
$realtime - ce_low_time);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
// ----------------------------------------------------
|
||||
// tDW
|
||||
//
|
||||
// Data must be valid before WE# rises.
|
||||
// Our controller drives DQ from WE# falling,
|
||||
// therefore setup is much larger than 23 ns.
|
||||
// ----------------------------------------------------
|
||||
|
||||
data_setup = $realtime - we_low_time;
|
||||
|
||||
if (data_setup < TDW_NS) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM TIMING ERROR");
|
||||
$display("tDW violation");
|
||||
$display("required = %0.2f ns", TDW_NS);
|
||||
$display("actual = %0.2f ns", data_setup);
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
// ----------------------------------------------------
|
||||
// tDH = 0 ns
|
||||
// ----------------------------------------------------
|
||||
|
||||
// No additional hold time is required.
|
||||
|
||||
// ----------------------------------------------------
|
||||
// Store data
|
||||
// ----------------------------------------------------
|
||||
|
||||
if (a !== active_addr) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM PROTOCOL ERROR");
|
||||
$display("ADDRESS CHANGED DURING WRITE");
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (a < DEPTH) begin
|
||||
|
||||
if (!lb_n)
|
||||
mem[a][7:0] <= dq[7:0];
|
||||
|
||||
if (!ub_n)
|
||||
mem[a][15:8] <= dq[15:8];
|
||||
end
|
||||
|
||||
write_active = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================
|
||||
// ZZ#
|
||||
// ============================================================
|
||||
|
||||
always @(negedge zz_n) begin
|
||||
|
||||
if (!ce_n) begin
|
||||
|
||||
$display("");
|
||||
$display("========================================");
|
||||
$display("PSRAM PROTOCOL ERROR");
|
||||
$display("ZZ# LOW while CE# LOW");
|
||||
$display("========================================");
|
||||
|
||||
$fatal;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user