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
0fda102e
Commit
0fda102e
authored
May 05, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed ddr3 -> system memory transfer
parent
59a577c9
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
268 additions
and
75 deletions
+268
-75
.project
.project
+15
-15
membridge.v
axi/membridge.v
+107
-15
x393_localparams.vh
includes/x393_localparams.vh
+6
-2
x393_axi_control_status.py
py393/x393_axi_control_status.py
+4
-4
system_defines.vh
system_defines.vh
+1
-0
x393_testbench01.sav
x393_testbench01.sav
+116
-34
x393_testbench01.tf
x393_testbench01.tf
+17
-5
x393_timing.xdc
x393_timing.xdc
+2
-0
No files found.
.project
View file @
0fda102e
...
...
@@ -62,77 +62,77 @@
<link>
<name>
vivado_logs/VivadoBitstream.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoBitstream-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoBitstream-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoOpt.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOpt-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOpt-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoOptPhys.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOptPhys-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOptPhys-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoOptPower.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOptPower-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoOptPower-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoPlace.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoPlace-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoPlace-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoRoute.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoRoute-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoRoute-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoSynthesis.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoSynthesis-2015050
3212133457
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoSynthesis-2015050
4180215142
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoTimimgSummaryReportImplemented.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoTimimgSummaryReportSynthesis.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-2015050
3212133457
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-2015050
4180215142
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoTimingReportImplemented.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-2015050
3212342992
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-2015050
4180408074
.log
</location>
</link>
<link>
<name>
vivado_logs/VivadoTimingReportSynthesis.log
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-2015050
3212133457
.log
</location>
<location>
/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-2015050
4180215142
.log
</location>
</link>
<link>
<name>
vivado_state/x393-opt-phys.dcp
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_state/x393-opt-phys-2015050
3212342992
.dcp
</location>
<location>
/home/andrey/git/x393/vivado_state/x393-opt-phys-2015050
4180408074
.dcp
</location>
</link>
<link>
<name>
vivado_state/x393-place.dcp
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_state/x393-place-2015050
3212342992
.dcp
</location>
<location>
/home/andrey/git/x393/vivado_state/x393-place-2015050
4180408074
.dcp
</location>
</link>
<link>
<name>
vivado_state/x393-route.dcp
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_state/x393-route-2015050
3212342992
.dcp
</location>
<location>
/home/andrey/git/x393/vivado_state/x393-route-2015050
4180408074
.dcp
</location>
</link>
<link>
<name>
vivado_state/x393-synth.dcp
</name>
<type>
1
</type>
<location>
/home/andrey/git/x393/vivado_state/x393-synth-2015050
3212133457
.dcp
</location>
<location>
/home/andrey/git/x393/vivado_state/x393-synth-2015050
4180215142
.dcp
</location>
</link>
</linkedResources>
</projectDescription>
axi/membridge.v
View file @
0fda102e
This diff is collapsed.
Click to expand it.
includes/x393_localparams.vh
View file @
0fda102e
...
...
@@ -119,8 +119,12 @@
localparam FRAME_START_ADDRESS= 'h1000; // RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0)
localparam FRAME_FULL_WIDTH= 'h0c0; // Padded line length (8-row increment), in 8-bursts (16 bytes)
localparam AFI_LO_ADDR64= 'h4000; // start of the system memory range in 64-bit words
localparam AFI_SIZE64= 'h4000; // size of system memory range in 64-bit words
// localparam AFI_LO_ADDR64= 'h4000; // start of the system memory range in 64-bit words
// localparam AFI_SIZE64= 'h4000; // size of system memory range in 64-bit words
// Same as in the actual hardware
localparam AFI_LO_ADDR64= 'h4f20000; // start of the system memory range in 64-bit words
localparam AFI_SIZE64= 'h0c80000; // size of system memory range in 64-bit words
// localparam SCANLINE_WINDOW_WH= `h079000a2; // 2592*1936: low word - 13-bit window width (0->'h4000), high word - 16-bit frame height (0->'h10000)
...
...
py393/x393_axi_control_status.py
View file @
0fda102e
...
...
@@ -355,7 +355,7 @@ class X393AxiControlStatus(object):
"""
global
mcntrl_en
en
=
(
0
,
1
)[
en
]
if
self
.
verbose
>
-
10
:
#
0:
if
self
.
verbose
>
0
:
print
(
"ENABLE MEMCTRL
%
s"
%
str
(
en
))
self
.
write_contol_register
(
vrlg
.
MCONTR_TOP_0BIT_ADDR
+
vrlg
.
MCONTR_TOP_0BIT_MCONTR_EN
+
en
,
0
);
mcntrl_en
=
en
...
...
@@ -368,7 +368,7 @@ class X393AxiControlStatus(object):
global
enabled_channels
enabled_channels
=
chnen
# currently enabled memory channels
self
.
write_contol_register
(
vrlg
.
MCONTR_TOP_16BIT_ADDR
+
vrlg
.
MCONTR_TOP_16BIT_CHN_EN
,
enabled_channels
&
0xffff
)
# {16'b0,chnen});
if
self
.
verbose
>
-
10
:
#
0:
if
self
.
verbose
>
0
:
print
(
"ENABLED MEMCTRL CHANNELS 0x
%
x (word), chnen=0x
%
x"
%
(
enabled_channels
,
chnen
))
def
enable_memcntrl_en_dis
(
self
,
...
...
@@ -385,7 +385,7 @@ class X393AxiControlStatus(object):
else
:
enabled_channels
&=
~
(
1
<<
chn
);
self
.
write_contol_register
(
vrlg
.
MCONTR_TOP_16BIT_ADDR
+
vrlg
.
MCONTR_TOP_16BIT_CHN_EN
,
enabled_channels
&
0xffff
)
# {16'b0,ENABLED_CHANNELS});
if
self
.
verbose
>
-
10
:
#
0:
if
self
.
verbose
>
0
:
print
(
"ENABLED MEMCTRL CHANNELS 0x
%
x (en/dis)"
%
enabled_channels
)
def
configure_channel_priority
(
self
,
...
...
@@ -398,7 +398,7 @@ class X393AxiControlStatus(object):
"""
global
channel_priority
self
.
write_contol_register
(
vrlg
.
MCONTR_ARBIT_ADDR
+
chn
,
priority
&
0xffff
)
# {16'b0,priority});
if
self
.
verbose
>
-
1
:
#
0:
if
self
.
verbose
>
0
:
print
(
"SET CHANNEL
%
d priority=0x
%
x"
%
(
chn
,
priority
))
channel_priority
[
chn
]
=
priority
system_defines.vh
View file @
0fda102e
// This file may be used to define same pre-processor macros to be included into each parsed file
`ifndef SYSTEM_DEFINES
`define SYSTEM_DEFINES
//`define MEMBRIDGE_DEBUG_READ 1
`define use200Mhz 1
`define USE_CMD_ENCOD_TILED_32_RD 1
// It can be used to check different `ifdef branches
...
...
x393_testbench01.sav
View file @
0fda102e
[*]
[*] GTKWave Analyzer v3.3.64 (w)1999-2014 BSI
[*] Mon May 4
03:20:08
2015
[*] Mon May 4
23:59:20
2015
[*]
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-2015050
3211205371
.lxt"
[dumpfile_mtime] "Mon May 4
03:17:3
8 2015"
[dumpfile_size] 2
74999726
[dumpfile] "/home/andrey/git/x393/simulation/x393_testbench01-2015050
4175355196
.lxt"
[dumpfile_mtime] "Mon May 4
23:58:4
8 2015"
[dumpfile_size] 2
64023680
[savefile] "/home/andrey/git/x393/x393_testbench01.sav"
[timestart]
4189563
0
[timestart]
5054000
0
[size] 1823 1180
[pos] 1919 0
*-
13.063198 41917667
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
*-
20.063198 54490000
-1 -1 -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_testbench01.
[treeopen] x393_testbench01.ddr3_i.
[treeopen] x393_testbench01.simul_axi_hp_wr_i.
...
...
@@ -18,7 +18,7 @@
[sst_width] 202
[signals_width] 547
[sst_expanded] 1
[sst_vpaned_height]
644
[sst_vpaned_height]
775
@800200
-DDR3
@28
...
...
@@ -39,25 +39,6 @@ x393_testbench01.SDD[15:0]
@1000200
-DDR3
@800200
-DDR3
@28
x393_testbench01.SDRST[0]
x393_testbench01.SDCLK[0]
@22
x393_testbench01.SDBA[2:0]
x393_testbench01.SDA[14:0]
@28
x393_testbench01.SDRAS[0]
x393_testbench01.SDCAS[0]
x393_testbench01.SDWE[0]
x393_testbench01.SDODT[0]
x393_testbench01.DQSL[0]
x393_testbench01.DQSU[0]
@22
x393_testbench01.SDD[15:0]
@1000200
-DDR3
@800200
-top
@28
x393_testbench01.RST[0]
...
...
@@ -78,7 +59,7 @@ x393_testbench01.PS_REG_DOUT[31:0]
x393_testbench01.PS_RDATA[31:0]
@1000200
-PS
@
c
00200
@
8
00200
-simul_afi_wr
@28
x393_testbench01.simul_axi_hp_wr_i.WrCmdReleaseMode[1:0]
...
...
@@ -198,9 +179,9 @@ x393_testbench01.simul_axi_hp_wr_i.wstrb[7:0]
x393_testbench01.simul_axi_hp_wr_i.wstrb_out[7:0]
@28
x393_testbench01.simul_axi_hp_wr_i.wvalid[0]
@1
401
200
@1
000
200
-simul_afi_wr
@
8
00200
@
c
00200
-simul_afi_rd
@28
x393_testbench01.simul_axi_hp_rd_i.aclk[0]
...
...
@@ -289,12 +270,12 @@ x393_testbench01.simul_axi_hp_rd_i.sim_rd_data[63:0]
x393_testbench01.simul_axi_hp_rd_i.sim_rd_qos[3:0]
@28
x393_testbench01.simul_axi_hp_rd_i.sim_rd_ready[0]
@c0002
9
@c0002
8
x393_testbench01.simul_axi_hp_rd_i.sim_rd_resp[1:0]
@2
9
@2
8
(0)x393_testbench01.simul_axi_hp_rd_i.sim_rd_resp[1:0]
(1)x393_testbench01.simul_axi_hp_rd_i.sim_rd_resp[1:0]
@140120
1
@140120
0
-group_end
@28
x393_testbench01.simul_axi_hp_rd_i.sim_rd_valid[0]
...
...
@@ -305,10 +286,33 @@ x393_testbench01.simul_axi_hp_rd_i.start_read_burst_w[0]
x393_testbench01.simul_axi_hp_rd_i.was_addr_fifo_write[0]
x393_testbench01.simul_axi_hp_rd_i.was_data_fifo_read[0]
x393_testbench01.simul_axi_hp_rd_i.was_data_fifo_write[0]
@1
000
200
@1
401
200
-simul_afi_rd
@800200
-membridge
@200
-
@22
x393_testbench01.x393_i.membridge_i.afi_awaddr[31:0]
x393_testbench01.x393_i.membridge_i.afi_awlen[3:0]
@28
x393_testbench01.x393_i.membridge_i.afi_awvalid[0]
x393_testbench01.x393_i.membridge_i.afi_wlast[0]
x393_testbench01.x393_i.membridge_i.afi_wvalid[0]
@200
-
@28
x393_testbench01.x393_i.membridge_i.read_over[0]
x393_testbench01.x393_i.membridge_i.read_started[0]
x393_testbench01.x393_i.membridge_i.left_zero[0]
@22
x393_testbench01.x393_i.membridge_i.axi_arw_requested[7:0]
x393_testbench01.x393_i.membridge_i.wresp_conf[7:0]
x393_testbench01.x393_i.membridge_i.axi_wr_pending[7:0]
@28
x393_testbench01.x393_i.membridge_i.read_busy[0]
@200
-
@22
x393_testbench01.x393_i.membridge_i.afi_arlen[3:0]
@28
...
...
@@ -619,7 +623,6 @@ x393_testbench01.x393_i.membridge_i.status_rq[0]
x393_testbench01.x393_i.membridge_i.status_start[0]
x393_testbench01.x393_i.membridge_i.suspend_chn1[0]
@22
x393_testbench01.x393_i.membridge_i.width64_mclk[14:0]
x393_testbench01.x393_i.membridge_i.wr_id[4:0]
@28
x393_testbench01.x393_i.membridge_i.wr_mode[0]
...
...
@@ -637,6 +640,85 @@ x393_testbench01.x393_i.membridge_i.xfer_reset_page_rd[0]
x393_testbench01.x393_i.membridge_i.xfer_reset_page_wr[0]
@1000200
-membridge
@200
-
@800200
-SAXIHP0
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0ACLK[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0ARADDR[31:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0ARBURST[1:0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0ARCACHE[3:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0ARESETN[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0ARID[5:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0ARLEN[3:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0ARLOCK[1:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0ARPROT[2:0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0ARQOS[3:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0ARREADY[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0ARSIZE[2:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0ARVALID[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0AWADDR[31:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0AWBURST[1:0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0AWCACHE[3:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0AWID[5:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0AWLEN[3:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0AWLOCK[1:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0AWPROT[2:0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0AWQOS[3:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0AWREADY[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0AWSIZE[2:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0AWVALID[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0BID[5:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0BREADY[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0BRESP[1:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0BVALID[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0RACOUNT[2:0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0RCOUNT[7:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0RDATA[63:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0RDISSUECAP1EN[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0RID[5:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0RLAST[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0RREADY[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0RRESP[1:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0RVALID[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0WACOUNT[5:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0WCOUNT[7:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0WDATA[63:0]
x393_testbench01.x393_i.ps7_i.SAXIHP0WID[5:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0WLAST[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0WREADY[0]
x393_testbench01.x393_i.ps7_i.SAXIHP0WRISSUECAP1EN[0]
@22
x393_testbench01.x393_i.ps7_i.SAXIHP0WSTRB[7:0]
@28
x393_testbench01.x393_i.ps7_i.SAXIHP0WVALID[0]
@1000200
-SAXIHP0
@c00200
-linear_rw_chn1
@28
...
...
x393_testbench01.tf
View file @
0fda102e
...
...
@@ -31,7 +31,7 @@
//`define TEST_READ_PATTERN 1
//`define TEST_WRITE_BLOCK 1
//`define TEST_READ_BLOCK 1
//
`define TEST_SCANLINE_WRITE
`
define
TEST_SCANLINE_WRITE
`
define
TEST_SCANLINE_WRITE_WAIT
1
// wait TEST_SCANLINE_WRITE finished (frame_done)
//`define TEST_SCANLINE_READ
`
define
TEST_READ_SHOW
1
...
...
@@ -42,7 +42,7 @@
//`define TEST_TILED_WRITE32 1
//`define TEST_TILED_READ32 1
`
define
TEST_AFI_WRITE
1
//
`define TEST_AFI_WRITE 1
`
define
TEST_AFI_READ
1
module
x393_testbench01
#(
...
...
@@ -580,8 +580,8 @@ always #(CLKIN_PERIOD/2) CLK = ~CLK;
end
// protect from never end
initial begin
#200000;
// #5
0000;
//
#200000;
#6
0000;
$
display("finish testbench 2");
$
finish;
end
...
...
@@ -1424,6 +1424,9 @@ task test_afi_rw; // SuppressThisWarning VEditor - may be unused
// -----------------------------------------
integer
mode
;
`
ifdef
MEMBRIDGE_DEBUG_READ
integer
ii
;
`
endif
begin
$display
(
"====== test_afi_rw: write=%d, extra_pages=%d, frame_start= %x, window_full_width=%d, window_width=%d, window_height=%d, window_left=%d, window_top=%d,@%t"
,
write_ddr3
,
extra_pages
,
frame_start_addr
,
window_full_width
,
window_width
,
window_height
,
window_left
,
window_top
,
$time
);
...
...
@@ -1452,7 +1455,16 @@ task test_afi_rw; // SuppressThisWarning VEditor - may be unused
start64
,
lo_addr64
,
size64
);
membridge_start
(
continue
);
membridge_start
(
continue
);
`
ifdef
MEMBRIDGE_DEBUG_READ
// debugging
for
(
ii
=
0
;
ii
<
10
;
ii
=
ii
+
1
)
begin
#200; //#50;
write_contol_register
(
MEMBRIDGE_ADDR
+
MEMBRIDGE_CTRL
,
{
27
'b0,continue,4'
b1101
}
);
// enable both address and data
end
#500;
write_contol_register
(
MEMBRIDGE_ADDR
+
MEMBRIDGE_CTRL
,
{
26
'b0,continue,5'
b10001
}
);
// disable debug (enable remaining xfers)
`
endif
// just wait done
wait_status_condition
(
// may also be read directly from the same bit of mctrl_linear_rw (address=5) status
MEMBRIDGE_STATUS_REG
,
// MCNTRL_TEST01_STATUS_REG_CHN3_ADDR,
...
...
x393_timing.xdc
View file @
0fda102e
...
...
@@ -79,3 +79,5 @@ create_generated_clock -name ddr3_clk_ref [get_nets -hierarchical clk_ref_pre ]
# do not check timing between axi_aclk and other clocks. Code should provide correct asynchronous crossing of the clock boundary.
set_clock_groups -name ps_async_clock -asynchronous -group {axi_aclk}
# do not check timing between clk_axihp_pre and other clocks. Code should provide correct asynchronous crossing of the clock boundary.
set_clock_groups -name ps_async_clock_axihp -asynchronous -group {clk_axihp_pre}
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