dmx/ 0000755 0001750 0001750 00000000000 11431235221 012024 5 ustar lekernel lekernel dmx/rtl/ 0000755 0001750 0001750 00000000000 11431045124 012626 5 ustar lekernel lekernel dmx/rtl/dmx_tx.v 0000644 0001750 0001750 00000015026 11431045124 014324 0 ustar lekernel lekernel /*
|
dmx/ 0000755 0001750 0001750 00000000000 11431235221 012024 5 ustar lekernel lekernel dmx/rtl/ 0000755 0001750 0001750 00000000000 11431045124 012626 5 ustar lekernel lekernel dmx/rtl/dmx_tx.v 0000644 0001750 0001750 00000015026 11431045124 014324 0 ustar lekernel lekernel /*
|
* Milkymist VJ SoC
|
* Milkymist VJ SoC
|
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
* Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
|
*
|
*
|
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
* the Free Software Foundation, version 3 of the License.
|
* the Free Software Foundation, version 3 of the License.
|
*
|
*
|
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
*
|
*
|
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
* along with this program. If not, see .
|
* along with this program. If not, see .
|
*/
|
*/
|
|
|
module dmx_tx #(
|
module dmx_tx #(
|
parameter csr_addr = 4'h0,
|
parameter csr_addr = 4'h0,
|
parameter clk_freq = 100000000
|
parameter clk_freq = 100000000
|
) (
|
) (
|
input sys_clk,
|
input sys_clk,
|
input sys_rst,
|
input sys_rst,
|
|
|
input [13:0] csr_a,
|
input [13:0] csr_a,
|
input csr_we,
|
input csr_we,
|
input [31:0] csr_di,
|
input [31:0] csr_di,
|
output [31:0] csr_do,
|
output [31:0] csr_do,
|
|
|
input thru,
|
input thru,
|
output tx
|
output tx
|
);
|
);
|
|
|
/* RAM and CSR interface */
|
/* RAM and CSR interface */
|
|
|
wire csr_selected = csr_a[13:10] == csr_addr;
|
wire csr_selected = csr_a[13:10] == csr_addr;
|
|
|
wire csr_channels_we;
|
wire csr_channels_we;
|
wire [31:0] csr_do_channels;
|
wire [31:0] csr_do_channels;
|
wire [8:0] channel_a;
|
wire [8:0] channel_a;
|
wire [7:0] channel_d;
|
wire [7:0] channel_d;
|
dmx_dpram channels(
|
dmx_dpram channels(
|
.clk(sys_clk),
|
.clk(sys_clk),
|
|
|
.a(csr_a[8:0]),
|
.a(csr_a[8:0]),
|
.we(csr_channels_we),
|
.we(csr_channels_we),
|
.di(csr_di[7:0]),
|
.di(csr_di[7:0]),
|
.do(csr_do_channels[7:0]),
|
.do(csr_do_channels[7:0]),
|
|
|
.a2(channel_a),
|
.a2(channel_a),
|
.we2(1'b0),
|
.we2(1'b0),
|
.di2(8'hxx),
|
.di2(8'hxx),
|
.do2(channel_d)
|
.do2(channel_d)
|
);
|
);
|
assign csr_channels_we = csr_selected & ~csr_a[9] & csr_we;
|
assign csr_channels_we = csr_selected & ~csr_a[9] & csr_we;
|
assign csr_do_channels[31:8] = 24'h000000;
|
assign csr_do_channels[31:8] = 24'h000000;
|
|
|
reg thru_en;
|
reg thru_en;
|
|
|
reg [31:0] csr_do_reg;
|
reg [31:0] csr_do_reg;
|
reg csr_do_sel;
|
reg csr_do_sel;
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(sys_rst) begin
|
if(sys_rst) begin
|
csr_do_reg <= 32'd0;
|
csr_do_reg <= 32'd0;
|
csr_do_sel <= 1'b0;
|
csr_do_sel <= 1'b0;
|
thru_en <= 1'b0;
|
thru_en <= 1'b0;
|
end else begin
|
end else begin
|
csr_do_reg <= 32'd0;
|
csr_do_reg <= 32'd0;
|
csr_do_sel <= 1'b0;
|
csr_do_sel <= 1'b0;
|
if(csr_selected) begin
|
if(csr_selected) begin
|
csr_do_sel <= ~csr_a[9];
|
csr_do_sel <= ~csr_a[9];
|
csr_do_reg <= thru_en;
|
csr_do_reg <= thru_en;
|
if(csr_we) begin
|
if(csr_we) begin
|
if(csr_a[9])
|
if(csr_a[9])
|
thru_en <= csr_di[0];
|
thru_en <= csr_di[0];
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
assign csr_do = csr_do_sel ? csr_do_channels : csr_do_reg;
|
assign csr_do = csr_do_sel ? csr_do_channels : csr_do_reg;
|
|
|
reg tx_gen;
|
reg tx_gen;
|
assign tx = thru_en ? thru : tx_gen;
|
assign tx = thru_en ? thru : tx_gen;
|
|
|
/* Signal generator */
|
/* Signal generator */
|
|
|
parameter divisor = clk_freq/250000;
|
parameter divisor = clk_freq/250000;
|
|
|
reg ce;
|
reg ce;
|
reg [8:0] ce_counter;
|
reg [8:0] ce_counter;
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(sys_rst) begin
|
if(sys_rst) begin
|
ce <= 1'b0;
|
ce <= 1'b0;
|
ce_counter <= divisor-1;
|
ce_counter <= divisor-1;
|
end else begin
|
end else begin
|
if(ce_counter == 9'd0) begin
|
if(ce_counter == 9'd0) begin
|
ce <= 1'b1;
|
ce <= 1'b1;
|
ce_counter <= divisor-1;
|
ce_counter <= divisor-1;
|
end else begin
|
end else begin
|
ce <= 1'b0;
|
ce <= 1'b0;
|
ce_counter <= ce_counter - 9'd1;
|
ce_counter <= ce_counter - 9'd1;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
reg [7:0] channel_d_r;
|
reg [7:0] channel_d_r;
|
reg channel_d_ce;
|
reg channel_d_ce;
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(channel_d_ce)
|
if(channel_d_ce)
|
channel_d_r <= channel_d;
|
channel_d_r <= channel_d;
|
end
|
end
|
|
|
reg [3:0] tx_sel;
|
reg [3:0] tx_sel;
|
parameter TX_SEL_B0 = 4'd0;
|
parameter TX_SEL_B0 = 4'd0;
|
parameter TX_SEL_B1 = 4'd1;
|
parameter TX_SEL_B1 = 4'd1;
|
parameter TX_SEL_B2 = 4'd2;
|
parameter TX_SEL_B2 = 4'd2;
|
parameter TX_SEL_B3 = 4'd3;
|
parameter TX_SEL_B3 = 4'd3;
|
parameter TX_SEL_B4 = 4'd4;
|
parameter TX_SEL_B4 = 4'd4;
|
parameter TX_SEL_B5 = 4'd5;
|
parameter TX_SEL_B5 = 4'd5;
|
parameter TX_SEL_B6 = 4'd6;
|
parameter TX_SEL_B6 = 4'd6;
|
parameter TX_SEL_B7 = 4'd7;
|
parameter TX_SEL_B7 = 4'd7;
|
parameter TX_SEL_HI = 4'd8;
|
parameter TX_SEL_HI = 4'd8;
|
parameter TX_SEL_LO = 4'd9;
|
parameter TX_SEL_LO = 4'd9;
|
|
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
case(tx_sel)
|
case(tx_sel)
|
TX_SEL_B0: tx_gen <= channel_d_r[0];
|
TX_SEL_B0: tx_gen <= channel_d_r[0];
|
TX_SEL_B1: tx_gen <= channel_d_r[1];
|
TX_SEL_B1: tx_gen <= channel_d_r[1];
|
TX_SEL_B2: tx_gen <= channel_d_r[2];
|
TX_SEL_B2: tx_gen <= channel_d_r[2];
|
TX_SEL_B3: tx_gen <= channel_d_r[3];
|
TX_SEL_B3: tx_gen <= channel_d_r[3];
|
TX_SEL_B4: tx_gen <= channel_d_r[4];
|
TX_SEL_B4: tx_gen <= channel_d_r[4];
|
TX_SEL_B5: tx_gen <= channel_d_r[5];
|
TX_SEL_B5: tx_gen <= channel_d_r[5];
|
TX_SEL_B6: tx_gen <= channel_d_r[6];
|
TX_SEL_B6: tx_gen <= channel_d_r[6];
|
TX_SEL_B7: tx_gen <= channel_d_r[7];
|
TX_SEL_B7: tx_gen <= channel_d_r[7];
|
TX_SEL_HI: tx_gen <= 1'b1;
|
TX_SEL_HI: tx_gen <= 1'b1;
|
TX_SEL_LO: tx_gen <= 1'b0;
|
TX_SEL_LO: tx_gen <= 1'b0;
|
default: tx_gen <= 1'bx;
|
default: tx_gen <= 1'bx;
|
endcase
|
endcase
|
end
|
end
|
|
|
reg acounter_reset;
|
reg acounter_reset;
|
reg acounter_ce;
|
reg acounter_ce;
|
reg frame_done;
|
reg frame_done;
|
reg [8:0] acounter;
|
reg [8:0] acounter;
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(ce) begin
|
if(ce) begin
|
if(acounter_reset) begin
|
if(acounter_reset) begin
|
acounter <= 9'd0;
|
acounter <= 9'd0;
|
frame_done <= 1'b0;
|
frame_done <= 1'b0;
|
end else if(acounter_ce) begin
|
end else if(acounter_ce) begin
|
acounter <= acounter + 9'd1;
|
acounter <= acounter + 9'd1;
|
frame_done <= acounter == 9'd511;
|
frame_done <= acounter == 9'd511;
|
end
|
end
|
end
|
end
|
end
|
end
|
assign channel_a = acounter;
|
assign channel_a = acounter;
|
|
|
reg break_counter_reset;
|
reg break_counter_reset;
|
reg [4:0] break_counter;
|
reg [4:0] break_counter;
|
reg break_done;
|
reg break_done;
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(ce) begin
|
if(ce) begin
|
if(break_counter_reset) begin
|
if(break_counter_reset) begin
|
break_counter <= 5'd0;
|
break_counter <= 5'd0;
|
break_done <= 1'b0;
|
break_done <= 1'b0;
|
end else begin
|
end else begin
|
if(break_counter == 5'd25)
|
if(break_counter == 5'd25)
|
break_done <= 1'b1;
|
break_done <= 1'b1;
|
else
|
else
|
break_counter <= break_counter + 5'd1;
|
break_counter <= break_counter + 5'd1;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
reg [4:0] state;
|
reg [4:0] state;
|
reg [4:0] next_state;
|
reg [4:0] next_state;
|
|
|
parameter MTBP = 5'd0;
|
parameter MTBP = 5'd0;
|
parameter BREAK = 5'd1;
|
parameter BREAK = 5'd1;
|
parameter MAB1 = 5'd2;
|
parameter MAB1 = 5'd2;
|
parameter MAB2 = 5'd3;
|
parameter MAB2 = 5'd3;
|
parameter SC_START = 5'd4;
|
parameter SC_START = 5'd4;
|
parameter SC_D0 = 5'd5;
|
parameter SC_D0 = 5'd5;
|
parameter SC_D1 = 5'd6;
|
parameter SC_D1 = 5'd6;
|
parameter SC_D2 = 5'd7;
|
parameter SC_D2 = 5'd7;
|
parameter SC_D3 = 5'd8;
|
parameter SC_D3 = 5'd8;
|
parameter SC_D4 = 5'd9;
|
parameter SC_D4 = 5'd9;
|
parameter SC_D5 = 5'd10;
|
parameter SC_D5 = 5'd10;
|
parameter SC_D6 = 5'd11;
|
parameter SC_D6 = 5'd11;
|
parameter SC_D7 = 5'd12;
|
parameter SC_D7 = 5'd12;
|
parameter SC_STOP1 = 5'd13;
|
parameter SC_STOP1 = 5'd13;
|
parameter SC_STOP2 = 5'd14;
|
parameter SC_STOP2 = 5'd14;
|
parameter START = 5'd15;
|
parameter START = 5'd15;
|
parameter D0 = 5'd16;
|
parameter D0 = 5'd16;
|
parameter D1 = 5'd17;
|
parameter D1 = 5'd17;
|
parameter D2 = 5'd18;
|
parameter D2 = 5'd18;
|
parameter D3 = 5'd19;
|
parameter D3 = 5'd19;
|
parameter D4 = 5'd20;
|
parameter D4 = 5'd20;
|
parameter D5 = 5'd21;
|
parameter D5 = 5'd21;
|
parameter D6 = 5'd22;
|
parameter D6 = 5'd22;
|
parameter D7 = 5'd23;
|
parameter D7 = 5'd23;
|
parameter STOP1 = 5'd24;
|
parameter STOP1 = 5'd24;
|
parameter STOP2 = 5'd25;
|
parameter STOP2 = 5'd25;
|
|
|
always @(posedge sys_clk) begin
|
always @(posedge sys_clk) begin
|
if(sys_rst)
|
if(sys_rst)
|
state <= MTBP;
|
state <= MTBP;
|
else if(ce)
|
else if(ce)
|
state <= next_state;
|
state <= next_state;
|
end
|
end
|
|
|
always @(*) begin
|
always @(*) begin
|
tx_sel = TX_SEL_HI;
|
tx_sel = TX_SEL_HI;
|
acounter_reset = 1'b1;
|
acounter_reset = 1'b1;
|
acounter_ce = 1'b0;
|
acounter_ce = 1'b0;
|
break_counter_reset = 1'b1;
|
break_counter_reset = 1'b1;
|
|
|
channel_d_ce = 1'b0;
|
channel_d_ce = 1'b0;
|
|
|
next_state = state;
|
next_state = state;
|
|
|
case(state)
|
case(state)
|
MTBP: next_state = BREAK;
|
MTBP: next_state = BREAK;
|
|
|
BREAK: begin
|
BREAK: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
break_counter_reset = 1'b0;
|
break_counter_reset = 1'b0;
|
if(break_done)
|
if(break_done)
|
next_state = MAB1;
|
next_state = MAB1;
|
end
|
end
|
|
|
MAB1: next_state = MAB2;
|
MAB1: next_state = MAB2;
|
MAB2: next_state = SC_START;
|
MAB2: next_state = SC_START;
|
|
|
SC_START: begin
|
SC_START: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D0;
|
next_state = SC_D0;
|
end
|
end
|
SC_D0: begin
|
SC_D0: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D1;
|
next_state = SC_D1;
|
end
|
end
|
SC_D1: begin
|
SC_D1: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D2;
|
next_state = SC_D2;
|
end
|
end
|
SC_D2: begin
|
SC_D2: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D3;
|
next_state = SC_D3;
|
end
|
end
|
SC_D3: begin
|
SC_D3: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D4;
|
next_state = SC_D4;
|
end
|
end
|
SC_D4: begin
|
SC_D4: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D5;
|
next_state = SC_D5;
|
end
|
end
|
SC_D5: begin
|
SC_D5: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D6;
|
next_state = SC_D6;
|
end
|
end
|
SC_D6: begin
|
SC_D6: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_D7;
|
next_state = SC_D7;
|
end
|
end
|
SC_D7: begin
|
SC_D7: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
next_state = SC_STOP1;
|
next_state = SC_STOP1;
|
end
|
end
|
SC_STOP1: next_state = SC_STOP2;
|
SC_STOP1: next_state = SC_STOP2;
|
SC_STOP2: next_state = START;
|
SC_STOP2: next_state = START;
|
|
|
START: begin
|
START: begin
|
tx_sel = TX_SEL_LO;
|
tx_sel = TX_SEL_LO;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
channel_d_ce = 1'b1;
|
channel_d_ce = 1'b1;
|
next_state = D0;
|
next_state = D0;
|
end
|
end
|
D0: begin
|
D0: begin
|
tx_sel = TX_SEL_B0;
|
tx_sel = TX_SEL_B0;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D1;
|
next_state = D1;
|
end
|
end
|
D1: begin
|
D1: begin
|
tx_sel = TX_SEL_B1;
|
tx_sel = TX_SEL_B1;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D2;
|
next_state = D2;
|
end
|
end
|
D2: begin
|
D2: begin
|
tx_sel = TX_SEL_B2;
|
tx_sel = TX_SEL_B2;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D3;
|
next_state = D3;
|
end
|
end
|
D3: begin
|
D3: begin
|
tx_sel = TX_SEL_B3;
|
tx_sel = TX_SEL_B3;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D4;
|
next_state = D4;
|
end
|
end
|
D4: begin
|
D4: begin
|
tx_sel = TX_SEL_B4;
|
tx_sel = TX_SEL_B4;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D5;
|
next_state = D5;
|
end
|
end
|
D5: begin
|
D5: begin
|
tx_sel = TX_SEL_B5;
|
tx_sel = TX_SEL_B5;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D6;
|
next_state = D6;
|
end
|
end
|
D6: begin
|
D6: begin
|
tx_sel = TX_SEL_B6;
|
tx_sel = TX_SEL_B6;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = D7;
|
next_state = D7;
|
end
|
end
|
D7: begin
|
D7: begin
|
tx_sel = TX_SEL_B7;
|
tx_sel = TX_SEL_B7;
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
next_state = STOP1;
|
next_state = STOP1;
|
end
|
end
|
STOP1: begin
|
STOP1: begin
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
acounter_ce = 1'b1;
|
acounter_ce = 1'b1;
|
next_state = STOP2;
|
next_state = STOP2;
|
end
|
end
|
STOP2: begin
|
STOP2: begin
|
acounter_reset = 1'b0;
|
acounter_reset = 1'b0;
|
if(frame_done)
|
if(frame_done)
|
next_state = MTBP;
|
next_state = MTBP;
|
else
|
else
|
next_state = START;
|
next_state = START;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|