Advertisement
Guest User

Untitled

a guest
Apr 29th, 2016
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.31 KB | None | 0 0
  1. `timescale 1ns / 1ps
  2.  
  3.  
  4. /*
  5. * ALU for simple 8-bit CPU.
  6. */
  7.  
  8. module alu (input [7:0] a,b,
  9. input [3:0] opcode,
  10. output reg [7:0] y);
  11. /* Decode the instruction */
  12. always @*
  13. case (opcode)
  14. 4'h0 /* OR */: y <= a | b;
  15. 4'h1 /* AND */: y <= a & b;
  16. 4'h2 /* NOTA */: y <= ~a;
  17. 4'h3 /* XOR */: y <= a ^ b;
  18. 4'h4 /* ADD */: y <= a + b;
  19. 4'h5 /* SUB */: y <= a - b;
  20. 4'h6 /* RSHIFT1 */: y <= a >> 1;
  21. 4'h7 /* RSHIFTN */: y <= a >> b;
  22. default: y <= 8'bZ;
  23. endcase
  24. endmodule //alu
  25.  
  26. /*
  27. * Control Unit for simple 8-bit CPU.
  28. */
  29.  
  30. module control ( input clk, reset, interrupt,
  31. input [7:0] datamem_data, datamem_address, regfile_out1, regfile_out2, alu_out,
  32. output reg [3:0] alu_opcode,
  33. output reg [7:0] regfile_data, output [7:0] usermem_data,
  34. output reg [1:0] regfile_read1, regfile_read2, regfile_writereg,
  35. output reg [7:0] usermem_address, pc_jmpaddr,
  36. output reg rw, regfile_regwrite, pc_jump);
  37. /* Flags */
  38. reg [1:0] stage;
  39. reg [7:0] instruction_c;
  40. reg [7:0] instruction;
  41. reg [7:0] prevaddr;
  42. reg [7:0] umd;
  43.  
  44.  
  45. parameter STAGE1 = 0, STAGE2 = 1, RESET = 2, INTERRUPT=3;
  46.  
  47. assign usermem_data=rw?umd:8'bz;
  48.  
  49. reg is_onecyc, is_rts;
  50.  
  51. always @(*) begin
  52. if (stage==2'b00) begin
  53. instruction_c<=datamem_data;
  54. is_onecyc <= (datamem_data[7:4] <= 4'h7);
  55. is_rts <= (datamem_data == 4'hb);
  56. end
  57. end
  58.  
  59. always @(posedge clk)
  60. begin
  61. /* Check for reset*/
  62. if(reset == 1)
  63. begin
  64. stage <= 2'b10;
  65. end
  66.  
  67.  
  68. else if(interrupt == 1)
  69. begin
  70. stage <=2'b11;
  71. end
  72.  
  73.  
  74. /* Stage 1: Fetch instruction, execute it in case it does not require an operand: */
  75.  
  76. case (stage)
  77. STAGE1:
  78. begin
  79. // $display("Stage 1!");
  80. pc_jump <= 0;
  81. rw <=0 ;
  82. instruction <= datamem_data;
  83. if (is_onecyc)
  84. begin
  85. // $display("No-Operand instruction will be executed!");
  86. rw <= 0;
  87. regfile_regwrite <= 1;
  88. regfile_read1 <= instruction_c[3:2];
  89. regfile_read2 <= instruction_c[1:0];
  90. alu_opcode <= instruction_c[7:4];
  91. regfile_writereg <= instruction_c[1:0];
  92. regfile_data <= alu_out;
  93. stage <= 0;
  94. end
  95.  
  96. else if (is_onecyc==0)
  97. if (is_rts) /* RTS */
  98. begin
  99. pc_jump <= 1;
  100. pc_jmpaddr <= prevaddr;
  101. stage <= 0;
  102. end
  103.  
  104. else
  105. stage <= 1;
  106. end
  107.  
  108. STAGE2:
  109. begin
  110. // $display("Stage 2!");
  111.  
  112. case (instruction_c[7:4])
  113. 4'h8 /* LD */:
  114. begin
  115. rw <= 0;
  116. regfile_writereg <= instruction[1:0];
  117. regfile_regwrite <= 1;
  118. regfile_data <= datamem_data;
  119. end
  120. 4'h9 /* JMP */:
  121. begin
  122. rw <= 0;
  123. pc_jump <= 1;
  124. pc_jmpaddr <= datamem_data;
  125. end
  126. 4'ha /* CALL */:
  127. begin
  128. rw <= 0;
  129. prevaddr <= datamem_address + 1;
  130. pc_jump <= 1;
  131. pc_jmpaddr <= datamem_data;
  132. end
  133. 4'hc /* BEQ */:
  134. begin
  135. rw <= 0;
  136. regfile_regwrite <= 0;
  137. regfile_read1 <= instruction[3:2];
  138. regfile_read2 <= instruction[1:0];
  139. if(regfile_out1 == regfile_out2)
  140. begin
  141. prevaddr <= datamem_address + 1;
  142. pc_jump <= 1;
  143. pc_jmpaddr <= datamem_data;
  144. end
  145. end
  146.  
  147. 4'hd /* BNE */:
  148. begin
  149. rw <= 0;
  150. regfile_regwrite <= 0;
  151. regfile_read1 <= instruction[3:2];
  152. regfile_read2 <= instruction[1:0];
  153. if(regfile_out1 != regfile_out2)
  154. begin
  155. prevaddr <= datamem_address + 1;
  156. pc_jump <= 1;
  157. pc_jmpaddr <= datamem_data;
  158. end
  159. end
  160.  
  161.  
  162. 4'he /* ST */:
  163. begin
  164. rw <= 1;
  165. usermem_address <= datamem_data;
  166. regfile_read1 <= instruction[3:2];
  167. umd <= regfile_out1;
  168. end
  169.  
  170. 4'hf /* LDUMEM */:
  171. begin
  172. rw <= 0;
  173. usermem_address <= datamem_data;
  174. regfile_writereg <= instruction[1:0];
  175. regfile_regwrite <= 1;
  176. regfile_data <= usermem_data;
  177. end
  178.  
  179.  
  180. endcase
  181. stage <= 2'h0;
  182. end
  183.  
  184.  
  185. RESET:
  186. begin
  187. {instruction, alu_opcode, regfile_data, umd, usermem_address} <= 8'b0;
  188. {regfile_read1, regfile_read2, regfile_writereg} <= 3'b0;
  189. {rw, regfile_regwrite, pc_jump} <= 1'b0;
  190. stage <= 2'b0;
  191. end
  192.  
  193.  
  194. INTERRUPT:
  195. begin
  196. prevaddr <= datamem_address;
  197. pc_jump <= 1;
  198. pc_jmpaddr <= 8'hfe;
  199. end
  200.  
  201. endcase
  202.  
  203. end
  204.  
  205.  
  206.  
  207.  
  208.  
  209. /* Stage 2: Fetch the operand and execute the relevant instruction: */
  210.  
  211. endmodule //control
  212.  
  213.  
  214. module pc(input clk, reset, jump,
  215. input [7:0] jmpaddr,
  216. output reg[7:0] data);
  217.  
  218. always @(posedge clk) begin
  219. if (reset == 1)
  220. data <= 8'b0;
  221. else if (reset == 0)
  222. begin
  223. if (jump == 1)
  224. data <= jmpaddr;
  225. else if (jump == 0)
  226. data <= data + 1;
  227. end
  228. end
  229. endmodule //pc
  230.  
  231.  
  232.  
  233.  
  234. /*
  235. * Register file for simple 8-bit CPU.
  236. */
  237.  
  238. module regfile (input [1:0] readreg1, readreg2, sreadreg1, sreadreg2, writereg,
  239. input [7:0] data,
  240. input clk, clr, regwrite,
  241. output [7:0] read1, read2, sread1, sread2);
  242. reg [7:0] registerfile [3:0];
  243. reg [7:0] storeregisterfile [3:0];
  244. integer i;
  245.  
  246. always @(negedge clk) begin
  247. if(regwrite == 1)
  248. begin
  249. registerfile[writereg] <= data;
  250. storeregisterfile[writereg] <= data;
  251.  
  252. end
  253. if(clr == 1)
  254. begin
  255. for(i = 0; i <= 3; i = i + 1)
  256. begin
  257. registerfile[i] <= 8'b0;
  258. storeregisterfile[i] <= 8'b0;
  259. end
  260. end
  261. end
  262. assign sread1 = storeregisterfile[sreadreg1];
  263. assign sread2 = storeregisterfile[sreadreg2];
  264. assign read1 = registerfile[sreadreg1];
  265. assign read2 = registerfile[sreadreg2];
  266.  
  267. endmodule //regfile
  268.  
  269.  
  270.  
  271. module cpu(input clk, reset, interrupt,
  272. input [7:0] datamem_data,
  273. inout [7:0] usermem_data,
  274. output [7:0] datamem_address, usermem_address,
  275. output rw);
  276. wire [1:0] regfile_read1, regfile_read2, regfile_writereg;
  277. wire [7:0] pc_jumpaddr, regfile_data, regfile_out1, regfile_out2;
  278. wire [7:0] alu_out;
  279. wire [3:0] alu_opcode;
  280. wire pc_jump;
  281. wire regfile_regwrite;
  282. pc pc0(clk, reset, pc_jump, pc_jumpaddr, datamem_address);
  283. regfile reg0(regfile_read1, regfile_read2, regfile_writereg,
  284. regfile_data, clk, reset, regfile_regwrite,
  285. regfile_out1, regfile_out2);
  286. alu alu0(regfile_out1, regfile_out2, alu_opcode, alu_out);
  287. control cntrl0(clk, reset, interrupt, datamem_data, datamem_address, regfile_out1, regfile_out2,
  288. alu_out, alu_opcode,
  289. regfile_data, usermem_data, regfile_read1, regfile_read2,
  290. regfile_writereg, usermem_address,
  291. pc_jumpaddr, rw, regfile_regwrite,
  292. pc_jump);
  293. endmodule //cpu
  294.  
  295. /*
  296. * Testbench for simple 8-bit CPU.
  297. */
  298.  
  299. // Added small program memory for simulation
  300. module programmem(input [7:0] pgmaddr, output [7:0] pgmdata);
  301. reg [7:0] pmemory[255:0];
  302. assign pgmdata=pmemory[pgmaddr];
  303.  
  304. initial
  305. begin
  306. pmemory[0]=8'h80; // load from next location
  307. pmemory[1]=8'hAA;
  308. pmemory[2]=8'h20; // NOT
  309. pmemory[3]=8'h90; // jump to 2 (or 0 to reload)
  310. pmemory[4]=8'h02;
  311. end
  312. endmodule
  313.  
  314. // Simple user memory for simulation
  315. module usermem(input clk, input [7:0] uaddr, inout [7:0] udata, input rw);
  316. reg [7:0] umemory[255:0];
  317. assign udata=rw?8'bz:umemory[uaddr];
  318. always @(negedge clk)
  319. if (rw==1) umemory[uaddr]<=udata;
  320.  
  321. initial
  322. begin
  323. umemory[0]=8'h00;
  324. umemory[1]=8'h33;
  325. umemory[2]=8'hAA;
  326. end
  327. endmodule
  328.  
  329. module cpu_tb;
  330. reg clk, reset, interrupt;
  331. wire [7:0] datamem_data, usermem_data, datamem_address, usermem_address, idata;
  332. wire rw;
  333. programmem pgm(datamem_address,idata);
  334. usermem umem(clk, usermem_address,usermem_data,rw);
  335. cpu dut0(clk, reset, interrupt, idata, usermem_data,
  336. datamem_address, usermem_address, rw);
  337. initial
  338. begin
  339. $display("NopCPU testbench. All waveforms will be dumped to the dump.vcd file.");
  340. clk = 1'b0;
  341. reset = 1'b1;
  342. interrupt = 1'b0;
  343. repeat(4) #10 clk = !clk;
  344. reset = 1'b0;
  345. end
  346. always
  347. #1 clk = !clk;
  348. //always
  349. //#20 interrupt = ~interrupt;
  350. initial
  351. #5000 $finish;
  352. endmodule //cpu_tb
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement