`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 08/06/2022 04:29:04 PM // Design Name: // Module Name: c2c_bridge // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module c2c_bridge #( parameter [31:0] FRAME_HEAD = 31'h7E7E7E7E, parameter [31:0] FRAME_MAX_LENGTH = 32'h00002000 ) ( input clk , // input clk, 100Mhz input rst , // input rst, active high //interface data input c2c_clkin , output c2c_clkout, input c2c_din , output c2c_dout , // bram interface output tx_bram_clk , // output bram clk output [31:0] tx_bram_addr , // output bram address[31:0] input [31:0] tx_bram_dout , // input bram data[31:0] output reg tx_bram_en , // output bram enable, active-high output reg [3:0] tx_bram_we , // output bram write enable, active-high output rx_bram_clk , // output bram clk output reg [31:0] rx_bram_addr , // output bram address[31:0] output reg [31:0] rx_bram_din , // output bram data[31:0] output reg rx_bram_en , // output bram enable, active-high output reg [3:0] rx_bram_we , // output bram write enable, active-high // pl interrupt output reg pl_rd_done , // output pl_rd_done, active-high output reg pl_wr_done , // output pl_wr_done, active-high // flag signal from ps to pl input ps_rd_done , // input ps_rd_done, active-high input ps_wr_done // input ps_wr_done, active-high ); reg [31:0] c2c_in_32; reg [39:0] tx_bitcnt; reg [39:0] rx_bitcnt; reg [31:0] tx_frame_length;//byte reg [31:0] rx_frame_length;//byte always @ ( posedge c2c_clkin or posedge rst) begin if ( rst ) begin c2c_in_32 <= 32'h00000000; end else begin c2c_in_32 <= {c2c_in_32[30:0],c2c_din}; end end reg [31:0] c2c_out_32; always @ ( posedge clk or posedge rst) begin if ( rst ) begin c2c_out_32 <= 32'h00000000; end else if(tx_bitcnt[4:0] == 5'd1) begin c2c_out_32 <= tx_bram_dout; end else begin c2c_out_32 <= {c2c_out_32[30:0],1'b0}; end end assign c2c_dout = c2c_out_32[31]; // dly wire pl_read_start; reg ps_rd_done_d0; reg ps_rd_done_d1; reg ps_rd_done_d2; reg ps_wr_done_d0; reg ps_wr_done_d1; reg ps_wr_done_d2; always @ ( posedge clk ) begin if ( rst ) begin ps_rd_done_d0 <= 1'b0; ps_rd_done_d1 <= 1'b0; ps_rd_done_d2 <= 1'b0; ps_wr_done_d0 <= 1'b0; ps_wr_done_d1 <= 1'b0; ps_wr_done_d2 <= 1'b0; end else begin ps_rd_done_d0 <= ps_rd_done; ps_rd_done_d1 <= ps_rd_done_d0; ps_rd_done_d2 <= ps_rd_done_d1; ps_wr_done_d0 <= ps_wr_done; ps_wr_done_d1 <= ps_wr_done_d0; ps_wr_done_d2 <= ps_wr_done_d1; end end assign pl_read_start = ps_wr_done_d1 ^ ps_wr_done_d2; ////////////////// TX PORT ///////////////////// // state machine reg [3:0] tx_state_next; reg [3:0] tx_state; localparam S_TX_WAIT = 4'd0; localparam S_TX_PLREAD = 4'd1; always @ (*) begin case (tx_state) S_TX_WAIT : begin if ( pl_read_start ) begin //can read tx_state_next <= S_TX_PLREAD; end else begin tx_state_next <= S_TX_WAIT; end end S_TX_PLREAD : begin // read bram if(tx_bram_addr[31:0] >= tx_frame_length[31:0]) begin//frame end tx_state_next <= S_TX_WAIT; end else if(tx_bram_addr > FRAME_MAX_LENGTH)begin //overtime tx_state_next <= S_TX_WAIT; end else begin tx_state_next <= S_TX_PLREAD; end end default : begin tx_state_next <= S_TX_WAIT; end endcase end always @(posedge clk) begin tx_state <= tx_state_next; end //tx_bitcnt always @(posedge clk) begin if(rst) begin tx_bitcnt[39:0] <= 40'd0; end else if(tx_state == S_TX_PLREAD) begin tx_bitcnt[39:0] <= tx_bitcnt[39:0]+40'd1; end else begin tx_bitcnt[39:0] <= 40'd0; end end //tx_frame_length always @(posedge clk) begin if(rst) begin tx_frame_length[31:0] <= 32'hFFFFFFFF; end else if(tx_bitcnt == 40'h0000000021) begin tx_frame_length[31:0] <= tx_bram_dout; end else if(tx_state == S_TX_PLREAD) begin tx_frame_length[31:0] <= tx_frame_length[31:0]; end else begin tx_frame_length[31:0] <= 32'hFFFFFFFF; end end // tx_bram_en // always enable always @(posedge clk) begin tx_bram_en <= 1'b1; end // tx_bram_we // always disable always @(posedge clk) begin tx_bram_we[3:0] <= 4'h0; end //tx_bram_addr assign tx_bram_addr = {tx_bitcnt[34:5],2'b0}; assign c2c_clkout = clk; assign tx_bram_clk = clk; ////////////////// RX PORT ///////////////////// reg [3:0] rx_state_next; reg [3:0] rx_state; localparam S_RX_WAIT = 4'd0; localparam S_RX_PLWRITE = 4'd1; always @ (*) begin case (rx_state) S_TX_WAIT : begin if ( c2c_in_32 == FRAME_HEAD ) begin //can write rx_state_next <= S_RX_PLWRITE; end else begin rx_state_next <= S_RX_WAIT; end end S_RX_PLWRITE : begin // write bram if(rx_bram_addr[31:0] >= rx_frame_length[31:0]) begin//frame end rx_state_next <= S_RX_WAIT; end else if(rx_bram_addr > FRAME_MAX_LENGTH)begin //overtime rx_state_next <= S_RX_WAIT; end else begin rx_state_next <= S_RX_PLWRITE; end end default : begin rx_state_next <= S_RX_WAIT; end endcase end always @(posedge c2c_clkin) begin rx_state <= rx_state_next; end //tx_bitcnt always @(posedge c2c_clkin or posedge rst) begin if(rst) begin rx_bitcnt[39:0] <= 40'd0; end else if(rx_state == S_RX_PLWRITE) begin rx_bitcnt[39:0] <= rx_bitcnt[39:0] + 40'd1; end else begin rx_bitcnt <= 40'd0; end end //rx_frame_length always @(posedge c2c_clkin or posedge rst) begin if(rst) begin rx_frame_length[31:0] <= 32'hFFFFFFFF; end else if(rx_bitcnt == 40'h000000001F) begin rx_frame_length[31:0] <= c2c_in_32; end else if(rx_state == S_RX_PLWRITE) begin rx_frame_length[31:0] <= rx_frame_length[31:0]; end else begin rx_frame_length[31:0] <= 32'hFFFFFFFF; end end // rx_bram_en // always enable always @(posedge c2c_clkin) begin rx_bram_en <= 1'b1; end // rx_bram_we // always disable always @(posedge c2c_clkin or posedge rst) begin if(rst) begin rx_bram_we[3:0] <= 4'h0; end else if(rx_state_next == S_RX_PLWRITE) begin rx_bram_we[3:0] <= 4'hF; end else begin rx_bram_we[3:0] <= 4'h0; end end //rx_bram_addr always @(posedge c2c_clkin or posedge rst) begin if(rst) begin rx_bram_addr[31:0] <= 32'd0; end else if(rx_state == S_RX_PLWRITE) begin rx_bram_addr = {rx_bitcnt[34:5],2'b0} + 32'd4; end else begin rx_bram_addr[31:0] <= 32'b0; end end reg [7:0] pl_wr_done_cnt; always @(posedge c2c_clkin or posedge rst) begin if(rst) begin pl_wr_done_cnt <= 8'd0; pl_wr_done <= 1'b0; end else if(rx_state == S_RX_PLWRITE && rx_state_next == S_RX_WAIT && rx_bram_addr <= FRAME_MAX_LENGTH) begin pl_wr_done_cnt <= 8'd16; pl_wr_done <= 1'b1; end else if(pl_wr_done_cnt > 0) begin pl_wr_done_cnt <= pl_wr_done_cnt - 8'd1; pl_wr_done <= 1'b1; end else begin pl_wr_done_cnt <= 8'd0; pl_wr_done <= 1'b0; end end always @(posedge c2c_clkin or posedge rst) begin if(rst) begin rx_bram_din[31:0] <= 32'd0; end else begin rx_bram_din <= c2c_in_32; end end assign rx_bram_clk = c2c_clkin; endmodule