2 lines
10 KiB
JSON
2 lines
10 KiB
JSON
{"task_id": "fsm_ps2data", "task_number": 1, "description": "We want a finite state machine that will search for message boundaries when given an input byte stream. The algorithm we'll use is to discard bytes until we see one with in[3]=1. We then assume that this is byte 1 of a message, and signal the receipt of a message once all 3 bytes have been received (done). The FSM should signal done in the cycle immediately after the third byte of each message was successfully received.\n\n// Implement the datapath module that will output the 24-bit (3 byte) message whenever a packet is received (out_bytes[23:16] is the first byte, out_bytes[15:8] is the second byte, etc.). The reset signal is active high synchronous. out_bytes needs to be valid whenever the done signal is asserted. You may output anything at other times (i.e., don't-care). \n\n// Waveform example:\n// time clk reset in[7:0] done out_bytes \n// 0ns 0 1 0 x x \n// 5ns 1 1 0 0 x \n// 10ns 0 1 0 0 x \n// 15ns 1 0 2c 0 x \n// 20ns 0 0 2c 0 x \n// 25ns 1 0 81 0 x \n// 30ns 0 0 81 0 x \n// 35ns 1 0 9 0 x \n// 40ns 0 0 9 0 x \n// 45ns 1 0 6b 1 2c8109 \n// 50ns 0 0 6b 1 2c8109 \n// 55ns 1 0 d 0 x \n// 60ns 0 0 d 0 x \n// 65ns 1 0 8d 0 x \n// 70ns 0 0 8d 0 x \n// 75ns 1 0 6d 1 6b0d8d \n// 80ns 0 0 6d 1 6b0d8d \n// 85ns 1 0 12 0 x \n// 90ns 0 0 12 0 x \n// 95ns 1 0 1 0 x \n// 100ns 0 0 1 0 x \n// 105ns 1 0 d 1 6d1201 \n// 110ns 0 0 d 1 6d1201 \n// 115ns 1 0 76 0 x \n// 120ns 0 0 76 0 x \n// 125ns 1 0 3d 0 x \n// 130ns 0 0 3d 0 x \n// 135ns 1 0 ed 1 d763d \n// 140ns 0 0 ed 1 d763d \n// 145ns 1 0 8c 0 x \n// 150ns 0 0 8c 0 x \n// 155ns 1 0 f9 0 x \n// 160ns 0 0 f9 0 x \n// 165ns 1 0 ce 1 ed8cf9 \n// 170ns 0 0 ce 1 ed8cf9 \n// 175ns 1 0 c5 0 x \n// 180ns 0 0 c5 0 x \n// 185ns 1 0 aa 0 x \n// 190ns 0 0 aa 0 x ", "header": "module top_module (\n\tinput clk,\n\tinput [7:0] in,\n\tinput reset,\n\toutput [23:0] out_bytes,\n\toutput done\n);\n", "module_code": "module top_module (\n\tinput clk,\n\tinput [7:0] in,\n\tinput reset,\n\toutput [23:0] out_bytes,\n\toutput done\n);\n\tparameter BYTE1=0, BYTE2=1, BYTE3=2, DONE=3;\n\treg [1:0] state;\n\treg [1:0] next;\n \n wire in3 = in[3];\n \n always_comb begin\n\t\tcase (state)\n\t\t\tBYTE1: next = in3 ? BYTE2 : BYTE1;\n\t\t\tBYTE2: next = BYTE3;\n\t\t\tBYTE3: next = DONE;\n\t\t\tDONE: next = in3 ? BYTE2 : BYTE1;\n\t\tendcase\n end\n \n always @(posedge clk) begin\n\t\tif (reset) state <= BYTE1;\n else state <= next;\n\tend\n\t\t\n\tassign done = (state==DONE);\n\t\n\treg [23:0] out_bytes_r;\n\talways @(posedge clk)\n\t\tout_bytes_r <= {out_bytes_r[15:0], in};\n\t\n\t// Implementations may vary: Allow user to do anything while the output doesn't have to be valid.\t\n\tassign out_bytes = done ? out_bytes_r : 'x;\t\t\n\t\nendmodule\n", "testbench": "`timescale 1 ps/1 ps\n`define OK 12\n`define INCORRECT 13\nmodule reference_module (\n\tinput clk,\n\tinput [7:0] in,\n\tinput reset,\n\toutput [23:0] out_bytes,\n\toutput done\n);\n\tparameter BYTE1=0, BYTE2=1, BYTE3=2, DONE=3;\n\treg [1:0] state;\n\treg [1:0] next;\n \n wire in3 = in[3];\n \n always_comb begin\n\t\tcase (state)\n\t\t\tBYTE1: next = in3 ? BYTE2 : BYTE1;\n\t\t\tBYTE2: next = BYTE3;\n\t\t\tBYTE3: next = DONE;\n\t\t\tDONE: next = in3 ? BYTE2 : BYTE1;\n\t\tendcase\n end\n \n always @(posedge clk) begin\n\t\tif (reset) state <= BYTE1;\n else state <= next;\n\tend\n\t\t\n\tassign done = (state==DONE);\n\t\n\treg [23:0] out_bytes_r;\n\talways @(posedge clk)\n\t\tout_bytes_r <= {out_bytes_r[15:0], in};\n\t\n\t// Implementations may vary: Allow user to do anything while the output doesn't have to be valid.\t\n\tassign out_bytes = done ? out_bytes_r : 'x;\t\t\n\t\nendmodule\n\n\nmodule stimulus_gen (\n\tinput clk,\n\toutput logic [7:0] in,\n\toutput logic reset\n);\n\n\tinitial begin\n\t\trepeat(200) @(negedge clk) begin\n\t\t\tin <= $random;\n\t\t\treset <= !($random & 31);\n\t\tend\n\t\treset <= 1'b0;\n\t\tin <= '0;\n\t\trepeat(10) @(posedge clk);\n\t\t\n\t\trepeat(200) begin\n\t\t\tin <= $random;\n\t\t\tin[3] <= 1'b1;\n\t\t\t@(posedge clk);\n\t\t\tin <= $random;\n\t\t\t@(posedge clk);\n\t\t\tin <= $random;\n\t\t\t@(posedge clk);\n\t\tend\n\n\t\t#1 $finish;\n\tend\n\t\nendmodule\n\nmodule tb();\n\n\ttypedef struct packed {\n\t\tint errors;\n\t\tint errortime;\n\t\tint errors_out_bytes;\n\t\tint errortime_out_bytes;\n\t\tint errors_done;\n\t\tint errortime_done;\n\n\t\tint clocks;\n\t} stats;\n\t\n\tstats stats1;\n\t\n\t\n\twire[511:0] wavedrom_title;\n\twire wavedrom_enable;\n\tint wavedrom_hide_after_time;\n\t\n\treg clk=0;\n\tinitial forever\n\t\t#5 clk = ~clk;\n\n\tlogic [7:0] in;\n\tlogic reset;\n\tlogic [23:0] out_bytes_ref;\n\tlogic [23:0] out_bytes_dut;\n\tlogic done_ref;\n\tlogic done_dut;\n\n\tinitial begin \n\t\t$dumpfile(\"wave.vcd\");\n\t\t$dumpvars(1, stim1.clk, tb_mismatch ,clk,in,reset,out_bytes_ref,out_bytes_dut,done_ref,done_dut );\n\tend\n\n\n\twire tb_match;\t\t// Verification\n\twire tb_mismatch = ~tb_match;\n\t\n\tstimulus_gen stim1 (\n\t\t.clk,\n\t\t.* ,\n\t\t.in,\n\t\t.reset );\n\treference_module good1 (\n\t\t.clk,\n\t\t.in,\n\t\t.reset,\n\t\t.out_bytes(out_bytes_ref),\n\t\t.done(done_ref) );\n\t\t\n\ttop_module top_module1 (\n\t\t.clk,\n\t\t.in,\n\t\t.reset,\n\t\t.out_bytes(out_bytes_dut),\n\t\t.done(done_dut) );\n\n\t\n\tbit strobe = 0;\n\ttask wait_for_end_of_timestep;\n\t\trepeat(5) begin\n\t\t\tstrobe <= !strobe; // Try to delay until the very end of the time step.\n\t\t\t@(strobe);\n\t\tend\n\tendtask\t\n\n\t\n\tfinal begin\n\t\tif (stats1.errors_out_bytes) $display(\"Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.\", \"out_bytes\", stats1.errors_out_bytes, stats1.errortime_out_bytes);\n\t\telse $display(\"Hint: Output '%s' has no mismatches.\", \"out_bytes\");\n\t\tif (stats1.errors_done) $display(\"Hint: Output '%s' has %0d mismatches. First mismatch occurred at time %0d.\", \"done\", stats1.errors_done, stats1.errortime_done);\n\t\telse $display(\"Hint: Output '%s' has no mismatches.\", \"done\");\n\n\t\t$display(\"Hint: Total mismatched samples is %1d out of %1d samples\\n\", stats1.errors, stats1.clocks);\n\t\t$display(\"Simulation finished at %0d ps\", $time);\n\t\t$display(\"Mismatches: %1d in %1d samples\", stats1.errors, stats1.clocks);\n\tend\n\t\n\t// Verification: XORs on the right makes any X in good_vector match anything, but X in dut_vector will only match X.\n\tassign tb_match = ( { out_bytes_ref, done_ref } === ( { out_bytes_ref, done_ref } ^ { out_bytes_dut, done_dut } ^ { out_bytes_ref, done_ref } ) );\n\t// Use explicit sensitivity list here. @(*) causes NetProc::nex_input() to be called when trying to compute\n\t// the sensitivity list of the @(strobe) process, which isn't implemented.\n\talways @(posedge clk, negedge clk) begin\n\n\t\tstats1.clocks++;\n\t\tif (!tb_match) begin\n\t\t\tif (stats1.errors == 0) stats1.errortime = $time;\n\t\t\tstats1.errors++;\n\t\tend\n\t\tif (out_bytes_ref !== ( out_bytes_ref ^ out_bytes_dut ^ out_bytes_ref ))\n\t\tbegin if (stats1.errors_out_bytes == 0) stats1.errortime_out_bytes = $time;\n\t\t\tstats1.errors_out_bytes = stats1.errors_out_bytes+1'b1; end\n\t\tif (done_ref !== ( done_ref ^ done_dut ^ done_ref ))\n\t\tbegin if (stats1.errors_done == 0) stats1.errortime_done = $time;\n\t\t\tstats1.errors_done = stats1.errors_done+1'b1; end\n\n\tend\nendmodule\n"}
|