Guest User

Untitled

a guest
Oct 17th, 2017
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module frame_store (
  2.    // Video interface
  3.    input  logic             comClk,
  4.    input  logic [ 19:0]     video_data_in,
  5.    input  logic             video_data_valid,
  6.  
  7.    // CPU configuration (all false paths)
  8.    input  logic             reset,
  9.    input  logic             interlaced,
  10.    input  logic             top_bottom,             // If this is set to 1, use top-bottom, otherwise use field interlaced
  11.    input  logic [ 21:0]     top_line_interval_1,    // 10:0 is the lower limit and 21:11 is the upper limit (10 bit numbers)
  12.    input  logic [ 21:0]     top_line_interval_2,    // Only used when top_bottom and interlaced are both true
  13.    input  logic [ 10:0]     vsync_line_number,      // Which line number directly follows the FRAME vsync
  14.    input  logic [ 10:0]     lines_per_frame,
  15.  
  16.    // DDR interface
  17.    input  logic             clk,
  18.    input  logic             fifo_rd,
  19.    output logic [ 23:0]     addr,
  20.    output logic [159:0]     fifo_data_out,
  21.    output logic [  2:0]     wr_req,
  22.    output logic [  7:0]     wr_cnt,
  23.  
  24.    // Read agent interface
  25.    output logic             start_reading
  26. );
  27.  
  28. parameter BANK_SELECT = 2'b10;
  29.  
  30. typedef enum logic [1:0] {
  31.    top,
  32.    bottom,
  33.    anc,
  34.    unknown
  35. } region_t;
  36.  
  37. // One-hot state machine indexes
  38. enum logic [1:0] {
  39.    DEC_3FF_BIT,
  40.    DEC_000_BIT,
  41.    DEC_001_BIT,
  42.    DEC_XYZ_BIT
  43. } trs_sm_index;
  44.  
  45. // One-hot state machine states
  46. typedef enum logic [3:0] {
  47.    dec_3ff     = 4'b1<<DEC_3FF_BIT,
  48.    dec_000     = 4'b1<<DEC_000_BIT,
  49.    dec_001     = 4'b1<<DEC_001_BIT,
  50.    dec_xyz     = 4'b1<<DEC_XYZ_BIT
  51. } trs_sm_t;
  52.  
  53. typedef struct packed {
  54.    region_t    region;
  55.    logic [5:0] count;
  56. } fifo_data_t;
  57.  
  58. trs_sm_t             trs_sm;
  59. trs_sm_t             trs_sm_next;
  60. logic                vsync;
  61. logic                hsync;
  62. logic                field;
  63. logic                vsync_next;
  64. logic                hsync_next;
  65. logic                field_next;
  66. logic [ 4:0][19:0]   video_data_in_delay;
  67. logic [159:0]        fifo_in;
  68. logic                rdempty;
  69. logic [ 6:0]         rdusedw;
  70.  
  71. region_t             video_region;  // current data type from the input video
  72.  
  73. fifo_data_t          first;         // first data type in the fifo
  74. fifo_data_t          middle;        // middle data type in the fifo
  75. fifo_data_t          last;          // last data type in the fifo
  76. fifo_data_t          first_next;
  77. fifo_data_t          middle_next;
  78. fifo_data_t          last_next;
  79.  
  80.  
  81. logic [ 3:0][19:0]   region_address;
  82. logic [ 3:0][19:0]   region_address_next;
  83. logic [ 3:0][ 8:0]   num_columns_left;
  84. logic [ 3:0][ 8:0]   num_columns_left_next;
  85.  
  86. logic                fifo_wr;
  87. logic                fifo_wr_2x;    // This signal is only 1 clk_2x cycle wide
  88. logic                two_fifo_wrs;    // This signal is only 1 clk_2x cycle wide
  89. logic                fifo_wr_cnt;
  90. logic                synced_d1;     // The data is delayed 5 times now to register the video_region  
  91. logic                synced;        // goes high after the last sample of a frame is detected
  92. logic                synced_next;
  93. logic [ 2:0]         hsync_extend_count;
  94. logic                active_video;
  95. logic [10:0]         video_line_number;
  96. logic [10:0]         video_line_number_next;
  97. logic                start_reading_next;
  98. integer              i;
  99. logic [ 6:0]         rdusedw_minus_1;
  100. logic [ 5:0]         wr_cnt_next;
  101. logic [ 5:0]         wr_cnt_int;
  102.  
  103. logic [ 2:0]         active_in_count;
  104. logic [ 3:0]         anc_in_count;
  105.  
  106. logic [ 7:0][19:0]   fifo_in_active;
  107. logic [15:0][19:0]   fifo_in_anc;
  108.  
  109. logic                fifo_in_ready;
  110. logic                write_anc_data;
  111. logic                anc_lo_hi_n;
  112.  
  113. logic [ 2:0]         fifo_state, fifo_state_next;
  114.  
  115. assign two_fifo_wrs     = fifo_wr_2x & fifo_wr_cnt;
  116. assign fifo_in_ready    = video_region == anc ? video_data_valid & write_anc_data : &active_in_count & video_data_valid;
  117. assign fifo_wr          = fifo_in_ready & synced_d1; // Suppress writes until the frame position is known
  118. assign fifo_in          = video_region == anc ? anc_lo_hi_n ? fifo_in_anc[7:0] : fifo_in_anc[15:8] : {video_data_in_delay[4], fifo_in_active[6:0]};
  119.  
  120. assign active_video     = !(hsync | |hsync_extend_count) & !vsync;
  121.  
  122.  
  123. assign addr             = {BANK_SELECT, first.region, region_address[first.region]};
  124. assign wr_req           = {3{rdusedw[5]}};
  125.  
  126.  
  127. always @* begin
  128.    wr_cnt         = 8'd0;
  129.    case (1'b1)
  130.       fifo_state[0]: begin
  131.          if (num_columns_left[first.region] < 8'd31) begin
  132.             wr_cnt   = num_columns_left[first.region];
  133.          end
  134.          else begin
  135.             wr_cnt   = 8'd31;
  136.          end
  137.       end
  138.       fifo_state[1], fifo_state[2]: begin
  139.          if (num_columns_left[first.region] < first.count) begin
  140.             wr_cnt   = num_columns_left[first.region];
  141.          end
  142.          else begin
  143.             wr_cnt   = {2'b00, first.count};
  144.          end
  145.       end
  146.    endcase
  147. end
  148.  
  149.  
  150.  
  151. // write_anc_data and anc_lo_hi_n control writing 16 ANC samples to the fifo
  152. // at once. This will prevent any problems that arise from the memory requirement
  153. // to always write in bursts of 4 by ensuring there are always multiples of 4
  154. // waiting to be written. The active video doesn't have this problem.
  155. always @(posedge comClk) begin
  156.    if (reset) begin
  157.       write_anc_data <= 1'b0;
  158.       anc_lo_hi_n    <= 1'b0;
  159.    end
  160.    else begin
  161.       if (video_data_valid) begin
  162.          if (video_region == anc) begin
  163.             if (&anc_in_count) begin
  164.                write_anc_data       <= 1'b1;
  165.                anc_lo_hi_n          <= 1'b1;
  166.             end
  167.             if (anc_lo_hi_n) begin
  168.                anc_lo_hi_n             <= 1'b0;
  169.             end
  170.             if (write_anc_data & !anc_lo_hi_n) begin
  171.                write_anc_data          <= 1'b0;
  172.             end
  173.          end
  174.       end
  175.    end
  176. end
  177.  
  178. // Decode the input video region
  179. always @(posedge comClk) begin
  180.    if (video_data_valid) begin
  181.       if (top_bottom) begin   // Indicates two line number ranges are needed to determine what region we're in
  182.          if (active_video) begin
  183.             if ((video_line_number >= top_line_interval_1[10:0] && video_line_number <= top_line_interval_1[21:11]) ||
  184.                 (video_line_number >= top_line_interval_2[10:0] && video_line_number <= top_line_interval_2[21:11]))
  185.             begin
  186.                video_region      <= top;
  187.             end
  188.             else begin
  189.                video_region      <= bottom;
  190.             end
  191.          end
  192.          else begin
  193.             video_region         <= anc;
  194.          end
  195.       end
  196.       else begin              // Only one line number range is used
  197.          if (active_video) begin
  198.             if (video_line_number >= top_line_interval_1[10:0] && video_line_number <= top_line_interval_1[21:11]) begin
  199.                video_region      <= top;
  200.             end
  201.             else begin
  202.                video_region      <= bottom;
  203.             end
  204.          end
  205.          else begin
  206.             video_region         <= anc;
  207.          end
  208.       end
  209.    end
  210. end
  211.  
  212. // Realign the video to the TRS signals
  213. always @(posedge comClk) begin
  214.    if (video_data_valid) begin
  215.       video_data_in_delay[4]  <= video_data_in_delay[3];
  216.       video_data_in_delay[3]  <= video_data_in_delay[2];
  217.       video_data_in_delay[2]  <= video_data_in_delay[1];
  218.       video_data_in_delay[1]  <= video_data_in_delay[0];
  219.       video_data_in_delay[0]  <= video_data_in;
  220.    end
  221. end
  222.  
  223. // Store the video and decode the TRS
  224. always @(posedge comClk) begin
  225.    if (reset) begin
  226.       synced               <= 1'b0;
  227.       synced_d1            <= 1'b0;
  228.       anc_in_count         <= 4'd0;
  229.       active_in_count      <= 3'd0;
  230.       trs_sm               <= dec_3ff;
  231.       video_line_number    <= 11'h0;
  232.       start_reading        <= 1'b0;
  233.       hsync_extend_count   <= 3'b0;
  234.    end
  235.    else begin
  236.       if (video_data_valid) begin
  237.          if (synced_d1) begin // Start preparing data to be written into the FIFO (two words at once)
  238.             if (video_region == anc) begin
  239.                anc_in_count <= anc_in_count + 1'b1;
  240.                fifo_in_anc[anc_in_count] <= video_data_in_delay[4];
  241.             end
  242.             else begin
  243.                active_in_count <= active_in_count + 1'b1;
  244.                fifo_in_active[active_in_count] <= video_data_in_delay[4];
  245.             end
  246.          end
  247.          if (!hsync_next & hsync) begin
  248.             hsync_extend_count <= 3'b100;
  249.          end
  250.          else if (|hsync_extend_count) begin
  251.             hsync_extend_count <= hsync_extend_count + 1'b1;
  252.          end
  253.  
  254.          video_line_number <= video_line_number_next;
  255.          trs_sm            <= trs_sm_next;
  256.          vsync             <= vsync_next;
  257.          hsync             <= hsync_next;
  258.          field             <= field_next;
  259.          synced            <= synced_next;
  260.          synced_d1         <= synced;
  261.          start_reading     <= start_reading_next;
  262.       end
  263.    end
  264. end
  265.  
  266. always @* begin
  267.    trs_sm_next             = trs_sm;
  268.    vsync_next              = vsync;
  269.    hsync_next              = hsync;
  270.    field_next              = field;
  271.    synced_next             = synced;
  272.    start_reading_next      = start_reading;
  273.  
  274.  
  275.    case (1'b1)
  276.       trs_sm[DEC_3FF_BIT]: begin
  277.          if (video_data_in[19:10] == 10'h3ff) begin
  278.             trs_sm_next = dec_000;
  279.          end
  280.       end
  281.       trs_sm[DEC_000_BIT]: begin
  282.          if (video_data_in[19:10] == 10'h000) begin
  283.             trs_sm_next = dec_001;
  284.          end
  285.          else begin
  286.             trs_sm_next = dec_3ff;
  287.          end
  288.       end
  289.       trs_sm[DEC_001_BIT]: begin
  290.          if (video_data_in[19:10] == 10'h000) begin
  291.             trs_sm_next = dec_xyz;
  292.          end
  293.          else begin
  294.             trs_sm_next = dec_3ff;
  295.          end
  296.       end
  297.       trs_sm[DEC_XYZ_BIT]: begin
  298.          trs_sm_next = dec_3ff;
  299.          field_next  = video_data_in[18];
  300.          vsync_next  = video_data_in[17];
  301.          hsync_next  = video_data_in[16];
  302.       end
  303.       default: begin
  304.          trs_sm_next = dec_3ff;
  305.       end
  306.    endcase
  307.  
  308.    if (vsync_next & !vsync & (interlaced & field | !interlaced)) begin
  309.       video_line_number_next     = vsync_line_number;
  310.    end
  311.    else if (hsync_next & !hsync) begin // New line starting
  312.       if (video_line_number == lines_per_frame) begin
  313.          video_line_number_next  = 11'd1;
  314.          synced_next             =  1'b1;
  315.          if (synced) begin
  316.             start_reading_next   =  1'b1;
  317.          end
  318.       end
  319.  
  320.       else begin
  321.          // Don't count after a reset until the line number is determined
  322.          video_line_number_next  = video_line_number + (|video_line_number);
  323.       end
  324.    end
  325.    else begin
  326.       video_line_number_next     = video_line_number;
  327.    end
  328. end
  329.  
  330. // Keep track of the addresses for the 3 memory regions by dividing the FIFO
  331. // into 3 sections (there will never be more than 3 different regions in the
  332. // FIFO at once)
  333. always @(posedge clk) begin
  334.    if (reset) begin
  335.       fifo_wr_2x        <= 1'b0;
  336.       first.region      <= unknown;
  337.       middle.region     <= unknown;
  338.       last.region       <= unknown;
  339.       first.count       <= 6'd0;
  340.       middle.count      <= 6'd0;
  341.       last.count        <= 6'd0;
  342.       fifo_state        <= 3'b001;
  343.       fifo_wr_cnt       <= 1'b0;
  344.       for (i = 0; i < 4; i++) begin
  345.          region_address[i]     <= 20'd0;
  346.          num_columns_left[i]   <=  9'd511;
  347.       end
  348.    end
  349.    else begin
  350.       fifo_wr_2x <= fifo_wr_2x ^ fifo_wr; // fifo_wr will be 2 clk cycles long, this changes it so it's only 1
  351.       if (fifo_wr_2x) begin
  352.          fifo_wr_cnt <= !fifo_wr_cnt;
  353.       end
  354.  
  355.       for (i = 0; i < 4; i++) begin
  356.          region_address[i]     <= region_address_next[i];
  357.          num_columns_left[i]   <= num_columns_left_next[i];
  358.       end
  359.       first       <= first_next;
  360.       middle      <= middle_next;
  361.       last        <= last_next;
  362.       fifo_state  <= fifo_state_next;
  363.    end
  364. end
  365.  
  366. always @* begin
  367.    for (i = 0; i < 4; i++) begin
  368.       region_address_next[i]     = region_address[i];
  369.       num_columns_left_next[i]   = num_columns_left[i];
  370.    end
  371.  
  372.    first_next           = first;
  373.    middle_next          = middle;
  374.    last_next            = last;
  375. //   wr_cnt_next          = wr_cnt_int;
  376.    fifo_state_next      = fifo_state;
  377.    if (fifo_state[0]) begin  // In this case, the fifo should only have one data type in it
  378.       case ({fifo_rd, two_fifo_wrs})
  379.          2'b01: begin
  380.             if (first.region == video_region) begin
  381.                first_next.count              = first.count + (!(|first.count) ? 1'b1 : 2'b10);
  382.                middle_next.count             = first.count + (!(|first.count) ? 1'b1 : 2'b10);
  383.                last_next.count               = first.count + (!(|first.count) ? 1'b1 : 2'b10);
  384.             end
  385.          end
  386.          2'b10: begin
  387.             first_next.count              = first.count - 1'b1;
  388.             middle_next.count             = first.count - 1'b1;
  389.             last_next.count               = first.count - 1'b1;
  390.          end
  391.          2'b11: begin
  392.             if (first.region != video_region) begin
  393.                first_next.count           = first.count - 1'b1;
  394.             end
  395.             else begin
  396.                first_next.count              = first.count + 1'b1;
  397.                middle_next.count             = first.count + 1'b1;
  398.                last_next.count               = first.count + 1'b1;
  399.             end
  400.          end
  401.          // All other combinations result in the count staying the same
  402.       endcase
  403.       if (fifo_rd) begin
  404.          region_address_next[first.region]   = region_address[first.region] + 1'b1;
  405.          num_columns_left_next[first.region] = num_columns_left[first.region] - 1'b1;
  406.       end
  407.    end
  408.    else begin
  409.       if (fifo_rd) begin
  410.          first_next.count                    = first.count - 1'b1;
  411.          region_address_next[first.region]   = region_address[first.region] + 1'b1;
  412.          num_columns_left_next[first.region] = num_columns_left[first.region] - 1'b1;
  413.       end
  414.       if (two_fifo_wrs) begin
  415.          if (middle.region == video_region) begin
  416.             middle_next.count          = last.count + (!(|last.count) ? 1'b1 : 2'b10);
  417.          end
  418.          last_next.count               = last.count + (!(|last.count) ? 1'b1 : 2'b10);
  419.       end
  420.    end
  421.  
  422.    // The state of the FIFO can be 4 possible things:
  423.    // rdempty is 1, the FIFO is empty (first == middle == last)
  424.    // One memory region in the FIFO, rdempty is 0 (first == middle == last)
  425.    // Two memory regions in the FIFO (first will be one, middle and last will be the other)
  426.    // Three memory regions in the FIFO (first, middle and last won't be equal)
  427.  
  428.    case (1'b1)
  429.       fifo_state[0]: begin
  430.          if (fifo_wr_2x) begin
  431.             if (first.region != video_region) begin
  432.                if (rdempty || (fifo_rd & first.count == 6'h0)) begin
  433.                   first_next.region       = video_region;
  434.                   middle_next.region      = video_region;
  435.                   last_next.region        = video_region;
  436.                   first_next.count        = 6'd0;
  437.                   middle_next.count       = 6'd0;
  438.                   last_next.count         = 6'd0;
  439.                end
  440.                else begin
  441.                   fifo_state_next         = 3'b010;
  442.                   middle_next.region      = video_region;
  443.                   last_next.region        = video_region;
  444.                   middle_next.count       = 8'd0;
  445.                   last_next.count         = 8'd0;
  446.                end
  447.             end
  448.          end
  449.       end
  450.       fifo_state[1]: begin
  451.          if (fifo_wr_2x) begin
  452.             if (last.region != video_region) begin
  453.                fifo_state_next    = 3'b100;
  454.                last_next.region   = video_region;
  455.                last_next.count    = 8'd0;
  456.             end
  457.          end
  458.          if (fifo_rd && first.count == 6'h0) begin
  459.             if (last.region == last_next.region) begin
  460.                fifo_state_next       = 3'b001;
  461.             end
  462.             first_next            = middle_next;
  463.             middle_next           = last_next; // last could be changing this cycle
  464.          end
  465.       end
  466.       fifo_state[2]: begin
  467.          if (fifo_rd && first.count == 6'h0) begin
  468.             fifo_state_next      = 3'b010;
  469.             first_next           = middle_next;
  470.             middle_next          = last_next;
  471.          end
  472.       end
  473.    endcase
  474. end
  475.  
  476.  
  477. fifo_64x160_async m_fifo_64x160_async (
  478.    .aclr       (reset),
  479.    .data       (fifo_in),
  480.    .rdclk      (clk),
  481.    .rdreq      (fifo_rd),
  482.    .wrclk      (comClk),
  483.    .wrreq      (fifo_wr),
  484.    .q          (fifo_data_out),
  485.    .rdempty    (rdempty),
  486.    .rdusedw    (rdusedw)
  487. );
  488.  
  489. endmodule
Add Comment
Please, Sign In to add comment