framer.v.txt
上传用户:saul_905
上传日期:2013-11-27
资源大小:184k
文件大小:8k
源码类别:

VHDL/FPGA/Verilog

开发平台:

Visual C++

  1. //
  2. // Simple example of a "framer".  In this case, an MPEG framer where
  3. // data is sent in 188-byte frames which begin with a special SYNC character
  4. // defined as 47 hex.  Framing must, of course, handle cases where 47s
  5. // happen to also be embedded in the data.  Framer must be able to find
  6. // the period SYNC characters while not be thrown off by spurious SYNCs.
  7. //
  8. // This circuit uses a modulo-188 counter that serves as a timestamp.
  9. // Every received SYNC character causes the current modulo-188 counter
  10. // to be pushed onto a little queue.  The idea is that the timestamps
  11. // should all be the same if the data was perfectly framed.  If spurious
  12. // false SYNC characters fall in the data, then some of the timestamps
  13. // will be different.  This is OK as long as there is a clear majority.
  14. //
  15. // This circuit is something I started to actually have to do, but then
  16. // I ended up not using it.  It is not tested, so use it only for ideas
  17. // and not as a proven circuit!!
  18. //
  19. // tom coonan, 12/1999
  20. //
  21. module framer (clk, resetb, din, dinstb, dout, doutsync, doutstb, locked);
  22. input clk;
  23. input resetb;
  24. input [7:0] din;
  25. input dinstb;
  26. output [7:0] dout;
  27. output doutsync;
  28. output doutstb;
  29. output locked;
  30. parameter SYNC = 8'h47;
  31. reg [7:0] dout;
  32. reg doutsync;
  33. reg doutstb;
  34. reg locked;
  35. /* Internals */
  36. // Free-running Modulo-188 counter
  37. reg [7:0] cnt188;
  38. // Modulo-188 value when SYNCs are expected once locked.
  39. reg [7:0] syncindex;
  40. // 6 deep queue of timestamps of every time a SYNC character is received.
  41. // the timestamp is the value of the modulo-188 counter when a SYNC is received.
  42. //
  43. reg [7:0] t0; // Oldest timestamp
  44. reg [7:0] t1;
  45. reg [7:0] t2;
  46. reg [7:0] t3;
  47. reg [7:0] t4;
  48. reg [7:0] t5; // Newest timestamp
  49. // Modulo-188 free-running counter.
  50. //
  51. always @(posedge clk or negedge resetb) begin
  52.    if (~resetb) begin
  53.       cnt188 <= 0;
  54.    end
  55.    else begin
  56.       if (dinstb) begin
  57.          if (cnt188 == 187) begin
  58.             cnt188 <= 0;
  59.          end
  60.          else begin
  61.             cnt188 <= cnt188 + 1;
  62.          end
  63.       end
  64.    end
  65. end
  66. // Timestamp queue.
  67. //
  68. always @(posedge clk or negedge resetb) begin
  69.    if (~resetb) begin
  70.       t0 <= 8'hff;  // Let's use FF as an invalid indicator, otherwise
  71.       t1 <= 8'hff;  // we'd potentially get a premature lock..
  72.       t2 <= 8'hff;
  73.       t3 <= 8'hff;
  74.       t4 <= 8'hff;
  75.       t5 <= 8'hff;
  76.    end
  77.    else begin
  78.       if (dinstb && (din == SYNC)) begin
  79.          // Add new timestamp into our queue.
  80.          t0 <= t1;   
  81.          t1 <= t2;   
  82.          t2 <= t3;   
  83.          t3 <= t4;   
  84.          t4 <= t5;   
  85.          t5 <= cnt188;   
  86.       end
  87.    end
  88. end
  89. // Comparators.
  90. wire t0equal = (t0 == cnt188) && (t0 != 8'hFF);
  91. wire t1equal = (t1 == cnt188) && (t1 != 8'hFF);
  92. wire t2equal = (t2 == cnt188) && (t2 != 8'hFF);
  93. wire t3equal = (t3 == cnt188) && (t3 != 8'hFF);
  94. wire t4equal = (t4 == cnt188) && (t4 != 8'hFF);
  95. wire t5equal = (t5 == cnt188) && (t5 != 8'hFF);
  96. // Count number of matches in all the prior timestamps and current modulo-188 time.
  97. wire [3:0] numequal = t0equal + t1equal + t2equal + t3equal + t4equal + t5equal;
  98. // Main sequential process.
  99. //
  100. always @(posedge clk or negedge resetb) begin
  101.    if (~resetb) begin
  102.       locked   <= 0;
  103.       dout     <= 0;
  104.       doutstb  <= 0;
  105.       doutsync <= 0;
  106.       syncindex <= 0;
  107.    end
  108.    else begin
  109.       doutstb  <= 0;  // defaults..
  110.       doutsync <= 0;
  111.       if (dinstb) begin
  112.          dout    <= din;
  113.          doutstb <= 1;
  114.          if (locked) begin
  115.             if (cnt188 == syncindex) begin
  116.                // We expect the data input to be a SYNC.  If it is not, we will
  117.                // immediately drop lock.
  118.                //
  119.                if (din == SYNC) begin
  120.                   $display (".. Received expected SYNC ..");
  121.                   doutsync <= 1;
  122.                end
  123.                else begin
  124.                   locked   <= 0;
  125.                   $display (".. Did not receive expected SYNC, dropping lock! ");
  126.                end
  127.             end
  128.          end
  129.          else begin
  130.             // The following line is the criteria for declaring LOCK.  It
  131.             // says that when a SYNC is recieved we look at the current
  132.             // timestamp, and if this timestamp is present in at least
  133.             // 4 other times in the queue, than this SYNC is an actual SYNC.
  134.             //
  135.             if ((din == SYNC) && (numequal > 3)) begin
  136.                doutsync <= 1;
  137.                locked   <= 1;
  138.                syncindex <= cnt188;
  139.                $display (".. Received SYNC (cnt188=%0h) and declaring LOCK!", cnt188);
  140.             end
  141.          end
  142.       end
  143.    end
  144. end
  145. endmodule
  146. // synopsys translate_off
  147. module test;
  148. reg clk;
  149. reg resetb;
  150. reg [7:0] din;
  151. reg dinstb;
  152. wire [7:0] dout;
  153. wire doutsync;
  154. wire doutstb;
  155. wire locked;
  156. // Instantiate the framer
  157. framer framer (
  158.    .clk(clk),
  159.    .resetb(resetb),
  160.    .din(din),
  161.    .dinstb(dinstb),
  162.    .dout(dout),
  163.    .doutsync(doutsync),
  164.    .doutstb(doutstb),
  165.    .locked(locked)
  166. );
  167. initial begin
  168.    fork
  169.       monitor_cycles(100000); // just in case..
  170.       genreset;
  171.       genclock;
  172.       begin
  173.          gendata (20);
  174.          $display ("Done sending good framed data, now sending trash..");
  175.          genradomdata (188*3);  // 3 frames worth of trash.. should drop lock.
  176.          $display ("Done sending trash.  Killing simulation.");
  177.          $finish;
  178.       end
  179.       monitor_framer_output;
  180.    join
  181. end
  182. // Generate VCD file for viewing.
  183. initial begin
  184.    $dumpfile ("framer.vcd");
  185.    $dumpvars (0,test);   
  186. end
  187. // Just a generic task for watching total cycles.
  188. task monitor_cycles;
  189.    input maxcycles;
  190.    integer maxcycles;
  191.    integer cycles;
  192.    begin
  193.       forever begin
  194.          @(posedge clk);
  195.          cycles = cycles + 1;
  196.          if (cycles > maxcycles) begin
  197.             $finish;
  198.          end
  199.       end
  200.    end
  201. endtask
  202. // Watch output of framer.  Expect to see the pattern 1,2,3,4 after each SYNC.
  203. // This is the pattern that will be injected into framer.
  204. //
  205. task monitor_framer_output;
  206.    integer cnt;
  207.    integer numerrors;
  208.    begin
  209.       numerrors = 0;
  210.       forever begin
  211.          @(posedge doutstb);
  212.          #1;
  213.          if (doutsync) begin
  214.             $display ("Framer says SYNC..");
  215.             cnt = 1;
  216.             repeat (4) begin
  217.                @(posedge doutstb);
  218.                #1
  219.                $display ("   and %h..", dout);
  220.                if (dout != cnt) begin
  221.                   numerrors = numerrors + 1;
  222.                   $display ("!! Unexpected data from framer !! (%0d errors)", numerrors);
  223.                end
  224.                cnt = cnt + 1;
  225.             end
  226.          end
  227.       end
  228.    end
  229. endtask
  230. task genreset;
  231.    begin
  232.       resetb = 0;
  233.       repeat (2) @(posedge clk);
  234.       @(negedge clk);
  235.       resetb = 1;
  236.    end
  237. endtask
  238. task genclock;
  239.    begin
  240.       clk = 0;
  241.       forever begin
  242.          #10 clk = ~clk;
  243.       end
  244.    end
  245. endtask
  246. // Input framed data into the framer.  First 4 bytes of each frame should be
  247. // a simple counting sequence that can then be checked at its output.
  248. //
  249. task gendata;
  250.    input numframes;
  251.    
  252.    integer numframes;
  253.    
  254.    integer cnt;
  255.    begin
  256.       cnt = $random;  // Start randomly in the frame sequence..
  257.       repeat (numframes*188) begin
  258.          repeat (3) @(posedge clk);
  259.          if (cnt == 0) begin
  260.             din = 8'h47;
  261.             $display ("SYNC..");
  262.          end
  263.          else begin
  264.             if (cnt < 5) begin
  265.                din = cnt;
  266.             end
  267.             else begin
  268.                din = $random;
  269.                if (din == 8'h47) begin
  270.                   $display ("   .. Non-SYNC 0x47 embedded in frame data !");
  271.                end
  272.             end
  273.          end
  274.       
  275.          dinstb = 1;
  276.          @(posedge clk);
  277.          dinstb = 0;
  278.          cnt = (cnt + 1) % 188;
  279.       end
  280.    end
  281. endtask
  282. // This will inject trash (no good framing) into framer.  Use this to show
  283. // that it actually drops lock.
  284. //
  285. task genradomdata;
  286.    input numbytes;
  287.    integer numbytes;
  288.    begin
  289.       repeat (numbytes) begin
  290.          repeat (3) @(posedge clk);
  291.          din = $random;
  292.          dinstb = 1;
  293.          @(posedge clk);
  294.          dinstb = 0;
  295.       end
  296.    end
  297. endtask
  298. endmodule
  299. // synopsys translate_on