Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
20cada45
Commit
20cada45
authored
Oct 27, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added single-clock frame trailer processing (adding metadata), simulating/debugging
parent
ca269a20
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
831 additions
and
60 deletions
+831
-60
bit_stuffer_27_32.v
compressor_jp/bit_stuffer_27_32.v
+38
-2
bit_stuffer_escape.v
compressor_jp/bit_stuffer_escape.v
+3
-3
bit_stuffer_metadata.v
compressor_jp/bit_stuffer_metadata.v
+160
-0
huffman_snglclk.v
compressor_jp/huffman_snglclk.v
+26
-16
huffman_stuffer_meta.v
compressor_jp/huffman_stuffer_meta.v
+151
-0
jp_channel.v
compressor_jp/jp_channel.v
+38
-0
mcontr_sequencer.v
memctrl/phy/mcontr_sequencer.v
+7
-1
x393_testbench02.sav
x393_testbench02.sav
+90
-17
x393_testbench03.sav
x393_testbench03.sav
+306
-14
x393_testbench03.tf
x393_testbench03.tf
+12
-7
No files found.
compressor_jp/bit_stuffer_27_32.v
View file @
20cada45
...
...
@@ -63,7 +63,7 @@ module bit_stuffer_27_32#(
else
ds_stage
<=
{
ds_stage
[
0
]
,
ds
};
if
(
rst
)
flush_stage
<=
0
;
else
flush_stage
<=
{
flush_stage
[
1
:
0
]
,
ds
};
else
flush_stage
<=
{
flush_stage
[
1
:
0
]
,
flush_in
};
if
(
rst
||
flush_in
)
early_length
<=
0
;
else
if
(
ds
)
early_length
<=
early_length
[
4
:
0
]
+
dlen
;
// early_length[5] is not used in calculations, it is just carry out
...
...
@@ -91,6 +91,7 @@ module bit_stuffer_27_32#(
2'h3
:
data2
<=
{
6'b0
,
data1
};
endcase
if
(
stage
[
0
])
case
(
dlen1
[
4
:
0
])
/*
5'h00: dmask2_rom <= 32'hffffffff;
5'h01: dmask2_rom <= 32'hfffffffe;
5'h02: dmask2_rom <= 32'hfffffffc;
...
...
@@ -123,6 +124,39 @@ module bit_stuffer_27_32#(
5'h1d: dmask2_rom <= 32'he0000000;
5'h1e: dmask2_rom <= 32'hc0000000;
5'h1f: dmask2_rom <= 32'h80000000;
*/
5'h00
:
dmask2_rom
<=
32'hffffffff
;
5'h01
:
dmask2_rom
<=
32'h7fffffff
;
5'h02
:
dmask2_rom
<=
32'h3fffffff
;
5'h03
:
dmask2_rom
<=
32'h1fffffff
;
5'h04
:
dmask2_rom
<=
32'h0fffffff
;
5'h05
:
dmask2_rom
<=
32'h07ffffff
;
5'h06
:
dmask2_rom
<=
32'h03ffffff
;
5'h07
:
dmask2_rom
<=
32'h01ffffff
;
5'h08
:
dmask2_rom
<=
32'h00ffffff
;
5'h09
:
dmask2_rom
<=
32'h007fffff
;
5'h0a
:
dmask2_rom
<=
32'h003fffff
;
5'h0b
:
dmask2_rom
<=
32'h001fffff
;
5'h0c
:
dmask2_rom
<=
32'h000fffff
;
5'h0d
:
dmask2_rom
<=
32'h0007ffff
;
5'h0e
:
dmask2_rom
<=
32'h0003ffff
;
5'h0f
:
dmask2_rom
<=
32'h0001ffff
;
5'h10
:
dmask2_rom
<=
32'h0000ffff
;
5'h11
:
dmask2_rom
<=
32'h00007fff
;
5'h12
:
dmask2_rom
<=
32'h00003fff
;
5'h13
:
dmask2_rom
<=
32'h00001fff
;
5'h14
:
dmask2_rom
<=
32'h00000fff
;
5'h15
:
dmask2_rom
<=
32'h000007ff
;
5'h16
:
dmask2_rom
<=
32'h000003ff
;
5'h17
:
dmask2_rom
<=
32'h000001ff
;
5'h18
:
dmask2_rom
<=
32'h000000ff
;
5'h19
:
dmask2_rom
<=
32'h0000007f
;
5'h1a
:
dmask2_rom
<=
32'h0000003f
;
5'h1b
:
dmask2_rom
<=
32'h0000001f
;
5'h1c
:
dmask2_rom
<=
32'h0000000f
;
5'h1d
:
dmask2_rom
<=
32'h00000007
;
5'h1e
:
dmask2_rom
<=
32'h00000003
;
5'h1f
:
dmask2_rom
<=
32'h00000001
;
endcase
// barrel shifter stage 3 (0/1), combined with output/hold register
if
(
ds_stage
[
1
])
begin
...
...
@@ -131,7 +165,9 @@ module bit_stuffer_27_32#(
data3
[
DATA3_LEN
-
1
-
32
:
0
]
<=
dlen2
[
0
]
?
data2
[
DATA2_LEN
-
31
-
1
:
0
]
:
{
data2
[
DATA2_LEN
-
32
-
1
:
0
]
,
1'b0
};
end
dv
<=
(
ds_stage
[
1
]
&&
dlen2
[
5
])
||
(
flush_stage
[
1
]
&&
!
(
|
data3
[
DATA3_LEN
-
1
-:
32
]))
;
// dv <= (ds_stage[1] && dlen2[5]) || (flush_stage[1] && !(|data3[DATA3_LEN-1 -: 32]));
// dv <= (ds_stage[1] && dlen1[5]) || (flush_stage[1] && !(|data3[DATA3_LEN-1 -: 32]));
dv
<=
(
ds_stage
[
0
]
&&
dlen1
[
5
])
||
(
flush_stage
[
1
]
&&
!
(
|
data3
[
DATA3_LEN
-
1
-:
32
]))
;
if
(
rst
||
ds_stage
[
1
])
bytes_out
<=
0
;
// if the dv was caused by 32 bits full - output 4 bytes
else
if
(
flush_stage
[
1
])
bytes_out
<=
pre_bits_out_w
[
4
:
3
]
;
...
...
compressor_jp/bit_stuffer_escape.v
View file @
20cada45
...
...
@@ -23,11 +23,11 @@
module
bit_stuffer_escape
(
input
xclk
,
// pixel clock, sync to incoming data
input
rst
,
// @xclk
// data from external FIFO (35x16 should be OK)
input
[
31
:
0
]
din
,
// input data, MSB aligned
input
[
1
:
0
]
bytes_in
,
// number of bytes, valid @ ds (0 means 4)
input
flush_in
,
// end of input data (ignore din/bytes_in)
input
in_stb
,
// input data/bytes_in/flush_in strobe
input
in_stb
,
// input data/bytes_in strobe
input
flush_in
,
// end of input data
output
reg
[
31
:
0
]
d_out
,
// output 32-bit data
output
reg
[
1
:
0
]
bytes_out
,
// valid @dv(only), 0 means 4 bytes
output
reg
dv
,
// output data valid
...
...
compressor_jp/bit_stuffer_metadata.v
0 → 100644
View file @
20cada45
/*******************************************************************************
* Module: bit_stuffer_metadata
* Date:2015-10-25
* Author: andrey
* Description:
*
* Copyright (c) 2015 Elphel, Inc .
* bit_stuffer_metadata.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* bit_stuffer_metadata.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
bit_stuffer_metadata
(
input
mclk
,
input
mrst
,
// @posedge mclk, sync reset
input
xclk
,
input
xrst
,
// @posedge xclk, sync reset
input
last_block
,
// use it to copy timestamp from fifo
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current frame, but before the next one
// and before the data is needed for output
input
ts_pre_stb
,
// @mclk - 1 cycle before receiving 8 bytes of timestamp data
input
[
7
:
0
]
ts_data
,
// timestamp data (s0,s1,s2,s3,us0,us1,us2,us3==0)
input
color_first
,
// @fradv_clk only used for timestamp
input
[
31
:
0
]
din
,
// input data, MSB aligned
input
[
1
:
0
]
bytes_in
,
// number of bytes, valid @ ds (0 means 4)
input
in_stb
,
// input data/bytes_in strobe
input
flush
,
// end of input data
input
abort
,
// @ any, extracts 0->1 and flushes
// outputs @ negedge clk
output
reg
[
31
:
0
]
data_out
,
// [31:0] output data
output
reg
data_out_valid
,
// output data valid
output
reg
done
,
// reset by !en, goes high after some delay after flushing
output
reg
running
// from registering timestamp until done
`ifdef
DEBUG_RING
,
output
reg
[
3
:
0
]
dbg_etrax_dma
,
output
dbg_ts_rstb
,
output
[
7
:
0
]
dbg_ts_dout
`endif
)
;
reg
[
7
:
0
]
time_ram0
[
0
:
3
]
;
// 0 - seconds, 1 - microseconds MSB in the output 32-bit word, byt LSB of the sec/usec
reg
[
7
:
0
]
time_ram1
[
0
:
3
]
;
reg
[
7
:
0
]
time_ram2
[
0
:
3
]
;
reg
[
7
:
0
]
time_ram3
[
0
:
3
]
;
reg
[
3
:
0
]
ts_in
=
8
;
reg
last_block_d
;
// last_block delayed by one clock
reg
color_first_r
;
reg
[
2
:
0
]
abort_r
;
reg
force_flush
;
// reg color_first_r; // registered with the same clock as color_first to extract leading edge
// stb_time[2] - single-cycle pulse after color_first goes low
// reg [19:0] imgsz32; // current image size in multiples of 32-bytes
reg
[
21
:
0
]
imgsz4
;
// current image size in multiples of 4-bytes
reg
last_stb_4
;
// last stb_in was 4 bytes
reg
trailer
;
reg
meta_out
;
reg
[
1
:
0
]
meta_word
;
reg
zeros_out
;
// output of 32 bytes (8 words) of zeros
wire
trailer_done
=
(
imgsz4
[
2
:
0
]
==
7
)
&&
zeros_out
;
wire
meta_last
=
(
imgsz4
[
2
:
0
]
==
7
)
&&
meta_out
;
// re-clock enable to this clock
wire
ts_rstb
=
last_block
&&
!
last_block_d
;
// enough time to have timestamp data; // one cycle before getting timestamp data from FIFO
wire
[
7
:
0
]
ts_dout
;
// timestamp data, byte at a time
wire
write_size
=
(
in_stb
&&
(
bytes_in
!=
0
))
||
(
flush
&&
last_stb_4
)
;
wire
stb_start
=
!
color_first
&&
color_first_r
;
wire
stb
=
in_stb
&
!
trailer
&&
!
force_flush
;
always
@
(
posedge
xclk
)
begin
if
(
xrst
||
trailer_done
)
imgsz4
<=
0
;
else
if
(
stb
||
trailer
)
imgsz4
<=
imgsz4
+
1
;
if
(
stb
)
last_stb_4
<=
(
bytes_in
==
0
)
;
last_block_d
<=
last_block
;
color_first_r
<=
color_first
;
if
(
xrst
)
ts_in
<=
8
;
else
if
(
ts_rstb
)
ts_in
<=
0
;
else
if
(
!
ts_in
[
3
])
ts_in
<=
ts_in
+
1
;
if
((
ts_in
[
3
]
&&
(
ts_in
[
1
:
0
]
==
0
))
||
write_size
)
time_ram0
[
ts_in
[
3
:
2
]]
<=
ts_in
[
3
]
?
(
{
imgsz4
[
5
:
0
]
,
flush
?
2'b0
:
bytes_in
}
)
:
ts_dout
;
//ts_in[3:2] == 2'b10 when write_size
if
((
ts_in
[
3
]
&&
(
ts_in
[
1
:
0
]
==
1
))
||
write_size
)
time_ram1
[
ts_in
[
3
:
2
]]
<=
ts_in
[
3
]
?
(
imgsz4
[
13
:
6
])
:
ts_dout
;
if
((
ts_in
[
3
]
&&
(
ts_in
[
1
:
0
]
==
2
))
||
write_size
)
time_ram2
[
ts_in
[
3
:
2
]]
<=
ts_in
[
3
]
?
(
imgsz4
[
21
:
14
])
:
ts_dout
;
if
((
ts_in
[
3
]
&&
(
ts_in
[
1
:
0
]
==
3
))
||
write_size
)
time_ram3
[
ts_in
[
3
:
2
]]
<=
ts_in
[
3
]
?
(
8'hff
)
:
ts_dout
;
if
(
xrst
)
trailer
<=
0
;
else
if
(
flush
||
force_flush
)
trailer
<=
1
;
else
if
(
trailer_done
)
trailer
<=
0
;
if
(
xrst
)
meta_out
<=
0
;
else
if
((
flush
||
trailer
)
&&
(
imgsz4
[
2
:
0
]
==
4
))
meta_out
<=
1
;
else
if
(
meta_last
)
meta_out
<=
0
;
if
(
!
meta_out
)
meta_word
<=
0
;
else
meta_word
<=
meta_word
+
1
;
if
(
xrst
)
zeros_out
<=
0
;
else
if
(
meta_last
)
zeros_out
<=
1
;
else
if
(
trailer_done
)
zeros_out
<=
0
;
data_out
<=
(
{
32
{
stb
}}
&
din
)
|
(
{
32
{
meta_out
}}
&
{
time_ram0
[
meta_word
]
,
time_ram1
[
meta_word
]
,
time_ram2
[
meta_word
]
,
time_ram3
[
meta_word
]
}
)
;
data_out_valid
<=
stb
||
trailer
;
if
(
xrst
)
running
<=
0
;
else
if
(
stb_start
)
running
<=
1
;
else
if
(
trailer
)
running
<=
0
;
done
<=
trailer_done
;
// re-clock abort, extract leading edge
abort_r
<=
{
abort_r
[
0
]
&
~
abort_r
[
1
]
,
abort_r
[
0
]
,
abort
&
~
trailer
};
if
(
xrst
||
trailer
)
force_flush
<=
0
;
else
if
(
abort_r
)
force_flush
<=
1
;
end
// just for testing
`ifdef
DEBUG_RING
assign
dbg_
=
ts_rstb
;
assign
dbg_ts_dout
=
ts_dout
;
always
@
(
posedge
xclk
)
begin
dbg_etrax_dma
<=
imgsz4
[
3
:
0
]
;
end
`endif
//color_first && color_first_r
timestamp_fifo
timestamp_fifo_i
(
.
sclk
(
mclk
)
,
// input
.
srst
(
mrst
)
,
// input
.
pre_stb
(
ts_pre_stb
)
,
// input
.
din
(
ts_data
)
,
// input[7:0]
.
aclk
(
xclk
)
,
//fradv_clk), // input
.
arst
(
xrst
)
,
//fradv_clk), // input
.
advance
(
stb_start
)
,
// triggers at the 0->1
.
rclk
(
xclk
)
,
// input
.
rrst
(
xrst
)
,
//fradv_clk), // input
.
rstb
(
ts_rstb
)
,
// input
.
dout
(
ts_dout
)
// output[7:0] reg
)
;
endmodule
compressor_jp/huffman_snglclk.v
View file @
20cada45
...
...
@@ -25,7 +25,6 @@
**
*/
`include
"system_defines.vh"
// 01/22/2004 - extended flush until ready (modified stuffer.v too)
module
huffman_snglclk
(
input
xclk
,
// pixel clock, sync to incoming data
input
rst
,
// @xclk
...
...
@@ -46,16 +45,17 @@ module huffman_snglclk (
output
flush
,
// last block done - flush the rest bits
output
last_block
,
output
reg
test_lbw
,
output
gotLastBlock
,
// last block done - flush the rest bits
input
clk_flush
,
// other clock to generate synchronized 1-cycle flush_clk output
output
flush_clk
,
// 1-cycle flush output @ clk_flush
output
gotLastBlock
,
// last block done - flush the rest bits
//
input clk_flush, // other clock to generate synchronized 1-cycle flush_clk output
//
output flush_clk, // 1-cycle flush output @ clk_flush
output
fifo_or_full
// FIFO output register full - just for debuging
)
;
// A small input FIFO, only needed for RLL >16 that require several clock cycles to output
reg
fifo_re
;
reg
fifo_re
_r
;
wire
fifo_rdy
;
wire
fifo_re
=
fifo_re_r
&&
fifo_rdy
;
wire
[
15
:
0
]
fifo_out
;
fifo_same_clock
#(
.
DATA_WIDTH
(
16
)
,
...
...
@@ -79,9 +79,9 @@ module huffman_snglclk (
assign
gotLastBlock
=
fifo_out
[
15
]
&&
fifo_out
[
14
]
&&
fifo_out
[
12
]
&&
fifo_re
;
wire
gotLastWord
=
!
fifo_out
[
14
]
&&
fifo_out
[
12
]
&&
fifo_re
;
// (AC or RLL) and last bit set
wire
gotColor
=
fifo_out
[
13
]
;
reg
[
5
:
0
]
rll
;
// 2 MSBs - counter to send "f0" codes
reg
[
3
:
0
]
rll1
;
// valid at cycle "1"
reg
[
3
:
0
]
rll2
;
// valid at cycle "1"
reg
[
5
:
0
]
rll
;
// 2 MSBs - counter to send "f0" codes
// reg [3:0] rll1;
// valid at cycle "1"
wire
[
3
:
0
]
rll_late
;
// match AC's length timing
reg
[
2
:
0
]
gotAC_r
;
reg
[
2
:
0
]
gotDC_r
;
reg
[
2
:
0
]
gotEOB_r
;
...
...
@@ -109,8 +109,8 @@ module huffman_snglclk (
assign
fifo_or_full
=
fifo_rdy
;
always
@
(
posedge
xclk
)
begin
if
(
rst
)
fifo_re
<=
0
;
else
fifo_re
<=
fifo_rdy
&&
!
(
fifo_re
&&
gotRLL
)
&&
!
(
|
rll
[
5
:
4
])
;
if
(
rst
)
fifo_re
_r
<=
0
;
else
fifo_re
_r
<=
fifo_rdy
&&
!
(
fifo_re
&&
gotRLL
)
&&
!
(
|
rll
[
5
:
4
])
;
if
(
rst
)
gotAC_r
<=
0
;
else
gotAC_r
<=
{
gotAC_r
[
1
:
0
]
,
gotAC
&&
fifo_re
};
...
...
@@ -132,8 +132,8 @@ module huffman_snglclk (
if
(
rst
)
rll
[
3
:
0
]
<=
0
;
else
if
(
fifo_re
)
rll
[
3
:
0
]
<=
gotRLL
?
fifo_out
[
3
:
0
]
:
4'b0
;
rll1
<=
rll
[
3
:
0
]
;
rll2
<=
rll1
;
//
rll1 <= rll[3:0];
// rll_late
<= rll1;
if
(
rst
)
gotF0_r
[
2
:
1
]
<=
0
;
else
gotF0_r
[
2
:
1
]
<=
{
gotF0_r
[
1
]
,
(
|
rll
[
5
:
4
])
};
...
...
@@ -145,7 +145,7 @@ module huffman_snglclk (
htable_addr
[
7
:
0
]
<=
(
{
8
{
gotEOB_r
[
2
]
}}
&
8'h0
)
|
// generate 00 code (end of block)
(
{
8
{
gotF0_r
[
2
]
}}
&
8'hf0
)
|
// generate f0 code (16 zeros)
(
{
8
{
gotDC_r
[
2
]
}}
&
{
val_length
[
3
:
0
]
,
4'hf
}
)
|
(
{
8
{
gotAC_r
[
2
]
}}
&
{
rll
2
[
3
:
0
]
,
val_length
[
3
:
0
]
}
)
;
(
{
8
{
gotAC_r
[
2
]
}}
&
{
rll
_late
[
3
:
0
]
,
val_length
[
3
:
0
]
}
)
;
if
(
rst
)
htable_re
<=
0
;
else
htable_re
<=
{
htable_re
[
1
:
0
]
,
gotEOB_r
[
2
]
|
gotF0_r
[
2
]
|
gotDC_r
[
2
]
|
gotAC_r
[
2
]
};
...
...
@@ -195,7 +195,7 @@ module huffman_snglclk (
)
;
ram18_var_w_var_r
#(
.
REGISTERS
(
0
)
,
.
REGISTERS
(
1
)
,
.
LOG2WIDTH_WR
(
4
)
,
.
LOG2WIDTH_RD
(
5
)
,
.
DUMMY
(
0
)
...
...
@@ -235,6 +235,16 @@ module huffman_snglclk (
.
dout
(
val_length_late
)
// output[0:0]
)
;
dly_16
#(
.
WIDTH
(
4
)
)
dly_16_rll_late_i
(
.
clk
(
xclk
)
,
// input
.
rst
(
rst
)
,
// input
.
dly
(
4'h2
)
,
// input[3:0]
.
din
(
rll
[
3
:
0
])
,
// input[0:0]
.
dout
(
rll_late
)
// output[0:0]
)
;
huffman_merge_code_literal
huffman_merge_code_literal_i
(
.
clk
(
xclk
)
,
// input
.
in_valid
(
htable_re
[
2
])
,
// input
...
...
@@ -246,7 +256,7 @@ module huffman_snglclk (
.
out_bits
(
do27
)
,
// output[26:0] reg
.
out_len
(
dl
)
// output[4:0] reg
)
;
/*
pulse_cross_clock flush_clk_i (
.rst (rst),
.src_clk (xclk),
...
...
@@ -255,6 +265,6 @@ module huffman_snglclk (
.out_pulse (flush_clk),
.busy ());
*/
endmodule
compressor_jp/huffman_stuffer_meta.v
0 → 100644
View file @
20cada45
/*******************************************************************************
* Module: huffman_stuffer_meta
* Date:2015-10-26
* Author: andrey
* Description: Huffman encoder, bit stuffer, inser meta-data
* "New" part of the JPEG/JP4 comressor that used double frequency clock
*
* Copyright (c) 2015 Elphel, Inc .
* huffman_stuffer_meta.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* huffman_stuffer_meta.v is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale
1
ns
/
1
ps
module
huffman_stuffer_meta
(
input
mclk
,
// system clock to write tables
input
mrst
,
input
xclk
,
// pixel clock, sync to incoming data
input
en_huffman
,
// @xclk
input
en_stuffer
,
// @xclk
input
abort_stuffer
,
// @ any
// Interface to program Huffman tables
input
tser_we
,
// enable write to a table
input
tser_a_not_d
,
// address/not data distributed to submodules
input
[
7
:
0
]
tser_d
,
// byte-wide serialized tables address/data to submodules
// Input data
input
[
15
:
0
]
di
,
// [15:0] specially RLL prepared 16-bit data (to FIFO) (sync to xclk)
input
ds
,
// di valid strobe (sync to xclk)
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current frame, but before the next one
// and before the data is needed for output
input
ts_pre_stb
,
// @mclk - 1 cycle before receiving 8 bytes of timestamp data
input
[
7
:
0
]
ts_data
,
// timestamp data (s0,s1,s2,s3,us0,us1,us2,us3==0)
input
color_first
,
// @fradv_clk only used for timestamp
// outputs @ negedge clk
output
[
31
:
0
]
data_out
,
// [31:0] output data
output
data_out_valid
,
// output data valid
output
done
,
// reset by !en, goes high after some delay after flushing
output
running
// from registering timestamp until done
`ifdef
DEBUG_RING
,
output
test_lbw
,
output
gotLastBlock
,
// last block done - flush the rest bits
output
[
3
:
0
]
dbg_etrax_dma
,
output
dbg_ts_rstb
,
output
[
7
:
0
]
dbg_ts_dout
`endif
)
;
wire
[
26
:
0
]
huffman_do27
;
wire
[
4
:
0
]
huffman_dl
;
wire
huffman_dv
;
wire
huffman_flush
;
wire
huffman_last_block
;
wire
[
31
:
0
]
stuffer_do32
;
wire
[
1
:
0
]
stuffer_bytes
;
wire
stuffer_dv
;
wire
stuffer_flush_out
;
wire
[
31
:
0
]
escape_do32
;
wire
[
1
:
0
]
escape_bytes
;
wire
escape_dv
;
wire
escape_flush_out
;
huffman_snglclk
huffman_snglclk_i
(
.
xclk
(
xclk
)
,
// input
.
rst
(
~
en_huffman
)
,
// input
.
mclk
(
mclk
)
,
// input
.
tser_we
(
tser_we
)
,
// input
.
tser_a_not_d
(
tser_a_not_d
)
,
// input
.
tser_d
(
tser_d
)
,
// input[7:0]
.
di
(
di
)
,
// input[15:0]
.
ds
(
ds
)
,
// input
.
do27
(
huffman_do27
)
,
// output[26:0]
.
dl
(
huffman_dl
)
,
// output[4:0]
.
dv
(
huffman_dv
)
,
// output
.
flush
(
huffman_flush
)
,
// output
.
last_block
(
huffman_last_block
)
,
// output
`ifdef
DEBUG_RING
.
test_lbw
(
test_lbw
)
,
.
gotLastBlock
(
gotLastBlock
)
,
// last block done - flush the rest bits
`else
.
test_lbw
()
,
.
gotLastBlock
()
,
// last block done - flush the rest bits
`endif
// .clk_flush(), // input
// .flush_clk(), // output
.
fifo_or_full
()
// output
)
;
bit_stuffer_27_32
#(
.
DIN_LEN
(
27
)
)
bit_stuffer_27_32_i
(
.
xclk
(
xclk
)
,
// input
.
rst
(
~
en_huffman
)
,
// input
.
din
(
huffman_do27
)
,
// input[26:0]
.
dlen
(
huffman_dl
)
,
// input[4:0]
.
ds
(
huffman_dv
)
,
// input
.
flush_in
(
huffman_flush
)
,
// input
.
d_out
(
stuffer_do32
)
,
// output[31:0]
.
bytes_out
(
stuffer_bytes
)
,
// output[1:0] reg
.
dv
(
stuffer_dv
)
,
// output reg
.
flush_out
(
stuffer_flush_out
)
// output reg
)
;
bit_stuffer_escape
bit_stuffer_escape_i
(
.
xclk
(
xclk
)
,
// input
.
rst
(
~
en_huffman
)
,
// input
.
din
(
stuffer_do32
)
,
// input[31:0]
.
bytes_in
(
stuffer_bytes
)
,
// input[1:0]
.
in_stb
(
stuffer_dv
)
,
// input
.
flush_in
(
stuffer_flush_out
)
,
// input
.
d_out
(
escape_do32
)
,
// output[31:0] reg
.
bytes_out
(
escape_bytes
)
,
// output[1:0] reg
.
dv
(
escape_dv
)
,
// output reg
.
flush_out
(
escape_flush_out
)
// output reg
)
;
bit_stuffer_metadata
bit_stuffer_metadata_i
(
.
mclk
(
mclk
)
,
// input
.
mrst
(
mrst
)
,
// input
.
xclk
(
xclk
)
,
// input
.
xrst
(
~
en_stuffer
)
,
// input
.
last_block
(
huffman_last_block
)
,
// input
.
ts_pre_stb
(
ts_pre_stb
)
,
// input
.
ts_data
(
ts_data
)
,
// input[7:0]
.
color_first
(
color_first
)
,
// input
.
din
(
escape_do32
)
,
// input[31:0]
.
bytes_in
(
escape_bytes
)
,
// input[1:0]
.
in_stb
(
escape_dv
)
,
// input
.
flush
(
escape_flush_out
)
,
// input
.
abort
(
abort_stuffer
)
,
// input
.
data_out
(
data_out
)
,
// output[31:0] reg
.
data_out_valid
(
data_out_valid
)
,
// output reg
.
done
(
done
)
,
// output reg
.
running
(
running
)
// output reg
)
;
endmodule
compressor_jp/jp_channel.v
View file @
20cada45
...
...
@@ -1126,6 +1126,44 @@ module jp_channel#(
,.
test_cntr1
(
test_cntr1
[
7
:
0
])
`endif
)
;
// Debugging - attaching new compressor module in parallel to the existing one
wire
[
31
:
0
]
alt_stuffer_do
;
// SuppressThisWarning VEditor Unused
wire
alt_stuffer_dv
;
// SuppressThisWarning VEditor Unused
wire
alt_stuffer_done
;
// SuppressThisWarning VEditor Unused
wire
alt_stuffer_running
;
// SuppressThisWarning VEditor Unused
huffman_stuffer_meta
huffman_stuffer_meta_i
(
.
mclk
(
mclk
)
,
// input
.
mrst
(
mrst
)
,
// input
.
xclk
(
xclk
)
,
// input
.
en_huffman
(
frame_en
)
,
// input
.
en_stuffer
(
stuffer_en
)
,
// input
.
abort_stuffer
(
force_flush_long
)
,
// input
.
tser_we
(
tser_he
)
,
// input
.
tser_a_not_d
(
tser_a_not_d
)
,
// input
.
tser_d
(
tser_d
)
,
// input[7:0]
.
di
(
enc_do
[
15
:
0
])
,
// input[15:0]
.
ds
(
enc_dv
)
,
// input
.
ts_pre_stb
(
ts_pre_stb
)
,
// input
.
ts_data
(
ts_data
)
,
// input[7:0]
.
color_first
(
color_first
)
,
// input valid @xclk - only for sec/usec
.
data_out
(
alt_stuffer_do
)
,
// output[31:0]
.
data_out_valid
(
alt_stuffer_dv
)
,
// output
.
done
(
alt_stuffer_done
)
,
// output
.
running
(
alt_stuffer_running
)
// output
`ifdef
DEBUG_RING
,.
test_lbw
()
,
// output
.
gotLastBlock
()
,
// output // last block done - flush the rest bits
.
dbg_etrax_dma
()
,
// output[3:0]
.
dbg_ts_rstb
()
,
// output
.
dbg_ts_dout
()
//output[7:0]
`endif
)
;
/*
,output dbg_ts_rstb
,output [7:0] dbg_ts_dout
...
...
memctrl/phy/mcontr_sequencer.v
View file @
20cada45
...
...
@@ -505,6 +505,7 @@ module mcontr_sequencer #(
.
rclk
(
mclk
)
,
// input
.
raddr
(
cmd_addr
)
,
// input[9:0]
.
ren
(
ren0
)
,
// input TODO: verify cmd_busy[0] is correct (was cmd_busy ). TODO: make cleaner ren/regen
// .ren (ren0 && !sequence_done), // input TODO: verify cmd_busy[0] is correct (was cmd_busy ). TODO: make cleaner ren/regen
.
regen
(
ren0
)
,
// input
.
data_out
(
phy_cmd0_word
)
,
// output[31:0]
.
wclk
(
cmd0_clk
)
,
// input
...
...
@@ -513,14 +514,19 @@ module mcontr_sequencer #(
.
web
(
4'hf
)
,
// input[3:0]
.
data_in
(
cmd0_data
)
// input[31:0]
)
;
// NOTE: Simulation sometimes may show:
// Memory Collision Error on RAMB36E1 : x393_testbench03.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd1_buf_i.RAMB36E1_i.genblk1.INT_RAMB_TDP.chk_for_col_msg
// It is OK, as the sequencer reads 2 extra (unused) locations before it stops at the end of block (stop depends on the read memory that has latency)
// Command sequence memory 0 ("manual"):
// Command sequence memory 1
ram_1kx32_1kx32
#(
.
REGISTERS
(
1
)
// (0) // register output
)
cmd1_buf_i
(
.
rclk
(
mclk
)
,
// input
.
raddr
(
cmd_addr
)
,
// input[9:0]
.
ren
(
ren1
)
,
// input ??? TODO: make cleaner ren/regen
// .ren ( ren1 && !sequence_done), // input ??? TODO: make cleaner ren/regen
.
regen
(
ren1
)
,
// input ???
.
data_out
(
phy_cmd1_word
)
,
// output[31:0]
.
wclk
(
cmd1_clk
)
,
// input
...
...
x393_testbench02.sav
View file @
20cada45
[*]
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*]
Tue Oct 13 02:08:59
2015
[*]
Mon Oct 26 23:54:57
2015
[*]
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench02-20151012
161611192
.fst"
[dumpfile_mtime] "
Mon Oct 12 22:50:38
2015"
[dumpfile_size] 1
72697643
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench02-20151012
200650115
.fst"
[dumpfile_mtime] "
Tue Oct 13 02:42:50
2015"
[dumpfile_size] 1
66114960
[savefile] "/home/andrey/git/x393/x393_testbench02.sav"
[timestart] 0
[timestart]
13657950
0
[size] 1823 1180
[pos] 1922 0
*-
25.149160 71803197
102872500 116192500 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
*-
15.149160 136632388
102872500 116192500 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] x393_testbench02.
[treeopen] x393_testbench02.compressor_control.
[treeopen] x393_testbench02.par12_hispi_psp4l_i.
[treeopen] x393_testbench02.par12_hispi_psp4l_i.cmprs_channel_block[0].
[treeopen] x393_testbench02.simul_axi_hp1_wr_i.
[treeopen] x393_testbench02.simul_axi_hp1_wr_i.waddr_i.
[treeopen] x393_testbench02.simul_clk_mult_i.
[treeopen] x393_testbench02.simul_saxi_gp0_wr_i.waddr_i.
[treeopen] x393_testbench02.simul_sensor12bits_i.
[treeopen] x393_testbench02.x393_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.chn_rd_buf_i.
...
...
@@ -32,9 +28,7 @@
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.cmprs_out_fifo_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.cmprs_pixel_buf_iface_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.csconvert_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.i_huffman.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.i_huffman.i_huff_fifo.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.quantizer393_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.table_ad_transmit_i.
[treeopen] x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.table_ad_transmit_i.i_end_burst.
...
...
@@ -56,6 +50,7 @@
[treeopen] x393_testbench02.x393_i.mcntrl393_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.cmd_encod_linear_rw_i.cmd_encod_linear_wr_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.mcntrl_linear_rw_chn1_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.phy_cmd_i.phy_top_i.
[treeopen] x393_testbench02.x393_i.mcntrl393_i.sens_comp_block[0].mcntrl_linear_wr_sensor_i.
...
...
@@ -106,8 +101,25 @@
[sst_vpaned_height] 611
@820
x393_testbench02.TEST_TITLE[639:0]
@800200
-memcntrl_debug
@29
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.sequence_done
@22
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd_addr[9:0]
@28
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.pause
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.ren1
@22
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd1_addr[9:0]
@28
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd1_we
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd_sel
x393_testbench02.x393_i.mcntrl393_i.memctrl16_i.mcontr_sequencer_i.cmd_busy[2:0]
@200
-
@1000200
-memcntrl_debug
@c00200
-debug_ring
@200
...
...
@@ -1240,8 +1252,9 @@ x393_testbench02.x393_i.membridge_i.status_generate_i.wd[7:0]
@1401200
-membridge_status
-membridge
@
c
00200
@
8
00200
-compressor0
@c00200
-func_compressor_control
@22
x393_testbench02.func_compressor_control.bayer[31:0]
...
...
@@ -1581,9 +1594,66 @@ x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.enco
-
@1000200
-encoder_DCAC
@
8
00200
@
c
00200
-stuffer
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.stb_start
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_rstb
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_dout[7:0]
@800022
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
@28
(0)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(1)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(2)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(3)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(4)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(5)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
(6)x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_cycles[6:0]
@1001200
-group_end
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.last_block
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.dl[3:0]
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.d[15:0]
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.stb
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.stb_start
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.abort
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.q[15:0]
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.qv
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flush
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flush_now
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flushing
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.etrax_dma[3:0]
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.inc_imgsz32
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.imgsz32[19:0]
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.start_time_out
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.start_sizeout
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.size_count[23:0]
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.time_out
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.time_size_out
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.size_out[2:0]
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.size_out_over
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flush_end
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.trailer
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flush_end_delayed
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.done
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.running
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.flushing
@200
-
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_pre_stb
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer393_i.ts_data[7:0]
...
...
@@ -1690,7 +1760,7 @@ x393_testbench02.x393_i.timing393_i.ts_stb_chn0
x393_testbench02.x393_i.timing393_i.ts_stb[3:0]
@200
-
@1
000
200
@1
401
200
-stuffer
@22
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.stuffer_do[15:0]
...
...
@@ -1923,8 +1993,10 @@ x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.yc_n
@28
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.yc_pre_first_out
x393_testbench02.x393_i.compressor393_i.cmprs_channel_block[0].jp_channel_i.ywe
@1
401
200
@1
000
200
-compressor0
@200
-
@c00200
-sim_cmprs_output
@22
...
...
@@ -3851,7 +3923,7 @@ x393_testbench02.x393_i.sensors393_i.sensor_channel_block[0].sensor_channel_i.se
x393_testbench02.x393_i.sensors393_i.sensor_channel_block[0].sensor_channel_i.hact_to_fifo
@200
-
@
8
00200
@
c
00200
-sens_i2c_io
@22
x393_testbench02.x393_i.sensors393_i.sensor_channel_block[0].sensor_channel_i.sensor_i2c_io_i.cmd_ad[7:0]
...
...
@@ -4474,6 +4546,7 @@ x393_testbench02.x393_i.sensors393_i.sensor_channel_block[0].sensor_channel_i.se
x393_testbench02.x393_i.sensors393_i.sensor_channel_block[0].sensor_channel_i.sensor_i2c_io_i.sensor_i2c_i.wpage_wr[3:0]
@1000200
-sens_i2c
@1401200
-sens_i2c_io
@c00200
-sensor_fifo
...
...
x393_testbench03.sav
View file @
20cada45
This diff is collapsed.
Click to expand it.
x393_testbench03.tf
View file @
20cada45
...
...
@@ -21,6 +21,7 @@
`
timescale
1
ns
/
1
ps
`
include
"system_defines.vh"
`
define
SAME_SENSOR_DATA
1
`
define
COMPRESS_SINGLE
//`define use200Mhz 1
//`define DEBUG_FIFO 1
`
undef
WAIT_MRS
...
...
@@ -1230,17 +1231,20 @@ assign #10 gpio_pins[9] = gpio_pins[8];
`
endif
`
ifdef
READBACK_DELAYS
TEST_TITLE
=
"
READBACK
"
;
`
ifdef
COMPRESS_SINGLE
TEST_TITLE
=
"
COMPRESS_FRAME
"
;
$display
(
"===================== TEST_%s ========================="
,
TEST_TITLE
);
axi_get_delays
;
`
endif
/*
compressor_run
(
0
,
2
);
// run single
compressor_run
(
1
,
2
);
// run single
compressor_run
(
2
,
2
);
// run single
compressor_run
(
3
,
2
);
// run single
*/
`
endif
`
ifdef
READBACK_DELAYS
TEST_TITLE
=
"READBACK"
;
$display
(
"===================== TEST_%s ========================="
,
TEST_TITLE
);
axi_get_delays
;
`
endif
`
ifdef
TEST_MEMBRIDGE
TEST_TITLE
=
"MEMBRIDGE_READ # 1"
;
...
...
@@ -2699,8 +2703,9 @@ task setup_sensor_channel;
1
);
// disable "need" (yield to sensor channels)
// compressor_run (num_sensor, 3); // run repetitive mode
`
ifndef
COMPRESS_SINGLE
compressor_run
(
num_sensor
,
3
);
// run repetitive mode
`
endif
TEST_TITLE
=
"DELAYS_SETUP"
;
$display
(
"===================== TEST_%s ========================="
,
TEST_TITLE
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment