Advertisement
seethesatyrrise

Untitled

Jun 21st, 2017
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import cmd_bits::*;
  2.  
  3. module dev_fsm
  4. #(
  5.     // parameter declaration
  6.     parameter DW = 8    // data width
  7. )
  8. (
  9.     // inputs
  10.     input logic clk, rst, cs,
  11.     input logic [DW - 1:0] din,
  12.  
  13.     // outputs
  14.     output logic busy, drdy,
  15.     output logic [DW - 1:0] dout
  16. );
  17.    
  18.     // state register and next state value
  19.     enum logic [4:0] {ST_IDLE, ST_RCV_1, ST_RCV_2, ST_PROC, ST_TX} state, next_state;
  20.    
  21.     // data and status registers
  22.     logic [DW - 1:0] result;
  23.     logic [DW - 1:0] op_1;
  24.     logic [DW - 1:0] op_2;
  25.     logic [DW - 1:0] cmd;
  26.    
  27.     // state register
  28.     always_ff @ (posedge clk or negedge rst)
  29.     begin
  30.         if (~rst) state <= ST_IDLE;
  31.         else state <= next_state;
  32.     end
  33.  
  34.     //next state logic
  35.     always_comb
  36.     begin
  37.         next_state = state;
  38.         case (state)
  39.         ST_IDLE:
  40.             if (cs)
  41.             begin
  42.                 if (din[b_op_1]) next_state = ST_RCV_1;
  43.                 else if (din[b_op_2]) next_state = ST_RCV_2;
  44.                 else if (din[b_tx]) next_state = ST_TX;
  45.                 else next_state = ST_PROC;
  46.             end
  47.         ST_RCV_1:
  48.             if (cmd[b_op_2]) next_state = ST_RCV_2;
  49.             else if (cmd[b_tx]) next_state = ST_TX;
  50.             else next_state = ST_IDLE;
  51.         ST_RCV_2:
  52.             if (cmd[b_tx]) next_state = ST_TX;
  53.             else next_state = ST_IDLE;
  54.         ST_PROC:
  55.             next_state = ST_IDLE;
  56.         ST_TX:
  57.             next_state = ST_IDLE;
  58.         default:
  59.             next_state = ST_IDLE;
  60.         endcase
  61.     end
  62.  
  63.     // data and status registers
  64.     always_ff @ (posedge clk or negedge rst)
  65.     begin
  66.         if (~rst)
  67.         begin
  68.             drdy <= 0;
  69.             busy <= 0;
  70.             result <= 0;
  71.             op_1 <= 0;
  72.             op_2 <= 0;
  73.             cmd <= 0;
  74.         end
  75.         else
  76.         begin
  77.             //since drdy is registered, set to 1 at the cloc edge when state changes to ST_TX
  78.             drdy<=(next_state==ST_TX);
  79.             //we set busy to 0 at reset and when we enter idle
  80.             busy<=!(next_state==ST_IDLE);
  81.             //latching data in registers
  82.             case (state)
  83.             ST_IDLE:
  84.                 //store command in register when we leave idle
  85.                 if (cs) cmd<=din;
  86.             ST_RCV_1:
  87.                 //store operand 1
  88.                 op_1<=din;
  89.             ST_RCV_2:
  90.                 //store operand 2
  91.                 op_2<=din;
  92.             ST_PROC:
  93.                 //change result register according to opcode
  94.                 case (cmd[DW - 1:DW - 4])
  95.                     4'b1000: result <= op_1 + op_2;
  96.                     4'b0100: result <= op_1 - op_2;
  97.                     4'b0010: result <= result + op_1;
  98.                     4'b0001: result <= result - op_1;
  99.                 endcase
  100.             endcase
  101.         end
  102.     end
  103.  
  104.     assign dout = (state==ST_TX)?result:'bx;
  105.    
  106. endmodule
  107.  
  108.  
  109.  
  110.  
  111. `timescale 1 ps/ 1 ps
  112.  
  113. //command bit definitions
  114. import cmd_bits::*;
  115.  
  116. module dev_fsm_tb();
  117.  
  118.     //parameters
  119.     parameter DW = 8;
  120.  
  121.     // test vector input registers
  122.     logic clk;
  123.     logic cs;
  124.     logic [DW-1:0] din;
  125.     logic rst;
  126.     // module output connections
  127.     logic busy;
  128.     logic [DW-1:0] dout;
  129.     logic drdy;
  130.     // testbench variables
  131.     logic [DW-1:0] res;
  132.  
  133.     //device under test
  134.     dev_fsm #(.DW(DW)) dut (
  135.         .busy(busy),
  136.         .clk(clk),
  137.         .cs(cs),
  138.         .din(din),
  139.         .dout(dout),
  140.         .drdy(drdy),
  141.         .rst(rst)
  142.     );
  143.  
  144.     // create clock
  145.     initial                                                
  146.     begin                                                  
  147.         clk=0;
  148.         forever #10 clk=~clk;
  149.     end                                                    
  150.  
  151.     // reset circuit and run several transactions
  152.     initial
  153.     begin
  154.         // reset
  155.         rst=0;
  156.         @(negedge clk) rst=1;
  157.         //skip one edge after reset
  158.         @(posedge clk);
  159.         // send two operands and add them to result
  160.         write_transaction((1<<b_op_1)|(1<<b_op_2)|(1<<b_addop),$random,$random,res);
  161.         // send one operand, add it to result and read the result back
  162.         write_transaction((1<<b_addop),0,0,res);
  163.         //wait couple clock cycles
  164.         //$stop;
  165.         repeat (2) @(posedge clk);
  166.         write_transaction((1<<b_tx),0,0,res);
  167.         //stop simulation
  168.         @(posedge clk);
  169.         $stop;
  170.     end
  171.    
  172.     //basic transaction with module
  173.     task write_transaction;
  174.         //input signals
  175.         input [DW-1:0] cmd;
  176.         input [DW-1:0] op_1;
  177.         input [DW-1:0] op_2;
  178.         output [DW-1:0] result;
  179.         //transaction implementation
  180.         begin
  181.             //wait while device is busy
  182.             while (busy) @(posedge clk);
  183.             //set chip select and write command to DUT
  184.             cs=1;
  185.             din=cmd;
  186.             //clear chip select
  187.             @(posedge clk);
  188.             cs=0;
  189.             //write op_1 if required and wait for one clock cycle
  190.             if (cmd[b_op_1])
  191.             begin
  192.                 din=op_1;
  193.                 @(posedge clk);
  194.             end
  195.             //write op_2 if required and wait for one clock cycle
  196.             if (cmd[b_op_2])
  197.             begin
  198.                 din=op_2;
  199.                 @(posedge clk);
  200.             end
  201.             //if read is supposed, wait for rdy to latch result
  202.             if (cmd[b_tx])
  203.             begin
  204.                 while (!drdy) @(posedge clk);
  205.                 result = dout;
  206.             end
  207.             else result = 'bx;
  208.         end
  209.     endtask
  210.    
  211. endmodule
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement