sigmoid.sv 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. `include "../fpu32/compare.sv"
  2. typedef enum logic [2:0] {
  3. hs_input,
  4. hs_compare_0,
  5. hs_compare_1,
  6. hs_compute_0,
  7. hs_compute_1,
  8. hs_output
  9. } hs_stage;
  10. /*
  11. Function:
  12. y = (x + 2.5) * 0.2
  13. minimum = 0
  14. maximum = 1
  15. */
  16. module hard_sigmoid #(parameter N=32)(clk, rst, x, y, left, right);
  17. input clk, rst;
  18. input [N-1:0] x;
  19. output logic [N-1:0] y;
  20. abus_io left, right;
  21. logic [N-1:0] value, comp_result;
  22. hs_stage stage;
  23. logic gt_neg;
  24. logic lt_pos;
  25. logic compute; // Flag to tell if mult and add compution is needed
  26. wire join_ack, join_stb;
  27. wire [N-1:0] join_value;
  28. logic in_stb, out_ack;
  29. wire in_ack, out_stb;
  30. // Multiply by 0.2
  31. multiplier mult0(
  32. .clk(clk),
  33. .rst(rst),
  34. .input_a('h3e4ccccd),
  35. .input_b(join_value),
  36. .input_stb(join_stb),
  37. .input_ack(join_ack),
  38. .output_z(comp_result),
  39. .output_z_ack(out_ack),
  40. .output_z_stb(out_stb)
  41. );
  42. // Add +2.5
  43. adder add0(
  44. .clk(clk),
  45. .rst(rst),
  46. .input_a('h40200000),
  47. .input_b(value),
  48. .input_stb(in_stb),
  49. .input_ack(in_ack),
  50. .output_z(join_value),
  51. .output_z_ack(join_ack),
  52. .output_z_stb(join_stb)
  53. );
  54. fpu32_gt gt0(value, 'hc0200000, gt_neg); // more then -2.5
  55. fpu32_lt lt0(value, 'h40200000, lt_pos); // less then +2.5
  56. always_ff @(posedge clk) begin
  57. case (stage)
  58. hs_input: begin
  59. left.ack <= 1;
  60. if (left.ack && left.stb) begin
  61. value <= x;
  62. left.ack <= 0;
  63. stage <= hs_compare_1;
  64. end
  65. end
  66. hs_compare_1: begin
  67. // if less than -2.5 output 0
  68. if(~gt_neg) begin
  69. y <= 0;
  70. stage <= hs_output;
  71. end else
  72. // if in between -2.5 and 2.5
  73. if(gt_neg & lt_pos) begin
  74. in_stb <= 1;
  75. stage <= hs_compute_0;
  76. end else
  77. // if more than 2.5 ouput 1
  78. begin
  79. y <= 'h3f800000;
  80. stage <= hs_output;
  81. end
  82. end
  83. hs_compute_0: begin
  84. if (in_ack) begin
  85. in_stb <= 0;
  86. stage <= hs_compute_1;
  87. end
  88. end
  89. hs_compute_1: begin
  90. out_ack <= 1;
  91. if (out_ack && out_stb) begin
  92. y <= comp_result;
  93. out_ack <= 0;
  94. stage <= hs_output;
  95. end
  96. end
  97. hs_output: begin
  98. right.stb <= 1;
  99. if (right.stb && right.ack) begin
  100. right.stb <= 0;
  101. stage <= hs_input;
  102. end
  103. end
  104. endcase
  105. if (rst == 1) begin
  106. stage <= hs_input;
  107. left.ack <= 0;
  108. right.stb <= 0;
  109. y <= 0;
  110. end
  111. end
  112. endmodule : hard_sigmoid
  113. module hard_sigmoid_tb;
  114. reg rst, clk;
  115. reg [31:0] x;
  116. wire [31:0] y;
  117. abus_io left();
  118. abus_io right();
  119. hard_sigmoid sigmoid0(clk, rst, x, y, left, right);
  120. reg [31:0] test_mem [5000:0];
  121. initial $readmemh("scripts/sigmoid_test.hex", test_mem);
  122. initial forever #5 clk = ~clk;
  123. initial begin
  124. int fd, start, delta;
  125. fd = $fopen("scripts/sigmoid_result.hex", "w");
  126. if(!fd) $display("Failed to open file! %0d", fd);
  127. clk = 0;
  128. rst = 1;
  129. left.stb = 0;
  130. right.ack = 0;
  131. # 10;
  132. rst = 0;
  133. for (int i=0; i < $size(test_mem); i++) begin
  134. x = test_mem[i];
  135. left.stb = 1;
  136. wait(left.ack == 1);
  137. start = $time;
  138. #15;
  139. left.stb = 0;
  140. wait(right.stb == 1);
  141. right.ack = 1;
  142. delta = $time - start;
  143. #15;
  144. right.ack = 0;
  145. $fdisplay(fd, "%H %H %d", x, y, delta);
  146. end
  147. $fclose(fd);
  148. $finish();
  149. end
  150. endmodule : hard_sigmoid_tb