tb.vhd 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. use ieee.std_logic_textio.all;
  5. library std; -- for Printing
  6. use std.textio.all;
  7. use work.mem_pkg.all;
  8. use work.op_pkg.all;
  9. use work.core_pkg.all;
  10. use work.tb_util_pkg.all;
  11. entity tb is
  12. end entity;
  13. architecture bench of tb is
  14. constant CLK_PERIOD : time := 10 ns;
  15. signal clk : std_logic;
  16. signal res_n : std_logic := '0';
  17. signal stop : boolean := false;
  18. signal start : std_logic := '0';
  19. file input_file : text;
  20. file output_ref_file : text;
  21. subtype addr is std_logic_vector(REG_BITS-1 downto 0);
  22. subtype data is std_logic_vector(DATA_WIDTH-1 downto 0);
  23. type data_arr is array(0 to 400) of MEM_DATA_TYPE;
  24. type input_t is
  25. record
  26. stall : std_logic;
  27. flush : std_logic;
  28. pc_in : pc_type;
  29. op : exec_op_type;
  30. memop_in : mem_op_type;
  31. wbop_in : wb_op_type;
  32. reg_write_mem : reg_write_type;
  33. reg_write_wr : reg_write_type;
  34. end record;
  35. type output_t is
  36. record
  37. pc_old_out : pc_type;
  38. pc_new_out : pc_type;
  39. aluresult : data_type;
  40. zero : std_logic;
  41. wrdata : data_type;
  42. exec_op : exec_op_type;
  43. memop_out : mem_op_type;
  44. wbop_out : wb_op_type;
  45. end record;
  46. signal inp : input_t := (
  47. '0',
  48. '0',
  49. (others => '0'),
  50. EXEC_NOP,
  51. MEM_NOP,
  52. WB_NOP,
  53. (write => '0', reg => (others => '0'), data => (others => '0')),
  54. (write => '0', reg => (others => '0'), data => (others => '0'))
  55. );
  56. signal outp : output_t;
  57. impure function read_next_input(file f : text) return input_t is
  58. variable l : line;
  59. variable result : input_t;
  60. begin
  61. l := get_next_valid_line(f);
  62. result.stall := str_to_sl(l(1));
  63. l := get_next_valid_line(f);
  64. result.flush := str_to_sl(l(1));
  65. l := get_next_valid_line(f);
  66. result.pc_in := bin_to_slv(l.all, inp.pc_in'LENGTH);
  67. l := get_next_valid_line(f);
  68. result.op.aluop := str_to_alu_op(l.all);
  69. l := get_next_valid_line(f);
  70. result.op.alusrc1 := str_to_sl(l(1));
  71. l := get_next_valid_line(f);
  72. result.op.alusrc2 := str_to_sl(l(1));
  73. l := get_next_valid_line(f);
  74. result.op.alusrc3 := str_to_sl(l(1));
  75. l := get_next_valid_line(f);
  76. result.op.rs1 := bin_to_slv(l.all, inp.op.rs1'LENGTH);
  77. l := get_next_valid_line(f);
  78. result.op.rs2 := bin_to_slv(l.all, inp.op.rs2'LENGTH);
  79. l := get_next_valid_line(f);
  80. result.op.readdata1 := bin_to_slv(l.all, inp.op.readdata1'LENGTH);
  81. l := get_next_valid_line(f);
  82. result.op.readdata2 := bin_to_slv(l.all, inp.op.readdata2'LENGTH);
  83. l := get_next_valid_line(f);
  84. result.op.imm := bin_to_slv(l.all, inp.op.imm'LENGTH);
  85. l := get_next_valid_line(f);
  86. result.memop_in.branch := str_to_branch(l.all);
  87. l := get_next_valid_line(f);
  88. result.memop_in.mem.memread := str_to_sl(l(1));
  89. l := get_next_valid_line(f);
  90. result.memop_in.mem.memwrite := str_to_sl(l(1));
  91. l := get_next_valid_line(f);
  92. result.memop_in.mem.memtype := str_to_mem_op(l.all);
  93. l := get_next_valid_line(f);
  94. result.wbop_in.rd := bin_to_slv(l.all, inp.wbop_in.rd'LENGTH);
  95. l := get_next_valid_line(f);
  96. result.wbop_in.write := str_to_sl(l(1));
  97. l := get_next_valid_line(f);
  98. result.wbop_in.src := str_to_wbs_op(l.all);
  99. l := get_next_valid_line(f);
  100. result.reg_write_mem.write := str_to_sl(l(1));
  101. l := get_next_valid_line(f);
  102. result.reg_write_mem.reg := bin_to_slv(l.all, inp.reg_write_mem.reg'LENGTH);
  103. l := get_next_valid_line(f);
  104. result.reg_write_mem.data := bin_to_slv(l.all, inp.reg_write_mem.data'LENGTH);
  105. l := get_next_valid_line(f);
  106. result.reg_write_wr.write := str_to_sl(l(1));
  107. l := get_next_valid_line(f);
  108. result.reg_write_wr.reg := bin_to_slv(l.all, inp.reg_write_wr.reg'LENGTH);
  109. l := get_next_valid_line(f);
  110. result.reg_write_wr.data := bin_to_slv(l.all, inp.reg_write_wr.data'LENGTH);
  111. return result;
  112. end function;
  113. impure function read_next_output(file f : text) return output_t is
  114. variable l : line;
  115. variable result : output_t;
  116. begin
  117. l := get_next_valid_line(f);
  118. result.pc_old_out := bin_to_slv(l.all, outp.pc_old_out'LENGTH);
  119. l := get_next_valid_line(f);
  120. result.pc_new_out := bin_to_slv(l.all, outp.pc_new_out'LENGTH);
  121. l := get_next_valid_line(f);
  122. result.aluresult := bin_to_slv(l.all, outp.aluresult'LENGTH);
  123. l := get_next_valid_line(f);
  124. result.zero := str_to_sl(l(1));
  125. l := get_next_valid_line(f);
  126. result.wrdata := bin_to_slv(l.all, outp.wrdata'LENGTH);
  127. l := get_next_valid_line(f);
  128. result.exec_op.aluop := str_to_alu_op(l.all);
  129. l := get_next_valid_line(f);
  130. result.exec_op.alusrc1 := str_to_sl(l(1));
  131. l := get_next_valid_line(f);
  132. result.exec_op.alusrc2 := str_to_sl(l(1));
  133. l := get_next_valid_line(f);
  134. result.exec_op.alusrc3 := str_to_sl(l(1));
  135. l := get_next_valid_line(f);
  136. result.exec_op.rs1 := bin_to_slv(l.all, outp.exec_op.rs1'LENGTH);
  137. l := get_next_valid_line(f);
  138. result.exec_op.rs2 := bin_to_slv(l.all, outp.exec_op.rs2'LENGTH);
  139. l := get_next_valid_line(f);
  140. result.exec_op.readdata1 := bin_to_slv(l.all, outp.exec_op.readdata1'LENGTH);
  141. l := get_next_valid_line(f);
  142. result.exec_op.readdata2 := bin_to_slv(l.all, outp.exec_op.readdata2'LENGTH);
  143. l := get_next_valid_line(f);
  144. result.exec_op.imm := bin_to_slv(l.all, outp.exec_op.imm'LENGTH);
  145. l := get_next_valid_line(f);
  146. result.memop_out.branch := str_to_branch(l.all);
  147. l := get_next_valid_line(f);
  148. result.memop_out.mem.memread := str_to_sl(l(1));
  149. l := get_next_valid_line(f);
  150. result.memop_out.mem.memwrite := str_to_sl(l(1));
  151. l := get_next_valid_line(f);
  152. result.memop_out.mem.memtype := str_to_mem_op(l.all);
  153. l := get_next_valid_line(f);
  154. result.wbop_out.rd := bin_to_slv(l.all, outp.wbop_out.rd'LENGTH);
  155. l := get_next_valid_line(f);
  156. result.wbop_out.write := str_to_sl(l(1));
  157. l := get_next_valid_line(f);
  158. result.wbop_out.src := str_to_wbs_op(l.all);
  159. return result;
  160. end function;
  161. procedure check_output(output_ref : output_t) is
  162. variable passed : boolean;
  163. begin
  164. passed := (outp = output_ref);
  165. if passed then
  166. report "PASSED: " & lf
  167. & "** stall=" & to_string(inp.stall) & lf
  168. & "** flush=" & to_string(inp.flush) & lf
  169. & "** pc_in=" & to_string(inp.pc_in) & lf
  170. & "** op.aluop=" & to_string(inp.op.aluop) & lf
  171. & "** op.alusrc1=" & to_string(inp.op.alusrc1) & lf
  172. & "** op.alusrc2=" & to_string(inp.op.alusrc2) & lf
  173. & "** op.alusrc3=" & to_string(inp.op.alusrc3) & lf
  174. & "** op.rs1=" & to_string(inp.op.rs1) & lf
  175. & "** op.rs1=" & to_string(inp.op.rs2) & lf
  176. & "** op.readdata1=" & to_string(inp.op.readdata1) & lf
  177. & "** op.readdata2=" & to_string(inp.op.readdata2) & lf
  178. & "** op.imm=" & to_string(inp.op.imm) & lf
  179. & "** memop_in.branch=" & to_string(inp.memop_in.branch) & lf
  180. & "** memop_in.memread=" & to_string(inp.memop_in.mem.memread) & lf
  181. & "** memop_in.memwrite=" & to_string(inp.memop_in.mem.memwrite) & lf
  182. & "** memop_in.memtype=" & to_string(inp.memop_in.mem.memtype) & lf
  183. & "** wbop_in.rd=" & to_string(inp.wbop_in.rd) & lf
  184. & "** wbop_in.write=" & to_string(inp.wbop_in.write) & lf
  185. & "** wbop_in.src=" & to_string(inp.wbop_in.src) & lf
  186. & "** reg_write_mem.write=" & to_string(inp.reg_write_mem.write) & lf
  187. & "** reg_write_mem.reg=" & to_string(inp.reg_write_mem.reg) & lf
  188. & "** reg_write_mem.data=" & to_string(inp.reg_write_mem.data) & lf
  189. & "** reg_write_wr.write=" & to_string(inp.reg_write_wr.write) & lf
  190. & "** reg_write_wr.reg=" & to_string(inp.reg_write_wr.reg) & lf
  191. & "** reg_write_wr.data=" & to_string(inp.reg_write_wr.data) & lf
  192. severity note;
  193. else
  194. report "FAILED: " & lf
  195. & "** stall=" & to_string(inp.stall) & lf
  196. & "** flush=" & to_string(inp.flush) & lf
  197. & "** pc_in=" & to_string(inp.pc_in) & lf
  198. & "** op.aluop=" & to_string(inp.op.aluop) & lf
  199. & "** op.alusrc1=" & to_string(inp.op.alusrc1) & lf
  200. & "** op.alusrc2=" & to_string(inp.op.alusrc2) & lf
  201. & "** op.alusrc3=" & to_string(inp.op.alusrc3) & lf
  202. & "** op.rs1=" & to_string(inp.op.rs1) & lf
  203. & "** op.rs1=" & to_string(inp.op.rs2) & lf
  204. & "** op.readdata1=" & to_string(inp.op.readdata1) & lf
  205. & "** op.readdata2=" & to_string(inp.op.readdata2) & lf
  206. & "** op.imm=" & to_string(inp.op.imm) & lf
  207. & "** memop_in.branch=" & to_string(inp.memop_in.branch) & lf
  208. & "** memop_in.memread=" & to_string(inp.memop_in.mem.memread) & lf
  209. & "** memop_in.memwrite=" & to_string(inp.memop_in.mem.memwrite) & lf
  210. & "** memop_in.memtype=" & to_string(inp.memop_in.mem.memtype) & lf
  211. & "** wbop_in.rd=" & to_string(inp.wbop_in.rd) & lf
  212. & "** wbop_in.write=" & to_string(inp.wbop_in.write) & lf
  213. & "** wbop_in.src=" & to_string(inp.wbop_in.src) & lf
  214. & "** reg_write_mem.write=" & to_string(inp.reg_write_mem.write) & lf
  215. & "** reg_write_mem.reg=" & to_string(inp.reg_write_mem.reg) & lf
  216. & "** reg_write_mem.data=" & to_string(inp.reg_write_mem.data) & lf
  217. & "** reg_write_wr.write=" & to_string(inp.reg_write_wr.write) & lf
  218. & "** reg_write_wr.reg=" & to_string(inp.reg_write_wr.reg) & lf
  219. & "** reg_write_wr.data=" & to_string(inp.reg_write_wr.data) & lf;
  220. report lf & "** expected: pc_old_out=" & to_string(output_ref.pc_old_out) & ", actual: " & to_string(outp.pc_old_out) & lf
  221. & "** expected: pc_new_out=" & to_string(output_ref.pc_new_out) & ", actual: " & to_string(outp.pc_new_out) & lf
  222. & "** expected: aluresult=" & to_string(output_ref.aluresult) & ", actual: " & to_string(outp.aluresult) & lf
  223. & "** expected: zero=" & to_string(output_ref.zero) & ", actual: " & to_string(outp.zero) & lf
  224. & "** expected: wrdata=" & to_string(output_ref.wrdata) & ", actual: " & to_string(outp.wrdata) & lf
  225. & "** expected: exec_op.aluop=" & to_string(output_ref.exec_op.aluop) & ", actual: " & to_string(outp.exec_op.aluop) & lf
  226. & "** expected: exec_op.alusrc1=" & to_string(output_ref.exec_op.alusrc1) & ", actual: " & to_string(outp.exec_op.alusrc1) & lf
  227. & "** expected: exec_op.alusrc2=" & to_string(output_ref.exec_op.alusrc2) & ", actual: " & to_string(outp.exec_op.alusrc2) & lf
  228. & "** expected: exec_op.alusrc3=" & to_string(output_ref.exec_op.alusrc3) & ", actual: " & to_string(outp.exec_op.alusrc3) & lf
  229. & "** expected: exec_op.rs1=" & to_string(output_ref.exec_op.rs1) & ", actual: " & to_string(outp.exec_op.rs1) & lf
  230. & "** expected: exec_op.rs2=" & to_string(output_ref.exec_op.rs2) & ", actual: " & to_string(outp.exec_op.rs2) & lf
  231. & "** expected: exec_op.readdata1=" & to_string(output_ref.exec_op.readdata1) & ", actual: " & to_string(outp.exec_op.readdata1) & lf
  232. & "** expected: exec_op.readdata2=" & to_string(output_ref.exec_op.readdata2) & ", actual: " & to_string(outp.exec_op.readdata2) & lf
  233. & "** expected: exec_op.imm=" & to_string(output_ref.exec_op.imm) & ", actual: " & to_string(outp.exec_op.imm) & lf
  234. & "** expected: memop_out.branch=" & to_string(output_ref.memop_out.branch) & ", actual: " & to_string(outp.memop_out.branch) & lf
  235. & "** expected: memop_out.mem.memread=" & to_string(output_ref.memop_out.mem.memread) & ", actual: " & to_string(outp.memop_out.mem.memread) & lf
  236. & "** expected: memop_out.mem.memwrite=" & to_string(output_ref.memop_out.mem.memwrite) & ", actual: " & to_string(outp.memop_out.mem.memwrite) & lf
  237. & "** expected: memop_out.mem.memtype=" & to_string(output_ref.memop_out.mem.memtype) & ", actual: " & to_string(outp.memop_out.mem.memtype) & lf
  238. & "** expected: wbop_out.rd=" & to_string(output_ref.wbop_out.rd) & ", actual: " & to_string(outp.wbop_out.rd) & lf
  239. & "** expected: wbop_out.write=" & to_string(output_ref.wbop_out.write) & ", actual: " & to_string(outp.wbop_out.write) & lf
  240. & "** expected: wbop_out.src=" & to_string(output_ref.wbop_out.src) & ", actual: " & to_string(outp.wbop_out.src) & lf
  241. severity error;
  242. end if;
  243. end procedure;
  244. begin
  245. exec_inst : entity work.exec
  246. port map (
  247. clk => clk,
  248. res_n => res_n,
  249. stall => inp.stall,
  250. flush => inp.flush,
  251. -- from DEC
  252. op => inp.op,
  253. pc_in => inp.pc_in,
  254. -- to MEM
  255. pc_old_out => outp.pc_old_out,
  256. pc_new_out => outp.pc_new_out,
  257. aluresult => outp.aluresult,
  258. wrdata => outp.wrdata,
  259. zero => outp.zero,
  260. memop_in => inp.memop_in,
  261. memop_out => outp.memop_out,
  262. wbop_in => inp.wbop_in,
  263. wbop_out => outp.wbop_out,
  264. -- FWD
  265. exec_op => outp.exec_op,
  266. reg_write_mem => inp.reg_write_mem,
  267. reg_write_wr => inp.reg_write_wr
  268. );
  269. stimulus : process
  270. variable fstatus: file_open_status;
  271. begin
  272. res_n <= '0';
  273. wait until rising_edge(clk);
  274. res_n <= '1';
  275. file_open(fstatus, input_file, "testdata/input.txt", READ_MODE);
  276. wait until falling_edge(clk);
  277. wait for CLK_PERIOD/10;
  278. while not endfile(input_file) loop
  279. inp <= read_next_input(input_file);
  280. start <= '1';
  281. timeout(1, CLK_PERIOD);
  282. end loop;
  283. wait;
  284. end process;
  285. output_checker : process
  286. variable fstatus: file_open_status;
  287. variable output_ref : output_t;
  288. begin
  289. file_open(fstatus, output_ref_file, "testdata/output.txt", READ_MODE);
  290. wait until res_n = '1';
  291. wait until start = '1';
  292. while not endfile(output_ref_file) loop
  293. output_ref := read_next_output(output_ref_file);
  294. wait until falling_edge(clk);
  295. check_output(output_ref);
  296. wait until rising_edge(clk);
  297. end loop;
  298. stop <= true;
  299. wait;
  300. end process;
  301. generate_clk : process
  302. begin
  303. clk_generate(clk, CLK_PERIOD, stop);
  304. wait;
  305. end process;
  306. end architecture;