pic.v.txt
上传用户:saul_905
上传日期:2013-11-27
资源大小:184k
文件大小:67k
源码类别:

VHDL/FPGA/Verilog

开发平台:

Visual C++

  1. // 
  2. // SYNTHETIC PIC 2.0                                          4/23/98
  3. //
  4. //    This is a synthesizable Microchip 16C57 compatible
  5. //    microcontroller.  This core is not intended as a high fidelity model of
  6. //    the PIC, but simply a way to offer a simple processor core to people
  7. //    familiar with the PIC who also have PIC tools.  
  8. //
  9. //    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
  10. //    piccpu.v   -   top-level synthesizable module
  11. //    picregs.v  -   register file instantiated under piccpu
  12. //    picalu.v   -   ALU instantiated under piccpu
  13. //    picidec.v  -   Instruction Decoder instantiated under piccpu
  14. //    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
  15. //                   into the Verilog $readmemh compatible file
  16. //    test*.asm  -   (note the wildcard..) Several test programs used
  17. //                   to help debug the verilog.  I used MPLAB and the simulator
  18. //                   to develop these programs and get the expected results.
  19. //                   Then, I ran them on Verilog-XL where they appeared to
  20. //                   match.
  21. //
  22. //    Copyright, Tom Coonan, '97.
  23. //    Use freely, but not for resale as is.  You may use this in your
  24. //    own projects as desired.  Just don't try to sell it as is!
  25. //
  26. //
  27. module picalu (
  28.    op,
  29.    a,
  30.    b,
  31.    y,
  32.    cin,
  33.    cout,
  34.    zout
  35. );
  36. input  [3:0] op; // ALU Operation
  37. input  [7:0] a; // 8-bit Input a
  38. input  [7:0] b; // 8-bit Input b
  39. output [7:0] y; // 8-bit Output
  40. input cin;
  41. output cout;
  42. output zout;
  43. // Reg declarations for outputs
  44. reg cout;
  45. reg zout;
  46. reg [7:0] y;
  47. // Internal declarations
  48. reg addercout; // Carry out straight from the adder itself.
  49.  
  50. parameter [3:0] ALUOP_ADD        = 4'b0000;
  51. parameter [3:0] ALUOP_SUB        = 4'b1000;
  52. parameter [3:0] ALUOP_AND        = 4'b0001;
  53. parameter [3:0] ALUOP_OR         = 4'b0010;
  54. parameter [3:0] ALUOP_XOR        = 4'b0011;
  55. parameter [3:0] ALUOP_COM        = 4'b0100;
  56. parameter [3:0] ALUOP_ROR        = 4'b0101;
  57. parameter [3:0] ALUOP_ROL        = 4'b0110;
  58. parameter [3:0] ALUOP_SWAP       = 4'b0111;
  59. always @(a or b or cin or op) begin
  60.    case (op) // synopsys full_case parallel_case
  61.       ALUOP_ADD:  {addercout,  y}  <= a + b;
  62.       ALUOP_SUB:  {addercout,  y}  <= a - b; // Carry out is really "borrow"
  63.       ALUOP_AND:  {addercout,  y}  <= {1'b0, a & b};
  64.       ALUOP_OR:   {addercout,  y}  <= {1'b0, a | b};
  65.       ALUOP_XOR:  {addercout,  y}  <= {1'b0, a ^ b};
  66.       ALUOP_COM:  {addercout,  y}  <= {1'b0, ~a};
  67.       ALUOP_ROR:  {addercout,  y}  <= {a[0], cin, a[7:1]};
  68.       ALUOP_ROL:  {addercout,  y}  <= {a[7], a[6:0], cin};
  69.       ALUOP_SWAP: {addercout,  y}  <= {1'b0, a[3:0], a[7:4]};
  70.       default:    {addercout,  y}  <= {1'b0, 8'h00};
  71.    endcase
  72. end
  73. always @(y)
  74.    zout <= (y == 8'h00);
  75. always @(addercout or op)
  76.    if (op == ALUOP_SUB) cout <= ~addercout; // Invert adder's carry to get borrow
  77.    else                 cout <=  addercout;
  78.       
  79. endmodule
  80. // 
  81. // SYNTHETIC PIC 2.0                                          4/23/98
  82. //
  83. //    This is a synthesizable Microchip 16C57 compatible
  84. //    microcontroller.  This core is not intended as a high fidelity model of
  85. //    the PIC, but simply a way to offer a simple processor core to people
  86. //    familiar with the PIC who also have PIC tools.  
  87. //
  88. //    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
  89. //    piccpu.v   -   top-level synthesizable module
  90. //    picregs.v  -   register file instantiated under piccpu
  91. //    picalu.v   -   ALU instantiated under piccpu
  92. //    picidec.v  -   Instruction Decoder instantiated under piccpu
  93. //    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
  94. //                   into the Verilog $readmemh compatible file
  95. //    test*.asm  -   (note the wildcard..) Several test programs used
  96. //                   to help debug the verilog.  I used MPLAB and the simulator
  97. //                   to develop these programs and get the expected results.
  98. //                   Then, I ran them on Verilog-XL where they appeared to
  99. //                   match.
  100. //
  101. //    Copyright, Tom Coonan, '97.
  102. //    Use freely, but not for resale as is.  You may use this in your
  103. //    own projects as desired.  Just don't try to sell it as is!
  104. //
  105. //
  106. module piccpu (
  107.    clk,
  108.    reset,
  109.    paddr,
  110.    pdata,
  111.    portain,
  112.    portbout,
  113.    portcout,
  114.    
  115.    debugw,
  116.    debugpc,
  117.    debuginst,
  118.    debugstatus
  119. );
  120. input clk;
  121. input reset;
  122. output [8:0] paddr;
  123. input  [11:0] pdata;
  124. input  [7:0] portain;
  125. output [7:0] portbout;
  126. output [7:0] portcout;
  127. output [7:0] debugw;
  128. output [8:0] debugpc;
  129. output [11:0] debuginst;
  130. output [7:0] debugstatus;
  131. // Register declarations for outputs
  132. reg [8:0] paddr;
  133. reg [7:0] portbout;
  134. reg [7:0] portcout;
  135. // This should be set to the ROM location where our restart vector is.
  136. // As set here, we have 512 words of program space.
  137. //
  138. parameter RESET_VECTOR = 9'h1FF;
  139. parameter INDF_ADDRESS = 3'h0,
  140. TMR0_ADDRESS = 3'h1,
  141. PCL_ADDRESS = 3'h2,
  142. STATUS_ADDRESS = 3'h3,
  143. FSR_ADDRESS = 3'h4,
  144. PORTA_ADDRESS = 3'h5,
  145. PORTB_ADDRESS = 3'h6,
  146. PORTC_ADDRESS = 3'h7;
  147. // Experimental custom peripheral, "Lil Adder (a 4-bit adder)" is at this address.
  148. //
  149. parameter EXPADDRESS_LILADDER = 7'h7F;
  150. // *********  Special internal registers
  151. // Instruction Register
  152. reg  [11:0] inst;
  153. // Program Counter
  154. reg  [8:0] pc;
  155. reg  [8:0] pcplus1; // Output of the pc incrementer.
  156. // Stack Registers and Stack "levels" register.
  157. reg [ 1:0] stacklevel;
  158. reg [ 8:0] stack1;
  159. reg [ 8:0] stack2;
  160. // W Register
  161. reg [ 7:0] w;
  162. // The STATUS register (#3) is 8 bits wide, however, we only currently use 2 bits
  163. // of it; the C and Z bit.
  164. //
  165. // bit 0  -  C
  166. // bit 2  -  Z
  167. //
  168. reg [ 7:0] status;
  169. // The FSR register is the pointer register used for Indirect addressing (e.g. using INDF).
  170. reg  [ 7:0] fsr;
  171. // Timer 0
  172. reg  [ 7:0] tmr0;
  173. reg  [ 7:0] prescaler;
  174. // Option Register
  175. reg [7:0] option;
  176. // Tristate Control registers. We do not neccessarily support bidirectional ports, but
  177. //    will save a place for these registers and the TRIS instruction.  Use for debug.
  178. reg [7:0] trisa;
  179. reg [7:0] trisb;
  180. reg [7:0] trisc;
  181. // I/O Port registers
  182. //
  183. reg [7:0] porta; // Input PORT
  184. reg [7:0] portb; // Output PORT
  185. reg [7:0] portc; // Output PORT
  186. // ********** Instruction Related signals ******
  187. reg  skip;  // When HI force a NOP (all zeros) into inst
  188. reg  [2:0] pcinsel;
  189. // Derive special sub signals from inst register
  190. wire [ 7:0] k;
  191. wire [ 4:0] fsel;
  192. wire [ 8:0] longk;
  193. wire d;
  194. wire [ 2:0] b;
  195. // ********** File Address ************
  196. //
  197. // This is the 7-bit Data Address that includes the lower 5-bit fsel, the
  198. // FSR bits and any indirect addressing.
  199. // Use this bus to address the Register File as well as all special registers, etc.
  200. //
  201. reg [6:0] fileaddr;
  202. // Address Selects
  203. reg specialsel;
  204. reg regfilesel;
  205. reg expsel;
  206. // ******  Instruction Decoder Outputs **************
  207. // Write enable for the actual ZERO and CARRY bits within the status register.
  208. // Generated by the Instruction Decoder.
  209. //
  210. wire [1:0] aluasel;
  211. wire [1:0] alubsel;
  212. wire [3:0] aluop;
  213. wire zwe;
  214. wire cwe;
  215. wire isoption;
  216. wire istris;
  217. wire fwe; // High if any "register" is being written to at all.
  218. wire wwe; // Write Enable for the W register.  Produced by Instruction Decoder.
  219. // *************  Internal Busses, mux connections, etc.  ********************
  220. // Bit decoder bits.  
  221. reg [7:0] bd; // Final decoder value after any polarity inversion.
  222. reg [7:0] bdec; // e.g. "Bit Decoded"
  223. // Data in and out of the and out of the register file
  224. //
  225. reg [7:0] regfilein; // Input into Register File, is connected to the dbus.
  226. wire [7:0] regfileout; // Path leaving the register file, goes to SBUS Mux
  227. reg regfilewe; // Write Enable
  228. reg regfilere; // Read Enable
  229. //
  230. // The dbus (Destination Bus) comes out of the ALU.  It is available to all
  231. // writable registers.
  232. //
  233. // The sbus (Source Bus) comes from all readable registers as well as the output
  234. // of the Register File.  It is one of the primary inputs into the ALU muxes.
  235. //
  236. // The ebus (Expansion Bus) comes from any of our custom modules.  They must
  237. // all coordinate to place whoever's data onto ebus.
  238. //
  239. reg  [7:0] dbus;
  240. reg  [7:0] sbus;
  241. reg  [7:0] ebus;
  242. // ALU Signals
  243. //
  244. reg  [7:0] alua;
  245. reg  [7:0] alub;
  246. wire [7:0] aluout;
  247. wire  alucin;
  248. wire alucout;
  249. wire        aluz;
  250. // ALU A and B mux selects.
  251. //
  252. parameter [1:0] ALUASEL_W = 2'b00,
  253. ALUASEL_SBUS = 2'b01,
  254. ALUASEL_K = 2'b10,
  255. ALUASEL_BD = 2'b11;
  256. parameter [1:0] ALUBSEL_W = 2'b00,
  257. ALUBSEL_SBUS = 2'b01,
  258. ALUBSEL_K = 2'b10,
  259. ALUBSEL_1 = 2'b11;
  260. // ALU Operation codes.
  261. //
  262. parameter  [3:0] ALUOP_ADD  = 4'b0000;
  263. parameter  [3:0] ALUOP_SUB  = 4'b1000;
  264. parameter  [3:0] ALUOP_AND  = 4'b0001;
  265. parameter  [3:0] ALUOP_OR   = 4'b0010;
  266. parameter  [3:0] ALUOP_XOR  = 4'b0011;
  267. parameter  [3:0] ALUOP_COM  = 4'b0100;
  268. parameter  [3:0] ALUOP_ROR  = 4'b0101;
  269. parameter  [3:0] ALUOP_ROL  = 4'b0110;
  270. parameter  [3:0] ALUOP_SWAP = 4'b0111;
  271. // Instantiate each of our subcomponents
  272. //
  273. picregs  regs (
  274.    .clk (clk), 
  275.    .reset (reset),
  276.    .we   (regfilewe),
  277.    .re (regfilere),
  278.    .bank (fileaddr[6:5]), 
  279.    .location (fileaddr[4:0]),
  280.    .din (regfilein), 
  281.    .dout (regfileout)
  282. );
  283. // Instatiate the ALU.
  284. //
  285. picalu   alu  (
  286.    .op         (aluop), 
  287.    .a          (alua), 
  288.    .b          (alub),
  289.    .y          (aluout),
  290.    .cin        (status[0]), 
  291.    .cout       (alucout), 
  292.    .zout       (aluz)
  293. );
  294. // Instantiate the Instruction Decoder.  This is really just a lookup table.
  295. // Given the instruction, generate all the signals we need.  
  296. //
  297. // For example, each instruction implies a specific ALU operation.  Some of
  298. // these are obvious such as the ADDW uses an ADD alu op.  Less obvious is
  299. // that a mov instruction uses an OR op which lets us do a simple copy.
  300. // 
  301. // Data has to funnel through the ALU, which sometimes makes for contrived
  302. // ALU ops.
  303. //
  304. picidec  idec (
  305.    .inst     (inst),
  306.    .aluasel  (aluasel),
  307.    .alubsel  (alubsel),
  308.    .aluop    (aluop),
  309.    .wwe      (wwe),
  310.    .fwe      (fwe),
  311.    .zwe      (zwe),
  312.    .cwe      (cwe),
  313.    .bdpol    (bdpol),
  314.    .option   (isoption),
  315.    .tris     (istris)
  316. );
  317. // *********** Debug ****************
  318. assign debugw = w;
  319. assign debugpc = pc;
  320. assign debuginst = inst;
  321. assign debugstatus = status;
  322. // *********** REGISTER FILE Addressing ****************
  323. //
  324. // We implement the following:
  325. //    - The 5-bit fsel address is within a "BANK" which is 32 bytes.
  326. //    - The FSR bits 6:5 are the BANK select, so there are 4 BANKS, a 
  327. //      total of 128 bytes.  Minus the 8 special registers, that's 
  328. //      really 120 bytes.
  329. //    - The INDF register is for indirect addressing.  Referencing INDF
  330. //      uses FSR as the pointer.  Therefore, using INDF/FSR you address
  331. //      7-bits of memory.
  332. // We DO NOT currently implement the PAGE for program (e.g. STATUS register
  333. // bits 6:5)
  334. //
  335. // The fsel address *may* be zero in which case, we are to do indirect
  336. // addressing, using FSR register as the 8-bit pointer.
  337. //
  338. // Otherwise, use the 5-bits of FSEL (from the Instruction itself) and 
  339. // 2 bank bits from the FSR register (bits 6:5).
  340. //
  341. always @(fsel or fsr) begin
  342.    if (fsel == INDF_ADDRESS) begin
  343.       // The INDEX register is addressed.  There really is no INDEX register.
  344.       // Use the FSR as an index, e.g. the FSR contents are the fsel.
  345.       //
  346.       fileaddr <= fsr[6:0];
  347.    end
  348.    else begin
  349.       // Use FSEL field and status bank select bits
  350.       //
  351.       fileaddr <= {fsr[6:5], fsel};
  352.    end
  353. end
  354. // Write Enable to Register File.  
  355. // Assert this when the general fwe (write enable to *any* register) is true AND Register File
  356. //    address range is specified.
  357. //  
  358. always @(regfilesel or fwe)
  359.    regfilewe <= regfilesel & fwe;
  360. // Read Enable (this if nothing else, helps in debug.)
  361. // Assert if Register File address range is specified AND the ALU is actually using some
  362. //    data off the SBUS.
  363. //   
  364. always @(regfilesel or aluasel or alubsel)
  365.    regfilere <= regfilesel & ((aluasel == ALUASEL_SBUS) | (alubsel == ALUBSEL_SBUS));
  366. // *********** Address Decodes **************
  367. //
  368. // Generate 3 selects: specialsel, regfilesel and expsel
  369. always @(fileaddr) begin
  370.    casex (fileaddr)
  371.       7'bXX00XXX: // The SPECIAL Registers are lower 8 addresses, in ALL BANKS
  372.          begin
  373.             specialsel <= 1'b1;
  374.             regfilesel <= 1'b0;
  375.             expsel <= 1'b0;
  376.          end
  377.       7'b1111111: // EXPANSION Registers are the top (1) addresses
  378.          begin
  379.             specialsel <= 1'b0;
  380.             regfilesel <= 1'b0;
  381.             expsel <= 1'b1;
  382.          end
  383.       default:  // Anything else must be in the Register File
  384.          begin
  385.             specialsel <= 1'b0;
  386.             regfilesel <= 1'b1;
  387.             expsel <= 1'b0;
  388.          end
  389.    endcase
  390. end
  391.   
  392. // *********** SBUS **************
  393. // The sbus (Source Bus) is the output of a multiplexor that takes
  394. // inputs from the Register File, and all other special registers
  395. // and input ports.  The Source Bus then, one of the inputs to the ALU
  396. // First MUX selects from all the special regsiters
  397. //
  398. always @(fsel or fsr or tmr0 or pc or status
  399.          or porta or portb or portc or regfileout or ebus
  400.          or specialsel or regfilesel or expsel) begin
  401.          
  402.    // For our current mix of registers and peripherals, only the first 8 addresses
  403.    // are "special" registers (e.g. not in the Register File).  As more peripheral
  404.    // registers are added, they must be muxed into this MUX as well.
  405.    //
  406.    // We currently prohibit tristates.
  407.    //
  408.    //
  409.    if (specialsel) begin
  410.       // Special register
  411.       case (fsel[2:0]) // synopsys parallel_case full_case
  412.          3'h0: sbus <= fsr;
  413.          3'h1: sbus <= tmr0;
  414.          3'h2: sbus <= pc[7:0];
  415.          3'h3: sbus <= status;
  416.          3'h4: sbus <= fsr;
  417.          3'h5: sbus <= porta; // PORTA is an input-only port
  418.          3'h6: sbus <= portb; // PORTB is an output-only port
  419.          3'h7: sbus <= portc; // PORTC is an output-only port
  420.       endcase
  421.    end
  422.    else begin
  423.       //
  424.       // Put whatever address equation is neccessary here.  Remember to remove unnecessary
  425.       // memory elements from Register File (picregs.v).  It'll still work, but they'd be
  426.       // wasted flip-flops.
  427.       //
  428.       if (expsel) begin
  429.          sbus <= ebus;
  430.       end
  431.       else begin
  432.          if (regfilesel) begin
  433.             // Final Priority is Choose the register file
  434.             sbus <= regfileout;
  435.          end
  436.          else begin
  437.             sbus <= 8'h00;
  438.          end
  439.       end
  440.    end
  441. end
  442. // ************** DBUS ******
  443. //  The Destination bus is just the output of the ALU.
  444. //
  445. always @(aluout)
  446.    dbus <= aluout;
  447. always @(dbus)
  448.    regfilein <= dbus;
  449.    
  450. // Drive the ROM address bus straight from the PC
  451. //
  452. always @(pc)
  453.    paddr = pc;
  454. // Define sub-signals out of inst
  455. //
  456. assign k =     inst[7:0];
  457. assign fsel  = inst[4:0];
  458. assign longk = inst[8:0];
  459. assign d     = inst[5];
  460. assign b     = inst[7:5];
  461. // Bit Decoder.
  462. //
  463. // Simply take the 3-bit b field in the PIC instruction and create the
  464. // expanded 8-bit decoder field, which is used as a mask.
  465. //
  466. always @(b) begin
  467.    case (b)
  468.       3'b000: bdec <= 8'b00000001;
  469.       3'b001: bdec <= 8'b00000010;
  470.       3'b010: bdec <= 8'b00000100;
  471.       3'b011: bdec <= 8'b00001000;
  472.       3'b100: bdec <= 8'b00010000;
  473.       3'b101: bdec <= 8'b00100000;
  474.       3'b110: bdec <= 8'b01000000;
  475.       3'b111: bdec <= 8'b10000000;
  476.    endcase
  477. end
  478. always @(bdec or bdpol)
  479.    bd <= bdec ^ bdpol;
  480. // Instruction regsiter usually get the ROM data as its input, but
  481. // sometimes for branching, the skip signal must cause a NOP.
  482. //
  483. always @(posedge clk) begin
  484.    if (reset) begin
  485.       inst <= 12'h000;
  486.    end
  487.    else begin
  488.       if (skip == 1'b1) begin
  489.          inst <= 12'b000000000000; // FORCE NOP
  490.       end
  491.       else begin
  492.          inst <= pdata;
  493.       end
  494.    end
  495. end
  496. // SKIP signal.
  497. //
  498. // We want to insert the NOP instruction for the following conditions:
  499. //    GOTO,CALL and RETLW instructions (All have inst[11:10] = 2'b10
  500. //    BTFSS instruction when aluz is HI  (
  501. //    BTFSC instruction when aluz is LO
  502. //
  503. always @(inst or aluz) begin
  504.    casex ({inst, aluz})
  505.       13'b10??_????_????_?:    // A GOTO, CALL or RETLW instructions
  506.          skip <= 1'b1;
  507.          
  508.       13'b0110_????_????_1:    // BTFSC instruction and aluz == 1
  509.          skip <= 1'b1;
  510.       13'b0111_????_????_0:    // BTFSS instruction and aluz == 0
  511.          skip <= 1'b1;
  512.       
  513.       13'b0010_11??_????_1:    // DECFSZ instruction and aluz == 1
  514.          skip <= 1'b1;
  515.       13'b0011_11??_????_1:    // INCFSZ instruction and aluz == 1
  516.          skip <= 1'b1;
  517.       default:
  518.          skip <= 1'b0;
  519.    endcase
  520. end
  521. // 4:1 Data MUX into alua
  522. //
  523. //
  524. always @(aluasel or w or sbus or k or bd) begin
  525.    case (aluasel)
  526.       2'b00: alua <= w;
  527.       2'b01: alua <= sbus;
  528.       2'b10: alua <= k;
  529.       2'b11: alua <= bd;
  530.    endcase
  531. end
  532. // 4:1 Data MUX into alub
  533. //
  534. //
  535. always @(alubsel or w or sbus or k) begin
  536.    case (alubsel)
  537.       2'b00: alub <= w;
  538.       2'b01: alub <= sbus;
  539.       2'b10: alub <= k;
  540.       2'b11: alub <= 8'b00000001;
  541.    endcase
  542. end
  543. // W Register
  544. always @(posedge clk) begin
  545.    if (reset) begin
  546.       w <= 8'h00;
  547.    end
  548.    else begin
  549.       if (wwe) begin
  550.          w <= dbus;
  551.       end
  552.    end   
  553. end
  554. // ************ Writes to various Special Registers (fsel between 0 and 7)
  555. // INDF Register (Register #0)
  556. //
  557. //    Not a real register.  This is the Indirect Addressing mode register.
  558. //    See the regfileaddr logic.
  559. // TMR0 Register (Register #1)
  560. //
  561. //    Timer0 is currently only a free-running timer clocked by the main system clock.
  562. //
  563. always @(posedge clk) begin
  564.    if (reset) begin
  565.       tmr0 <= 8'h00;
  566.    end
  567.    else begin
  568.       // See if the status register is actually being written to
  569.       if (fwe & specialsel & (fsel == TMR0_ADDRESS)) begin
  570.          // Yes, so just update the register from the dbus
  571.          tmr0 <= dbus;
  572.       end
  573.       else begin
  574.          // Mask off the prescaler value based on desired divide ratio.
  575.          // Whenever this is zero, then that is our divided pulse.  Increment
  576.          // the final timer value when it's zero.
  577.          //
  578.          case (option[2:0]) // synopsys parallel_case full_case
  579.             3'b000: if (~|(prescaler & 8'b00000001)) tmr0 <= tmr0 + 1;
  580.             3'b001: if (~|(prescaler & 8'b00000011)) tmr0 <= tmr0 + 1;
  581.             3'b010: if (~|(prescaler & 8'b00000111)) tmr0 <= tmr0 + 1;
  582.             3'b011: if (~|(prescaler & 8'b00001111)) tmr0 <= tmr0 + 1;
  583.             3'b100: if (~|(prescaler & 8'b00011111)) tmr0 <= tmr0 + 1;
  584.             3'b101: if (~|(prescaler & 8'b00111111)) tmr0 <= tmr0 + 1;
  585.             3'b110: if (~|(prescaler & 8'b01111111)) tmr0 <= tmr0 + 1;
  586.             3'b111: if (~|(prescaler & 8'b11111111)) tmr0 <= tmr0 + 1;
  587.          endcase            
  588.       end
  589.    end
  590. end
  591. // The prescaler is always counting from 00 to FF
  592. always @(posedge clk) begin
  593.    if (reset) begin
  594.       prescaler <= 8'h00;
  595.    end
  596.    else begin
  597.       // See if the status register is actually being written to
  598.       prescaler <= prescaler + 1;
  599.    end
  600. end
  601. // PCL Register (Register #2)
  602. //
  603. //    PC Lower 8 bits.  This is handled in the PC section below...
  604. // STATUS Register (Register #3)
  605. //
  606. always @(posedge clk) begin
  607.    if (reset) begin
  608.       status <= 8'h00;
  609.    end
  610.    else begin
  611.       // See if the status register is actually being written to
  612.       if (fwe & specialsel & (fsel == STATUS_ADDRESS)) begin
  613.          // Yes, so just update the register from the dbus
  614.          status <= dbus;
  615.       end
  616.       else begin
  617.          // Update status register on a bit-by-bit basis.
  618.          //
  619.          // For the carry and zero flags, each instruction has its own rule as
  620.          // to whether to update this flag or not.  The instruction decoder is
  621.          // providing us with an enable for C and Z.  Use this to decide whether
  622.          // to retain the existing value, or update with the new alu status output.
  623.          //
  624.          status <= {
  625.             status[7], // BIT 7: Undefined.. (maybe use for debugging)
  626.             status[6], // BIT 6: Program Page, HI bit
  627.             status[5], // BIT 5: Program Page, LO bit
  628.             status[4], // BIT 4: Time Out bit (not implemented at this time)
  629.             status[3], // BIT 3: Power Down bit (not implemented at this time)
  630.             (zwe) ? aluz : status[2], // BIT 2: Z
  631.             status[1], // BIT 1: DC
  632.             (cwe) ? alucout : status[0] // BIT 0: C
  633.          };
  634.       end
  635.    end
  636. end
  637. // FSR Register  (Register #4)
  638. //            
  639. always @(posedge clk) begin
  640.    if (reset) begin
  641.       fsr <= 8'h00;
  642.    end
  643.    else begin
  644.       // See if the status register is actually being written to
  645.       if (fwe & specialsel & (fsel == FSR_ADDRESS)) begin
  646.          fsr <= dbus;
  647.       end
  648.    end
  649. end
  650. // OPTION Register
  651. //
  652. // The special OPTION instruction should move W into the OPTION register.
  653. always @(posedge clk) begin
  654.    if (reset) begin
  655.       option <= 8'h00;
  656.    end
  657.    else begin
  658.       if (isoption)
  659.          option <= dbus;
  660.    end   
  661. end
  662. // PORTA Input Port   (Register #5)
  663. //
  664. // Register anything on the module's porta input on every single clock.
  665. //
  666. always @(posedge clk) begin
  667.    if (reset) begin
  668.       porta <= 8'h00;
  669.    end
  670.    else begin
  671.       porta <= portain;
  672.    end   
  673. end
  674. // PORTB Output Port  (Register #6)
  675. always @(posedge clk) begin
  676.    if (reset) begin
  677.       portb <= 8'h00;
  678.    end
  679.    else begin
  680.       if (fwe & specialsel & (fsel == PORTB_ADDRESS) & ~istris) begin
  681.          portb <= dbus;
  682.       end
  683.    end   
  684. end
  685. // Connect the output ports to the register output.
  686. always @(portb)
  687.    portbout <= portb;
  688.    
  689. // PORTC Output Port  (Register #7)
  690. always @(posedge clk) begin
  691.    if (reset) begin
  692.       portc <= 8'h00;
  693.    end
  694.    else begin
  695.       if (fwe & specialsel & (fsel == PORTC_ADDRESS) & ~istris) begin
  696.          portc <= dbus;
  697.       end
  698.    end   
  699. end
  700. // Connect the output ports to the register output.
  701. always @(portc)
  702.    portcout <= portc;
  703.  
  704. // TRIS Registers
  705. always @(posedge clk) begin
  706.    if (reset) begin
  707.       trisa <= 8'hff; // Default is to tristate them
  708.    end
  709.    else begin
  710.       if (fwe & specialsel & (fsel == PORTA_ADDRESS) & istris) begin
  711.          trisa <= dbus;
  712.       end
  713.    end   
  714. end
  715. always @(posedge clk) begin
  716.    if (reset) begin
  717.       trisb <= 8'hff; // Default is to tristate them
  718.    end
  719.    else begin
  720.       if (fwe & specialsel & (fsel == PORTB_ADDRESS) & istris) begin
  721.          trisb <= dbus;
  722.       end
  723.    end   
  724. end
  725. always @(posedge clk) begin
  726.    if (reset) begin
  727.       trisc <= 8'hff; // Default is to tristate them
  728.    end
  729.    else begin
  730.       if (fwe & specialsel & (fsel == PORTC_ADDRESS) & istris) begin
  731.          trisc <= dbus;
  732.       end
  733.    end   
  734. end
  735.   
  736. // ********** PC AND STACK *************************
  737. //
  738. // There are 4 ways to change the PC.  They are:
  739. //    GOTO  101k_kkkk_kkkk
  740. //    CALL  1001_kkkk_kkkk
  741. //    RETLW 1000_kkkk_kkkk
  742. //    MOVF  0010_0010_0010  (e.g. a write to reg #2)
  743. //
  744. // Remember that the skip instructions work by inserting
  745. // a NOP instruction or not into program stream and don't
  746. // change the PC.
  747. //
  748. // We need pc + 1 in several places, so lets define this incrementor and
  749. // its output signal it in one place so that we never get redundant adders.
  750. //
  751. always @(pc)
  752.    pcplus1 <= pc + 1;
  753.    
  754. parameter PC_SELECT_PCPLUS1 = 3'b000,
  755. PC_SELECT_K             = 3'b001,
  756. PC_SELECT_STACK1        = 3'b010,
  757. PC_SELECT_STACK2        = 3'b011,
  758. PC_SELECT_DBUS          = 3'b100,
  759. PC_SELECT_RESET_VECTOR  = 3'b101;
  760. // 8:1 Data MUX into PC 
  761. always @(posedge clk) begin
  762.    case (pcinsel) // synopsys parallel_case full_case
  763.       3'b000:  pc <= pcplus1;
  764.       3'b001:  pc <= k;
  765.       3'b010:  pc <= stack1;
  766.       3'b011:  pc <= stack2;
  767.       3'b100:  pc <= dbus;
  768.       3'b101:  pc <= RESET_VECTOR;
  769.       
  770.       // Don't really carry about these...
  771.       3'b110:  pc <= pc;
  772.       3'b111:  pc <= pc;
  773.    endcase
  774. end
  775. // Select for the MUX going into the PC.
  776. //
  777. //
  778. always @(inst or stacklevel or reset) begin
  779.    if (reset == 1'b1) begin
  780.       pcinsel <= PC_SELECT_RESET_VECTOR;
  781.    end
  782.    else begin
  783.       casex ({inst, stacklevel})
  784.          14'b101?_????_????_??: pcinsel <= PC_SELECT_K; // GOTO
  785.          14'b1001_????_????_??: pcinsel <= PC_SELECT_K; // CALL
  786.          14'b1000_????_????_00: pcinsel <= PC_SELECT_STACK1; // RETLW
  787.          14'b1000_????_????_01: pcinsel <= PC_SELECT_STACK1; // RETLW
  788.          14'b1000_????_????_10: pcinsel <= PC_SELECT_STACK2; // RETLW
  789.          14'b1000_????_????_11: pcinsel <= PC_SELECT_STACK2; // RETLW
  790.          14'b0010_0010_0010_??: pcinsel <= PC_SELECT_DBUS; // MOVF where f=PC
  791.          default:
  792.             pcinsel <= PC_SELECT_PCPLUS1;
  793.       endcase
  794.    end
  795. end
  796. // Implement STACK1 and STACK2 registers
  797. //
  798. // The Stack registers are only fed from the PC itself!
  799. //
  800. always @(posedge clk) begin
  801.    if (reset) begin
  802.       stack1 <= 9'h000;
  803.    end
  804.    else begin
  805.       // CALL instruction
  806.       if (inst[11:8] == 4'b1001) begin
  807.          case (stacklevel)
  808.             2'b00:
  809.                // No previous CALLs 
  810.                begin
  811.                   stack1 <= pc;
  812.                   $display ("Write to STACK1: %0h", pc);
  813.                end
  814.             2'b01:
  815.                // ONE previous CALL 
  816.                begin
  817.                   stack2 <= pc;
  818.                   $display ("Write to STACK2: %0h", pc);
  819.                end
  820.             2'b10:
  821.                // TWO previous CALLs -- This is illegal on the 16C5X! 
  822.                begin
  823.                   $display ("Too many CALLs!!");
  824.                end
  825.             2'b11: 
  826.                begin
  827.                   $display ("Too many CALLs!!");
  828.                end
  829.          endcase
  830.       end
  831.    end
  832. end
  833. // Write to stacklevel
  834. //
  835. // The stacklevel register keeps track of the current stack depth.  On this
  836. // puny processor, there are only 2 levels (you could fiddle with this and
  837. // increase the stack depth).  There are two stack registers, stack1 and stack2.
  838. // The stack1 register is used first (e.g. the first time a call is performed),
  839. // then stack2.  As CALLs are done, stacklevel increments.  Conversely, as
  840. // RETs are done, stacklevel goes down. 
  841. always @(posedge clk) begin
  842.    if (reset == 1'b1) begin
  843.       stacklevel <= 2'b00;  // On reset, there should be no CALLs in progress
  844.    end
  845.    else begin
  846.       casex ({inst, stacklevel})
  847.          // Call instructions
  848.          14'b1001_????_????_00: stacklevel <= 2'b01;  // Record 1st CALL
  849.          14'b1001_????_????_01: stacklevel <= 2'b10;  // Record 2nd CALL
  850.          14'b1001_????_????_10: stacklevel <= 2'b10;  // Already 2! Ignore
  851.          14'b1001_????_????_11: stacklevel <= 2'b00;  // {shouldn't happen}
  852.          // Return instructions
  853.          14'b1000_????_????_00: stacklevel <= 2'b00;  // {shouldn't happen}
  854.          14'b1000_????_????_01: stacklevel <= 2'b00;  // Go back to no CALL in progress
  855.          14'b1000_????_????_10: stacklevel <= 2'b01;  // Go back to 1 CALL in progress
  856.          14'b1000_????_????_11: stacklevel <= 2'b10;  // {shouldn't happen} sort of like, Go back to 2 calls in progress
  857.          default:
  858.             stacklevel <= stacklevel;
  859.       endcase
  860.    end
  861. end
  862. // ************  EXPANSION  *************************
  863. //
  864. // The following is an example of customization.
  865. //
  866. // Example:  Create a read/write port located at address 7F.  It'll be 8-bits, where
  867. //           the upper 4 bits are outputs and the lower 4 bits are inputs.  
  868. //           Use indirect addressing to access it (INDF/FSR).  Just for fun, let's
  869. //           attach a special loop-back circuit between the outputs and inputs.
  870. //           Let's attach... say... a 4-bit adder.
  871. //
  872. reg [3:0] special_peripheral_writeable_bits;
  873. reg [3:0] special_peripheral_readeable_bits;
  874. // Implement the writeable bits.
  875. //
  876. always @(posedge clk) begin
  877.    if (reset) begin
  878.       special_peripheral_writeable_bits <= 4'b0000;
  879.    end
  880.    else begin
  881.       if (fwe & expsel & (fileaddr == EXPADDRESS_LILADDER)) begin
  882.          special_peripheral_writeable_bits <= dbus;
  883.       end
  884.    end
  885. end
  886. // Implement the special peripheral function (the 4-bit adder for this example).
  887. always @(special_peripheral_writeable_bits) begin
  888.    special_peripheral_readeable_bits <= special_peripheral_writeable_bits + 1;
  889. end
  890. // Drive the ebus.  With only one custom address, no more muxing needs to be
  891. // done, but if there are multiple custom circuits, everyone needs to cooperate
  892. // and drive ebus properly.
  893. //
  894. always @(fileaddr or special_peripheral_readeable_bits) begin
  895.    if (fileaddr == EXPADDRESS_LILADDER)
  896.       ebus <= special_peripheral_readeable_bits;
  897.    else
  898.       ebus <= 8'hff;
  899. end
  900. endmodule
  901. // 
  902. // SYNTHETIC PIC 2.0                                          4/23/98
  903. //
  904. //    This is a synthesizable Microchip 16C57 compatible
  905. //    microcontroller.  This core is not intended as a high fidelity model of
  906. //    the PIC, but simply a way to offer a simple processor core to people
  907. //    familiar with the PIC who also have PIC tools.  
  908. //
  909. //    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
  910. //    piccpu.v   -   top-level synthesizable module
  911. //    picregs.v  -   register file instantiated under piccpu
  912. //    picalu.v   -   ALU instantiated under piccpu
  913. //    picidec.v  -   Instruction Decoder instantiated under piccpu
  914. //    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
  915. //                   into the Verilog $readmemh compatible file
  916. //    test*.asm  -   (note the wildcard..) Several test programs used
  917. //                   to help debug the verilog.  I used MPLAB and the simulator
  918. //                   to develop these programs and get the expected results.
  919. //                   Then, I ran them on Verilog-XL where they appeared to
  920. //                   match.
  921. //
  922. //    Copyright, Tom Coonan, '97.
  923. //    Use freely, but not for resale as is.  You may use this in your
  924. //    own projects as desired.  Just don't try to sell it as is!
  925. //
  926. //
  927. // This is the PIC Instruction Decoder.
  928. //
  929. // The 12-bit PIC instruction must result in a set of control
  930. // signals to the ALU, register write enables and other wires.
  931. // This is purely combinatorial.  This can physically be
  932. // implemented as a ROM, or, in this implementation a Verilog
  933. // casex statement is used to directly synthesize the signals.
  934. // This approach is more portable, and hopefully much reduction
  935. // occurs in the equations.
  936. //
  937. // The Synthetic PIC Manual contains a table that better shows
  938. // all the required signals per instruction.  I basically
  939. // took that table and created the Verilog implementation below.
  940. //
  941. module picidec (
  942. inst,
  943. aluasel,
  944. alubsel,
  945. aluop,
  946. wwe,
  947. fwe,
  948. zwe,
  949. cwe,
  950. bdpol,
  951. option,
  952. tris
  953. );
  954. input  [11:0] inst;
  955. output [1:0] aluasel;
  956. output [1:0] alubsel;
  957. output [3:0] aluop;
  958. output wwe;
  959. output fwe;
  960. output zwe;
  961. output cwe;
  962. output bdpol;
  963. output option;
  964. output tris;
  965. reg [14:0] decodes;
  966. // For reference, the ALU Op codes are:
  967. //
  968. //   ADD  0000
  969. //   SUB  1000
  970. //   AND  0001
  971. //   OR   0010
  972. //   XOR  0011
  973. //   COM  0100
  974. //   ROR  0101
  975. //   ROL  0110
  976. //   SWAP 0111
  977. assign { aluasel, // Select source for ALU A input. 00=W, 01=SBUS, 10=K, 11=BD
  978. alubsel, // Select source for ALU B input. 00=W, 01=SBUS, 10=K, 11="1"
  979. aluop, // ALU Operation (see comments above for these codes)
  980. wwe, // W register Write Enable
  981. fwe, // File Register Write Enable
  982. zwe, // Status register Z bit update
  983. cwe, // Status register Z bit update
  984. bdpol, // Polarity on bit decode vector (0=no inversion, 1=invert)
  985. tris, // Instruction is an TRIS instruction
  986. option // Instruction is an OPTION instruction
  987. } = decodes;
  988. // This is a large combinatorial decoder.
  989. // I use the casex statement.
  990. always @(inst) begin
  991. casex (inst)
  992. // *** Byte-Oriented File Register Operations
  993. //
  994. //                                 A  A  ALU  W F Z C B T O
  995. //                                 L  L   O   W W W W D R P
  996. //                                 U  U   P   E E E E P I T
  997. //                                 A  B               O S
  998. //                                                    L
  999. 12'b0000_0000_0000: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // NOP
  1000. 12'b0000_001X_XXXX: decodes <= 15'b00_00_0010_0_1_0_0_0_0_0; // MOVWF
  1001. 12'b0000_0100_0000: decodes <= 15'b00_00_0011_1_0_1_0_0_0_0; // CLRW
  1002. 12'b0000_011X_XXXX: decodes <= 15'b00_00_0011_0_1_1_0_0_0_0; // CLRF
  1003. 12'b0000_100X_XXXX: decodes <= 15'b01_00_1000_1_0_1_1_0_0_0; // SUBWF (d=0)
  1004. 12'b0000_101X_XXXX: decodes <= 15'b01_00_1000_0_1_1_1_0_0_0; // SUBWF (d=1)
  1005. 12'b0000_110X_XXXX: decodes <= 15'b01_11_1000_1_0_1_0_0_0_0; // DECF  (d=0)
  1006. 12'b0000_111X_XXXX: decodes <= 15'b01_11_1000_0_1_1_0_0_0_0; // DECF  (d=1)
  1007. 12'b0001_000X_XXXX: decodes <= 15'b00_01_0010_1_0_1_0_0_0_0; // IORWF (d=0)
  1008. 12'b0001_001X_XXXX: decodes <= 15'b00_01_0010_0_1_1_0_0_0_0; // IORWF (d=1)
  1009. 12'b0001_010X_XXXX: decodes <= 15'b00_01_0001_1_0_1_0_0_0_0; // ANDWF (d=0)
  1010. 12'b0001_011X_XXXX: decodes <= 15'b00_01_0001_0_1_1_0_0_0_0; // ANDWF (d=1)
  1011. 12'b0001_100X_XXXX: decodes <= 15'b00_01_0011_1_0_1_0_0_0_0; // XORWF (d=0)
  1012. 12'b0001_101X_XXXX: decodes <= 15'b00_01_0011_0_1_1_0_0_0_0; // XORWF (d=1)
  1013. 12'b0001_110X_XXXX: decodes <= 15'b00_01_0000_1_0_1_1_0_0_0; // ADDWF (d=0)
  1014. 12'b0001_111X_XXXX: decodes <= 15'b00_01_0000_0_1_1_1_0_0_0; // ADDWF (d=1)
  1015. 12'b0010_000X_XXXX: decodes <= 15'b01_01_0010_1_0_1_0_0_0_0; // MOVF  (d=0)
  1016. 12'b0010_001X_XXXX: decodes <= 15'b01_01_0010_0_1_1_0_0_0_0; // MOVF  (d=1)
  1017. 12'b0010_010X_XXXX: decodes <= 15'b01_01_0100_1_0_1_0_0_0_0; // COMF  (d=0)
  1018. 12'b0010_011X_XXXX: decodes <= 15'b01_01_0100_0_1_1_0_0_0_0; // COMF  (d=1)
  1019. 12'b0010_100X_XXXX: decodes <= 15'b01_11_0000_1_0_1_0_0_0_0; // INCF  (d=0)
  1020. 12'b0010_101X_XXXX: decodes <= 15'b01_11_0000_0_1_1_0_0_0_0; // INCF  (d=1)
  1021. 12'b0010_110X_XXXX: decodes <= 15'b01_11_1000_1_0_0_0_0_0_0; // DECFSZ(d=0)
  1022. 12'b0010_111X_XXXX: decodes <= 15'b01_11_1000_0_1_0_0_0_0_0; // DECFSZ(d=1)
  1023. 12'b0011_000X_XXXX: decodes <= 15'b01_01_0101_1_0_0_1_0_0_0; // RRF   (d=0)
  1024. 12'b0011_001X_XXXX: decodes <= 15'b01_01_0101_0_1_0_1_0_0_0; // RRF   (d=1)
  1025. 12'b0011_010X_XXXX: decodes <= 15'b01_01_0110_1_0_0_1_0_0_0; // RLF   (d=0)
  1026. 12'b0011_011X_XXXX: decodes <= 15'b01_01_0110_0_1_0_1_0_0_0; // RLF   (d=1)
  1027. 12'b0011_100X_XXXX: decodes <= 15'b01_01_0111_1_0_0_0_0_0_0; // SWAPF (d=0)
  1028. 12'b0011_101X_XXXX: decodes <= 15'b01_01_0111_0_1_0_0_0_0_0; // SWAPF (d=1)
  1029. 12'b0011_110X_XXXX: decodes <= 15'b01_11_0000_1_0_0_0_0_0_0; // INCFSZ(d=0)
  1030. 12'b0011_111X_XXXX: decodes <= 15'b01_11_0000_0_1_0_0_0_0_0; // INCFSZ(d=1)
  1031. // *** Bit-Oriented File Register Operations
  1032.                 //
  1033. //                                 A  A  ALU  W F Z C B T O
  1034. //                                 L  L   O   W W W W D R P
  1035. //                                 U  U   P   E E E E P I T
  1036. //                                 A  B               O S
  1037. //                                                    L
  1038. 12'b0100_XXXX_XXXX: decodes <= 15'b11_01_0001_0_1_0_0_1_0_0; // BCF
  1039. 12'b0101_XXXX_XXXX: decodes <= 15'b11_01_0010_0_1_0_0_0_0_0; // BSF
  1040. 12'b0110_XXXX_XXXX: decodes <= 15'b11_01_0001_0_0_0_0_0_0_0; // BTFSC
  1041. 12'b0111_XXXX_XXXX: decodes <= 15'b11_01_0001_0_0_0_0_0_0_0; // BTFSS
  1042. // *** Literal and Control Operations
  1043.                 //
  1044. //                                 A  A  ALU  W F Z C B T O
  1045. //                                 L  L   O   W W W W D R P
  1046. //                                 U  U   P   E E E E P I T
  1047. //                                 A  B               O S
  1048. //                                                    L
  1049. 12'b0000_0000_0010: decodes <= 15'b00_00_0010_0_1_0_0_0_0_1; // OPTION
  1050. 12'b0000_0000_0011: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // SLEEP
  1051. 12'b0000_0000_0100: decodes <= 15'b00_00_0000_0_0_0_0_0_0_0; // CLRWDT
  1052. 12'b0000_0000_0101: decodes <= 15'b00_00_0000_0_1_0_0_0_1_0; // TRIS 5
  1053. 12'b0000_0000_0110: decodes <= 15'b00_00_0010_0_1_0_0_0_1_0; // TRIS 6
  1054. 12'b0000_0000_0111: decodes <= 15'b00_00_0010_0_1_0_0_0_1_0; // TRIS 7
  1055.                 //
  1056. //                                 A  A  ALU  W F Z C B T O
  1057. //                                 L  L   O   W W W W D R P
  1058. //                                 U  U   P   E E E E P I T
  1059. //                                 A  B               O S
  1060. //                                                    L
  1061. 12'b1000_XXXX_XXXX: decodes <= 15'b10_10_0010_1_0_0_0_0_0_0; // RETLW
  1062. 12'b1001_XXXX_XXXX: decodes <= 15'b10_10_0010_0_0_0_0_0_0_0; // CALL
  1063. 12'b101X_XXXX_XXXX: decodes <= 15'b10_10_0010_0_0_0_0_0_0_0; // GOTO
  1064. 12'b1100_XXXX_XXXX: decodes <= 15'b10_10_0010_1_0_0_0_0_0_0; // MOVLW
  1065. 12'b1101_XXXX_XXXX: decodes <= 15'b00_10_0010_1_0_1_0_0_0_0; // IORLW
  1066. 12'b1110_XXXX_XXXX: decodes <= 15'b00_10_0001_1_0_1_0_0_0_0; // ANDLW
  1067. 12'b1111_XXXX_XXXX: decodes <= 15'b00_10_0011_1_0_1_0_0_0_0; // XORLW
  1068. default:
  1069. decodes <= 15'b00_00_0000_0_0_0_0_0_0_0;
  1070. endcase
  1071. end
  1072. endmodule
  1073. // 
  1074. // SYNTHETIC PIC 2.0                                          4/23/98
  1075. //
  1076. //    This is a synthesizable Microchip 16C57 compatible
  1077. //    microcontroller.  This core is not intended as a high fidelity model of
  1078. //    the PIC, but simply a way to offer a simple processor core to people
  1079. //    familiar with the PIC who also have PIC tools.  
  1080. //
  1081. //    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
  1082. //    piccpu.v   -   top-level synthesizable module
  1083. //    picregs.v  -   register file instantiated under piccpu
  1084. //    picalu.v   -   ALU instantiated under piccpu
  1085. //    picidec.v  -   Instruction Decoder instantiated under piccpu
  1086. //    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
  1087. //                   into the Verilog $readmemh compatible file
  1088. //    test*.asm  -   (note the wildcard..) Several test programs used
  1089. //                   to help debug the verilog.  I used MPLAB and the simulator
  1090. //                   to develop these programs and get the expected results.
  1091. //                   Then, I ran them on Verilog-XL where they appeared to
  1092. //                   match.
  1093. //
  1094. //    Copyright, Tom Coonan, '97.
  1095. //    Use freely, but not for resale as is.  You may use this in your
  1096. //    own projects as desired.  Just don't try to sell it as is!
  1097. //
  1098. //
  1099. //`define DEBUG_SHOWREADS
  1100. //`define DEBUG_SHOWWRITES
  1101. // Memory Map:
  1102. //
  1103. // PIC Data Memory addressing is complicated.  See the Data Book for full explanation..
  1104. //
  1105. // Basically, each BANK contains 32 locations.  The lowest 16 locations in ALL Banks
  1106. // are really all mapped to the same bank (bank #0).  The first 8 locations are the Special
  1107. // registers like the STATUS and PC registers.  The upper 16 words in each bank, really are
  1108. // unique to each bank.  The smallest PIC (16C54) only has the one bank #0.
  1109. //
  1110. // So, as a programmer, what you get is this.  No matter what bank you are in (FSR[6:5])
  1111. // you always have access to your special registers and also to registers 8-15.  You can
  1112. // change to a 1 of 4 banks by setting FSR[6:5] and get 4 different sets of registers
  1113. // 16-31.
  1114. //
  1115. // For numbering purposes, I've numbered the registers as if they are one linear memory
  1116. // space, just like in the Data Book (see Figure 4-15 "Direct/Indirect Addressing").
  1117. // So, the unique 16 registers in bank #1 are named r48 - r63 (I use decimal).  The
  1118. // unique registers in bank #3 are therefore r112 - r127.  There is no r111 because,
  1119. // remember, the lower 16 registers each each bank are all reall the same registers 0-15.
  1120. // 
  1121. // Confused?!  The Data Book explains it better than I can.
  1122. //
  1123. //   bank location 
  1124. //     XX 00rrr  -  The special registers are not implemented in this register file.
  1125. //     XX 01rrr  -  The 8 common words, just above the Special Regs, same for all Banks
  1126. //     00 1rrrr  -  The 16 words unique to Bank #0
  1127. //     01 1rrrr  -  The 16 words unique to Bank #1
  1128. //     10 1rrrr  -  The 16 words unique to Bank #2
  1129. //     11 1rrrr  -  The 16 words unique to Bank #3
  1130. //
  1131. //  So, 
  1132. //     Special Regs are location[4:3] == 00
  1133. //     Common Regs are  location[4:3] == 01
  1134. //     Words in banks   location[4]   == 1
  1135. // 
  1136. //
  1137. //  I had problems trying to use simple register file declarations that
  1138. //  would always, always work right, were synthesizable and allowed
  1139. //  me to easily remove locations from the memory space.  SOOOooo... I
  1140. //  did the brute force thing and enumerated all the locations..
  1141. //
  1142. //  Much larger spaces will probably need a RAM and whatever I do would need
  1143. //  custom hacking anyway..  I don't see an obvious solution to all this, but
  1144. //  welcome suggestions..
  1145. //
  1146. module picregs (clk, reset, we, re, bank, location, din, dout);
  1147. input clk;
  1148. input reset;
  1149. input we;
  1150. input re;
  1151. input  [1:0] bank; // Bank 0,1,2,3
  1152. input  [4:0] location; // Location
  1153. input  [7:0] din; // Input 
  1154. output [7:0] dout; // Output 
  1155. //parameter MAX_ADDRESS = 127;
  1156. reg [7:0] dout;
  1157. integer index;
  1158. // Declare the major busses in and out of each block.
  1159. //
  1160. reg [7:0] commonblockout; // Data Memory common across all banks
  1161. reg [7:0] highblock0out; // Upper 16 bytes in BANK #0
  1162. reg [7:0] highblock1out; // Upper 16 bytes in BANK #1
  1163. reg [7:0] highblock2out; // Upper 16 bytes in BANK #2
  1164. reg [7:0] highblock3out; // Upper 16 bytes in BANK #3
  1165. reg [7:0] commonblockin; // Data Memory common across all banks
  1166. reg [7:0] highblock0in; // Upper 16 bytes in BANK #0
  1167. reg [7:0] highblock1in; // Upper 16 bytes in BANK #1
  1168. reg [7:0] highblock2in; // Upper 16 bytes in BANK #2
  1169. reg [7:0] highblock3in; // Upper 16 bytes in BANK #3
  1170. reg commonblocksel; // Select
  1171. reg highblock0sel; // Select
  1172. reg highblock1sel; // Select
  1173. reg highblock2sel; // Select
  1174. reg highblock3sel; // Select
  1175. // synopsys translate_off
  1176. integer cycle_counter;
  1177. initial cycle_counter = 0;
  1178. always @(negedge clk) begin
  1179.    if (re) begin
  1180. `ifdef DEBUG_SHOWREADS   
  1181.       $display ("[%0d] Read:  data = %0h(hex), from bank #%0d(dec) location %0h", cycle_counter, dout, bank, location);
  1182. `endif
  1183.    end
  1184.    if (we) begin
  1185. `ifdef DEBUG_SHOWWRITES   
  1186.       $display ("[%0d] Write: data = %0h(hex), to   bank #%0d(dec) location %0h", cycle_counter, din, bank, location);
  1187. `endif
  1188.    end
  1189.    if (~reset) cycle_counter = cycle_counter + 1;
  1190. end  
  1191. // synopsys translate_on
  1192. // READ the Register File
  1193. //
  1194. always @(bank or location or re
  1195. or commonblockout 
  1196. or highblock0out 
  1197. or highblock1out 
  1198. or highblock2out 
  1199. or highblock3out) begin
  1200.    if (re) begin
  1201.       if (location[4:3] == 2'b01) begin
  1202.          // This is the lower 8 words, common to all banks, just above special registers
  1203.          dout <= commonblockout; // Access to first 8 locations past Special Registers 
  1204.       end
  1205.       else begin
  1206.          if (location[4]) begin
  1207.             // Address is in the upper 16 words on one of the 4 banks
  1208.             case (bank) // synopsys full_case parallel_case
  1209.                2'b00:  dout <= highblock0out; // Upper 16 words of Bank #0
  1210.                2'b01:  dout <= highblock1out; // Upper 16 words of Bank #1
  1211.                2'b10:  dout <= highblock2out; // Upper 16 words of Bank #2
  1212.                2'b11:  dout <= highblock3out; // Upper 16 words of Bank #3
  1213.             endcase
  1214.          end
  1215.          else begin
  1216.             dout <= 8'hff;
  1217.          end
  1218.       end
  1219.    end
  1220.    else begin
  1221.       dout <= 8'hff;
  1222.    end
  1223. end
  1224. // Initial Write logic.
  1225. //
  1226. // Generate the specific write enables based on the PIC's bank/location rules.
  1227. // The individual memory blocks will do the actual synchronous write.
  1228. //
  1229. always @(we or bank or location or reset) begin
  1230.    if (reset) begin
  1231.       commonblocksel <= 1'b0;
  1232.       highblock0sel  <= 1'b0;
  1233.       highblock1sel  <= 1'b0;
  1234.       highblock2sel  <= 1'b0;
  1235.       highblock3sel  <= 1'b0;
  1236.    end
  1237.    else begin
  1238.       if (we) begin
  1239.          if (location[4:3] == 2'b01) begin
  1240.             // This is the lower 8 words, common to all banks, just above special registers
  1241.             commonblocksel <= 1'b1;
  1242.             highblock0sel  <= 1'b0;
  1243.             highblock1sel  <= 1'b0;
  1244.             highblock2sel  <= 1'b0;
  1245.             highblock3sel  <= 1'b0;
  1246.          end
  1247.          else begin
  1248.             if (location[4]) begin
  1249.                // Address is in the upper 16 words on one of the 4 banks
  1250.                commonblocksel <= 1'b0;
  1251.                case (bank) // synopsys full_case parallel_case
  1252.                   2'b00:  {highblock0sel, highblock1sel, highblock2sel, highblock3sel} <= 4'b1000; // Upper 16 words of Bank #0
  1253.                   2'b01:  {highblock0sel, highblock1sel, highblock2sel, highblock3sel} <= 4'b0100; // Upper 16 words of Bank #1
  1254.                   2'b10:  {highblock0sel, highblock1sel, highblock2sel, highblock3sel} <= 4'b0010; // Upper 16 words of Bank #2
  1255.                   2'b11:  {highblock0sel, highblock1sel, highblock2sel, highblock3sel} <= 4'b0001; // Upper 16 words of Bank #3
  1256.                endcase
  1257.             end
  1258.             else begin
  1259.                commonblocksel <= 1'b0;
  1260.                highblock0sel  <= 1'b0;
  1261.                highblock1sel  <= 1'b0;
  1262.                highblock2sel  <= 1'b0;
  1263.                highblock3sel  <= 1'b0;
  1264.             end
  1265.          end
  1266.       end
  1267.       else begin
  1268.          commonblocksel <= 1'b0;
  1269.          highblock0sel  <= 1'b0;
  1270.          highblock1sel  <= 1'b0;
  1271.          highblock2sel  <= 1'b0;
  1272.          highblock3sel  <= 1'b0;
  1273.       end
  1274.    end
  1275. end
  1276. // *** Buses feeding the memory blocks are driven directly from din.
  1277. always @(din)
  1278.    commonblockin <= din;
  1279. always @(din)
  1280.    highblock0in <= din;
  1281. always @(din)
  1282.    highblock1in <= din;
  1283. always @(din)
  1284.    highblock2in <= din;
  1285. always @(din)
  1286.    highblock3in <= din;
  1287. // ****************** Common Block *************
  1288. reg [7:0] r8, r9, r10, r11, r12, r13, r14, r15;
  1289. // Read from common block
  1290. always @(location or
  1291. r8 or r9 or r10 or r11 or r12 or r13 or r14 or r15) begin
  1292.    case (location[2:0])
  1293.       3'h0: commonblockout <= r8;
  1294.       3'h1: commonblockout <= r9;
  1295.       3'h2: commonblockout <= r10;
  1296.       3'h3: commonblockout <= r11;
  1297.       3'h4: commonblockout <= r12;
  1298.       3'h5: commonblockout <= r13;
  1299.       3'h6: commonblockout <= r14;
  1300.       3'h7: commonblockout <= r15;
  1301.    endcase
  1302. end
  1303.       
  1304. // Write to common block
  1305. always @(posedge clk) begin
  1306.    if (we & commonblocksel) begin
  1307.       case (location[2:0])
  1308.          3'h0: r8  <= commonblockin;
  1309.          3'h1: r9  <= commonblockin;
  1310.          3'h2: r10 <= commonblockin;
  1311.          3'h3: r11 <= commonblockin;
  1312.          3'h4: r12 <= commonblockin;
  1313.          3'h5: r13 <= commonblockin;
  1314.          3'h6: r14 <= commonblockin;
  1315.          3'h7: r15 <= commonblockin;
  1316.       endcase
  1317.    end
  1318. end
  1319. // **************** Highblock0 ****************
  1320. reg [7:0] r16, r17, r18, r19, r20, r21, r22, r23;
  1321. reg [7:0] r24, r25, r26, r27, r28, r29, r30, r31;
  1322. // Read from high block bank0
  1323. always @(location or
  1324. r16 or r17 or r18 or r19 or r20 or r21 or r22 or r23 or
  1325. r24 or r25 or r26 or r27 or r28 or r29 or r30 or r31
  1326. ) begin
  1327.    case (location[3:0])
  1328.       4'h0: highblock0out <= r16;
  1329.       4'h1: highblock0out <= r17;
  1330.       4'h2: highblock0out <= r18;
  1331.       4'h3: highblock0out <= r19;
  1332.       4'h4: highblock0out <= r20;
  1333.       4'h5: highblock0out <= r21;
  1334.       4'h6: highblock0out <= r22;
  1335.       4'h7: highblock0out <= r23;
  1336.       4'h8: highblock0out <= r24;
  1337.       4'h9: highblock0out <= r25;
  1338.       4'hA: highblock0out <= r26;
  1339.       4'hB: highblock0out <= r27;
  1340.       4'hC: highblock0out <= r28;
  1341.       4'hD: highblock0out <= r29;
  1342.       4'hE: highblock0out <= r30;
  1343.       4'hF: highblock0out <= r31;
  1344.    endcase
  1345. end
  1346.       
  1347. // Write to high block bank 0
  1348. always @(posedge clk) begin
  1349.    if (we & highblock0sel) begin
  1350.       case (location[3:0])
  1351.          4'h0: r16 <= highblock0in;
  1352.          4'h1: r17 <= highblock0in;
  1353.          4'h2: r18 <= highblock0in;
  1354.          4'h3: r19 <= highblock0in;
  1355.          4'h4: r20 <= highblock0in;
  1356.          4'h5: r21 <= highblock0in;
  1357.          4'h6: r22 <= highblock0in;
  1358.          4'h7: r23 <= highblock0in;
  1359.          4'h8: r24 <= highblock0in;
  1360.          4'h9: r25 <= highblock0in;
  1361.          4'hA: r26 <= highblock0in;
  1362.          4'hB: r27 <= highblock0in;
  1363.          4'hC: r28 <= highblock0in;
  1364.          4'hD: r29 <= highblock0in;
  1365.          4'hE: r30 <= highblock0in;
  1366.          4'hF: r31 <= highblock0in;
  1367.       endcase
  1368.    end
  1369. end
  1370. // **************** Highblock1 ****************
  1371. reg [7:0] r48, r49, r50, r51, r52, r53, r54, r55;
  1372. reg [7:0] r56, r57, r58, r59, r60, r61, r62, r63;
  1373. // Read
  1374. always @(location or
  1375. r48 or r49 or r50 or r51 or r52 or r53 or r54 or r55 or
  1376. r56 or r57 or r58 or r59 or r60 or r61 or r62 or r63
  1377. ) begin
  1378.    case (location[3:0])
  1379.       4'h0: highblock1out <= r48;
  1380.       4'h1: highblock1out <= r49;
  1381.       4'h2: highblock1out <= r50;
  1382.       4'h3: highblock1out <= r51;
  1383.       4'h4: highblock1out <= r52;
  1384.       4'h5: highblock1out <= r53;
  1385.       4'h6: highblock1out <= r54;
  1386.       4'h7: highblock1out <= r55;
  1387.       4'h8: highblock1out <= r56;
  1388.       4'h9: highblock1out <= r57;
  1389.       4'hA: highblock1out <= r58;
  1390.       4'hB: highblock1out <= r59;
  1391.       4'hC: highblock1out <= r60;
  1392.       4'hD: highblock1out <= r61;
  1393.       4'hE: highblock1out <= r62;
  1394.       4'hF: highblock1out <= r63;
  1395.    endcase
  1396. end
  1397. // Write
  1398. always @(posedge clk) begin
  1399.    if (we & highblock1sel) begin
  1400.       case (location[3:0])
  1401.          4'h0: r48 <= highblock1in;
  1402.          4'h1: r49 <= highblock1in;
  1403.          4'h2: r50 <= highblock1in;
  1404.          4'h3: r51 <= highblock1in;
  1405.          4'h4: r52 <= highblock1in;
  1406.          4'h5: r53 <= highblock1in;
  1407.          4'h6: r54 <= highblock1in;
  1408.          4'h7: r55 <= highblock1in;
  1409.          4'h8: r56 <= highblock1in;
  1410.          4'h9: r57 <= highblock1in;
  1411.          4'hA: r58 <= highblock1in;
  1412.          4'hB: r59 <= highblock1in;
  1413.          4'hC: r60 <= highblock1in;
  1414.          4'hD: r61 <= highblock1in;
  1415.          4'hE: r62 <= highblock1in;
  1416.          4'hF: r63 <= highblock1in;
  1417.       endcase
  1418.    end
  1419. end
  1420.       
  1421. // **************** Highblock2 ****************
  1422. reg [7:0] r80, r81, r82, r83, r84, r85, r86, r87;
  1423. reg [7:0] r88, r89, r90, r91, r92, r93, r94, r95;
  1424. // Read
  1425. always @(location or
  1426. r80 or r81 or r82 or r83 or r84 or r85 or r86 or r87 or
  1427. r88 or r89 or r90 or r91 or r92 or r93 or r94 or r95
  1428. ) begin
  1429.    case (location[3:0])
  1430.       4'h0: highblock2out <= r80;
  1431.       4'h1: highblock2out <= r81;
  1432.       4'h2: highblock2out <= r82;
  1433.       4'h3: highblock2out <= r83;
  1434.       4'h4: highblock2out <= r84;
  1435.       4'h5: highblock2out <= r85;
  1436.       4'h6: highblock2out <= r86;
  1437.       4'h7: highblock2out <= r87;
  1438.       4'h8: highblock2out <= r88;
  1439.       4'h9: highblock2out <= r89;
  1440.       4'hA: highblock2out <= r90;
  1441.       4'hB: highblock2out <= r91;
  1442.       4'hC: highblock2out <= r92;
  1443.       4'hD: highblock2out <= r93;
  1444.       4'hE: highblock2out <= r94;
  1445.       4'hF: highblock2out <= r95;
  1446.    endcase
  1447. end
  1448. // Write
  1449. always @(posedge clk) begin
  1450.    if (we & highblock2sel) begin
  1451.       case (location[3:0])
  1452.          4'h0: r80 <= highblock2in;
  1453.          4'h1: r81 <= highblock2in;
  1454.          4'h2: r82 <= highblock2in;
  1455.          4'h3: r83 <= highblock2in;
  1456.          4'h4: r84 <= highblock2in;
  1457.          4'h5: r85 <= highblock2in;
  1458.          4'h6: r86 <= highblock2in;
  1459.          4'h7: r87 <= highblock2in;
  1460.          4'h8: r88 <= highblock2in;
  1461.          4'h9: r89 <= highblock2in;
  1462.          4'hA: r90 <= highblock2in;
  1463.          4'hB: r91 <= highblock2in;
  1464.          4'hC: r92 <= highblock2in;
  1465.          4'hD: r93 <= highblock2in;
  1466.          4'hE: r94 <= highblock2in;
  1467.          4'hF: r95 <= highblock2in;
  1468.       endcase
  1469.    end
  1470. end
  1471. // **************** Highblock3 ****************
  1472. // *** The Following Registers are removed because of CUSTOM Hardware (see piccpu.v) **
  1473. //
  1474. //    r129 (or 7E)
  1475. //
  1476. // **********
  1477. reg [7:0] r112, r113, r114, r115, r116, r117, r118, r119;
  1478. reg [7:0] r120, r121, r122, r123, r124, r125, r126 /*, r127*/ ;
  1479. // Read
  1480. always @(location or
  1481. r112 or r113 or r114 or r115 or r116 or r117 or r118 or r119 or
  1482. r120 or r121 or r122 or r123 or r124 or r125 or r126 /* or r127 */
  1483. ) begin
  1484.    case (location[3:0])
  1485.       4'h0: highblock3out <= r112;
  1486.       4'h1: highblock3out <= r113;
  1487.       4'h2: highblock3out <= r114;
  1488.       4'h3: highblock3out <= r115;
  1489.       4'h4: highblock3out <= r116;
  1490.       4'h5: highblock3out <= r117;
  1491.       4'h6: highblock3out <= r118;
  1492.       4'h7: highblock3out <= r119;
  1493.       4'h8: highblock3out <= r120;
  1494.       4'h9: highblock3out <= r121;
  1495.       4'hA: highblock3out <= r122;
  1496.       4'hB: highblock3out <= r123;
  1497.       4'hC: highblock3out <= r124;
  1498.       4'hD: highblock3out <= r125;
  1499.       4'hE: highblock3out <= r126;
  1500.       4'hF: highblock3out <= 8'hff /* r127*/ ;
  1501.    endcase
  1502. end
  1503. // Write
  1504. always @(posedge clk) begin
  1505.    if (we & highblock3sel) begin
  1506.       case (location[3:0])
  1507.          4'h0: r112 <= highblock3in;
  1508.          4'h1: r113 <= highblock3in;
  1509.          4'h2: r114 <= highblock3in;
  1510.          4'h3: r115 <= highblock3in;
  1511.          4'h4: r116 <= highblock3in;
  1512.          4'h5: r117 <= highblock3in;
  1513.          4'h6: r118 <= highblock3in;
  1514.          4'h7: r119 <= highblock3in;
  1515.          4'h8: r120 <= highblock3in;
  1516.          4'h9: r121 <= highblock3in;
  1517.          4'hA: r122 <= highblock3in;
  1518.          4'hB: r123 <= highblock3in;
  1519.          4'hC: r124 <= highblock3in;
  1520.          4'hD: r125 <= highblock3in;
  1521.          4'hE: r126 <= highblock3in;
  1522.          4'hF: /* r127 <= highblock3in */;
  1523.       endcase
  1524.    end
  1525. end
  1526. // synopsys translate_off
  1527. `define CLEAR_MEMORY
  1528. `ifdef CLEAR_MEMORY
  1529. initial
  1530. begin
  1531.    $display ("Clearing SRAM.");
  1532.    clear_memory;
  1533. end
  1534. task clear_memory;
  1535. begin
  1536.    // Common registers
  1537.    r8  = 0;
  1538.    r9  = 0;
  1539.    r10 = 0;
  1540.    r11 = 0;
  1541.    r12 = 0;
  1542.    r13 = 0;
  1543.    r14 = 0;
  1544.    r15 = 0;
  1545.    // Bank #0
  1546.    r16 = 0;
  1547.    r17 = 0;
  1548.    r18 = 0;
  1549.    r19 = 0;
  1550.    r20 = 0;
  1551.    r21 = 0;
  1552.    r22 = 0;
  1553.    r23 = 0;
  1554.    r24 = 0;
  1555.    r25 = 0;
  1556.    r26 = 0;
  1557.    r27 = 0;
  1558.    r28 = 0;
  1559.    r29 = 0;
  1560.    r30 = 0;
  1561.    r31 = 0;
  1562.    // Bank #1
  1563.    r48 = 0;
  1564.    r49 = 0;
  1565.    r50 = 0;
  1566.    r51 = 0;
  1567.    r52 = 0;
  1568.    r53 = 0;
  1569.    r54 = 0;
  1570.    r55 = 0;
  1571.    r56 = 0;
  1572.    r57 = 0;
  1573.    r58 = 0;
  1574.    r59 = 0;
  1575.    r60 = 0;
  1576.    r61 = 0;
  1577.    r62 = 0;
  1578.    r63 = 0;
  1579.    // Bank #2
  1580.    r80 = 0;
  1581.    r94 = 0;
  1582.    // Bank #3
  1583.    r112 = 0;
  1584.    r126 = 0;
  1585.   
  1586. end
  1587. endtask
  1588. `endif
  1589. // synopsys translate_on 
  1590. endmodule
  1591. // 
  1592. // SYNTHETIC PIC 2.0                                          4/23/98
  1593. //
  1594. //    This is a synthesizable Microchip 16C57 compatible
  1595. //    microcontroller.  This core is not intended as a high fidelity model of
  1596. //    the PIC, but simply a way to offer a simple processor core to people
  1597. //    familiar with the PIC who also have PIC tools.  
  1598. //
  1599. //    pictest.v  -   top-level testbench (NOT SYNTHESIZABLE)
  1600. //    piccpu.v   -   top-level synthesizable module
  1601. //    picregs.v  -   register file instantiated under piccpu
  1602. //    picalu.v   -   ALU instantiated under piccpu
  1603. //    picidec.v  -   Instruction Decoder instantiated under piccpu
  1604. //    hex2rom.c  -   C program used to translate MPLAB's INTEL HEX output
  1605. //                   into the Verilog $readmemh compatible file
  1606. //    test*.asm  -   (note the wildcard..) Several test programs used
  1607. //                   to help debug the verilog.  I used MPLAB and the simulator
  1608. //                   to develop these programs and get the expected results.
  1609. //                   Then, I ran them on Verilog-XL where they appeared to
  1610. //                   match.
  1611. //
  1612. //    Copyright, Tom Coonan, '97.
  1613. //    Use freely, but not for resale as is.  You may use this in your
  1614. //    own projects as desired.  Just don't try to sell it as is!
  1615. //
  1616. //
  1617. `timescale 1ns / 10ps
  1618. module pictest;
  1619. // Select which test to run HERE..
  1620. parameter TEST_NUMBER = 9;
  1621. // *** Testing variables
  1622. // Debug flags.
  1623. integer dbg_showporta; // Are set in an 'initial' for default values, 
  1624. integer dbg_showportb; //    override in specific tests...
  1625. integer dbg_showportc; // Setting to 1 will cause variable to be displayed.
  1626. integer dbg_showinst;
  1627. integer dbg_showrom;
  1628. integer dbg_showw;
  1629. integer dbg_showpc;
  1630. // cycles counter variables
  1631. integer dbg_showcycles; // Set to 1 to see cycles
  1632. integer dbg_limitcycles;// Set to one to enable maxcycles check
  1633. integer dbg_maxcycles; // Limit simulation to some number of cycles.
  1634. integer cycles; // Cycles counter.
  1635. // *** Interface to the PICCPU
  1636. reg clk;
  1637. reg reset;
  1638. reg  [7:0] porta;
  1639. wire [7:0] portb;
  1640. wire [7:0] portc;
  1641. reg  [11:0] rom[0:511];
  1642. wire [8:0] romaddr;
  1643. reg  [11:0] romdata;
  1644. // ROM Interface
  1645. always @(romaddr) begin
  1646.    romdata = rom[romaddr];
  1647. end
  1648. reg [7:0] last_debugw;
  1649. reg [8:0] last_debugpc;
  1650. reg [11:0] last_debuginst;
  1651. reg [7:0] last_debugstatus;
  1652. wire [7:0] debugw;
  1653. wire [8:0] debugpc;
  1654. wire [11:0] debuginst;
  1655. wire [7:0] debugstatus;
  1656. // Instantiate one PICCPU to be tested.
  1657. piccpu piccpu_inst (
  1658.    .clk (clk),
  1659.    .reset (reset),
  1660.    .paddr (romaddr),
  1661.    .pdata (romdata),
  1662.    .portain (porta),
  1663.    .portbout (portb),
  1664.    .portcout (portc),
  1665.    .debugw (debugw),
  1666.    .debugpc (debugpc),
  1667.    .debuginst (debuginst),
  1668.    .debugstatus (debugstatus)
  1669. );
  1670. // Capture some data
  1671. initial begin
  1672.    $dumpfile ("pic.vcd");
  1673.    $dumpvars (0, pictest);
  1674. end
  1675. // Reset
  1676. initial begin
  1677.    reset = 1;
  1678.    #200;
  1679.    reset = 0;
  1680. end
  1681.   
  1682. // Drive the clock input
  1683. initial begin
  1684.    clk  = 0;
  1685.    forever begin
  1686.       #50 clk = 1;
  1687.       #50 clk = 0;
  1688.    end
  1689. end
  1690. // Debug defaults.  Override in individual test tasks.
  1691. //
  1692. initial begin
  1693.    dbg_showporta  = 0;
  1694.    dbg_showportb  = 0;
  1695.    dbg_showportc  = 0;
  1696.    dbg_showinst   = 0;
  1697.    dbg_showrom    = 0;
  1698.    dbg_showw      = 0;
  1699.    dbg_showpc     = 0;
  1700.    dbg_showcycles = 0;
  1701.    
  1702.    dbg_limitcycles = 1;
  1703.    dbg_maxcycles   = 50000;
  1704. end
  1705. // Call the appropriate test task based on the TEST_NUMBER parameter set at top.
  1706. //
  1707. initial begin
  1708.    case (TEST_NUMBER)
  1709.       1: test1;
  1710.       2: test2;
  1711.       3: test3;
  1712.       4: test4;
  1713.       5: test5;
  1714.       6: test6;
  1715.       7: test7;
  1716.       8: test8;
  1717.       9: test9;
  1718.       default: 
  1719.          begin
  1720.             $display ("ERROR: Unknown Test Number: %0d", TEST_NUMBER);
  1721.             $finish;
  1722.          end
  1723.    endcase
  1724. end
  1725. task test1;
  1726. begin
  1727.    $display ("SYNTHETIC PIC 2.0.  This is TEST #1");
  1728.    #1;
  1729.    
  1730.    // Only Watch Port B
  1731.    dbg_showportb  = 1;
  1732.    dbg_showcycles = 1;
  1733.    $readmemh ("TEST1.ROM", rom);
  1734.    dbg_limitcycles = 1;
  1735.    dbg_maxcycles   = 500;
  1736. end
  1737. endtask
  1738. task test2;
  1739. begin
  1740.    $display ("SYNTHETIC PIC 2.0.  This is TEST #2");
  1741.    #1;
  1742.    // Only Watch Port B
  1743.    dbg_showportb = 1;
  1744.    $readmemh ("TEST2.ROM", rom);
  1745.    dbg_limitcycles = 1;
  1746.    dbg_maxcycles = 500;
  1747. end
  1748. endtask
  1749. task test3;
  1750. begin
  1751.    $display ("SYNTHETIC PIC 2.0.  This is TEST #3");
  1752.    #1;
  1753.    // Only Watch Port B
  1754.    dbg_showportb = 1;
  1755.    $readmemh ("TEST3.ROM", rom);
  1756.    dbg_limitcycles = 1;
  1757.    dbg_maxcycles = 500;
  1758. end
  1759. endtask
  1760. task test4;
  1761. begin
  1762.    $display ("SYNTHETIC PIC 2.0.  This is TEST #4");
  1763.    #1;
  1764.    // Only Watch Port B
  1765.    dbg_showportb = 1;
  1766.    $readmemh ("TEST4.ROM", rom);
  1767.    dbg_limitcycles = 1;
  1768.    dbg_maxcycles = 500;
  1769. end
  1770. endtask
  1771. task test5;
  1772. begin
  1773.    $display ("SYNTHETIC PIC 2.0.  This is TEST #5");
  1774.    #1;
  1775.    // Only Watch Port B
  1776.    dbg_showportb = 1;
  1777.    $readmemh ("TEST5.ROM", rom);
  1778.    dbg_limitcycles = 1;
  1779.    dbg_maxcycles = 500;
  1780. end
  1781. endtask
  1782. task test6;
  1783. begin
  1784.    $display ("SYNTHETIC PIC 2.0.  This is TEST #6");
  1785.    #1;
  1786.    // Watch Port B and C
  1787.    dbg_showportb = 1;
  1788.    dbg_showportc = 1;
  1789.    dbg_limitcycles = 0;
  1790.    $readmemh ("TEST6.ROM", rom);
  1791.    #200;
  1792.    
  1793.    repeat (20) begin
  1794.       porta = $random;
  1795.       #10000;
  1796.    end
  1797.    
  1798.    $finish;
  1799. end
  1800. endtask
  1801. task test7;
  1802. begin
  1803.    $display ("SYNTHETIC PIC 2.0.  This is TEST #7");
  1804.    #1;
  1805.    // Only Watch Port B
  1806.    dbg_showportb = 1;
  1807.    $readmemh ("TEST7.ROM", rom);
  1808.    dbg_limitcycles = 1;
  1809.    dbg_maxcycles = 500;
  1810. end
  1811. endtask
  1812. task test8;
  1813. begin
  1814.    $display ("SYNTHETIC PIC 2.0.  This is TEST #8");
  1815.    #1;
  1816.    // Watch All ports
  1817.    dbg_showporta = 1;
  1818.    dbg_showportb = 1;
  1819.    dbg_showportc = 1;
  1820.    $readmemh ("TEST8.ROM", rom);
  1821.    dbg_limitcycles = 1;
  1822.    dbg_maxcycles = 500;
  1823. end
  1824. endtask
  1825. task test9;
  1826. begin
  1827.    $display ("SYNTHETIC PIC 2.0.  This is TEST #9");
  1828.    #1;
  1829.    // Watch All ports
  1830.    dbg_showportb = 1;
  1831.    dbg_showportc = 1;
  1832.    $readmemh ("TEST9.ROM", rom);
  1833.    dbg_limitcycles = 1;
  1834.    dbg_maxcycles = 2000;
  1835. end
  1836. endtask
  1837. // ******** END Of TEST TASKS
  1838. // Cycles counter
  1839. //
  1840. initial begin
  1841.    cycles = 0;
  1842.    #1;
  1843.    // Don't start counting until after reset.
  1844.    @(negedge reset);
  1845.    
  1846.    forever begin
  1847.       @(posedge clk);
  1848.       cycles = cycles + 1;
  1849.       if ((cycles % 256) == 0) begin
  1850.          if (dbg_showcycles) begin
  1851.             $display ("#Cycles = %0d", cycles);
  1852.          end
  1853.       end
  1854.    
  1855.       if (dbg_limitcycles) begin
  1856.          if (cycles > dbg_maxcycles) begin
  1857.             $display ("Maximum cycles (%0d) Exceeded.  Halting simulation.", dbg_maxcycles);
  1858.             $finish;
  1859.          end
  1860.       end
  1861.    end
  1862. end
  1863. always @(romaddr) begin
  1864.    if (dbg_showrom) 
  1865.       $display ("ROM Address = %h, Data = %h", romaddr, romdata);
  1866. end
  1867. always @(porta) begin
  1868.    if (dbg_showporta)
  1869.       $display ("porta changes to: %h", porta);
  1870. end
  1871. always @(portb) begin
  1872.    if (dbg_showportb)
  1873.       $display ("portb changes to: %h", portb);
  1874. end
  1875. always @(portc) begin
  1876.    if (dbg_showportc)
  1877.       $display ("portc changes to: %h", portc);
  1878. end
  1879. initial begin
  1880.    if (dbg_showw) begin
  1881.       forever begin
  1882.          @(negedge clk);
  1883.          if (debugw != last_debugw) begin
  1884.             $display ("W = %0h", debugw);
  1885.          end
  1886.          last_debugw = debugw;
  1887.       end
  1888.    end
  1889. end
  1890. initial begin
  1891.    if (dbg_showpc) begin
  1892.       forever begin
  1893.          @(negedge clk);
  1894.          $display ("PC = %0h", debugpc);
  1895.       end
  1896.    end
  1897. end
  1898. reg [11:0] last_pc;
  1899. always @(posedge clk) begin
  1900.    last_pc = debugpc;
  1901. end
  1902. initial begin
  1903.    if (dbg_showinst) begin
  1904.       forever begin
  1905.         @(negedge clk);
  1906. if (debuginst[11:0] == 12'b0000_0000_0000) begin
  1907. $display ("%h NOP", last_pc);
  1908. end
  1909. else if (debuginst[11:5] == 7'b0000_001) begin
  1910. $display ("%h MOVWF  f=0x%0h", last_pc, debuginst[4:0]);
  1911. end
  1912. else if (debuginst == 12'b0000_0100_0000) begin
  1913. $display ("%h CLRW", last_pc);
  1914. end
  1915. else if (debuginst[11:5] == 7'b0000_011) begin
  1916. $display ("%h CLRF  f=0x%0h", last_pc, debuginst[4:0]);
  1917. end
  1918. else if (debuginst[11:6] == 7'b0000_10) begin
  1919. if (piccpu_inst.d == 0) $display ("%h SUBWF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1920. else        $display ("%h SUBWF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1921. end
  1922. else if (debuginst[11:6] == 7'b0000_11) begin
  1923. if (piccpu_inst.d == 0) $display ("%h DECF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1924. else        $display ("%h DECF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1925. end
  1926. else if (debuginst[11:6] == 7'b0001_00) begin
  1927. if (piccpu_inst.d == 0) $display ("%h IORWF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1928. else        $display ("%h IORWF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1929. end
  1930. else if (debuginst[11:6] == 7'b0001_01) begin
  1931. if (piccpu_inst.d == 0) $display ("%h ANDWF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1932. else        $display ("%h ANDWF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1933. end
  1934. else if (debuginst[11:6] == 7'b0001_10) begin
  1935. if (piccpu_inst.d == 0) $display ("XORWF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1936. else        $display ("%h XORWF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1937. end
  1938. else if (debuginst[11:6] == 7'b0001_11) begin
  1939. if (piccpu_inst.d == 0) $display ("%h ADDWF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1940. else        $display ("%h ADDWF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1941. end
  1942. else if (debuginst[11:6] == 7'b0010_00) begin
  1943. if (piccpu_inst.d == 0) $display ("%h MOVF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1944. else        $display ("%h MOVF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1945. end
  1946. else if (debuginst[11:6] == 7'b0010_01) begin
  1947. if (piccpu_inst.d == 0) $display ("%h COMF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1948. else        $display ("%h COMF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1949. end
  1950. else if (debuginst[11:6] == 7'b0010_10) begin
  1951. if (piccpu_inst.d == 0) $display ("%h INCF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1952. else        $display ("%h INCF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1953. end
  1954. else if (debuginst[11:6] == 7'b0010_11) begin
  1955. if (piccpu_inst.d == 0) $display ("%h DECFSZ  f=0x%0h, W", last_pc, debuginst[4:0]);
  1956. else        $display ("%h DECFSZ  f=0x%0h, f", last_pc, debuginst[4:0]);
  1957. end
  1958. else if (debuginst[11:6] == 7'b0011_00) begin
  1959. if (piccpu_inst.d == 0) $display ("%h RRF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1960. else        $display ("%h RRF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1961. end
  1962. else if (debuginst[11:6] == 7'b0011_01) begin
  1963. if (piccpu_inst.d == 0) $display ("%h RLF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1964. else        $display ("%h RLF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1965. end
  1966. else if (debuginst[11:6] == 7'b0011_10) begin
  1967. if (piccpu_inst.d == 0) $display ("%h SWAPF  f=0x%0h, W", last_pc, debuginst[4:0]);
  1968. else        $display ("%h SWAPF  f=0x%0h, f", last_pc, debuginst[4:0]);
  1969. end
  1970. else if (debuginst[11:6] == 7'b0011_11) begin
  1971. if (piccpu_inst.d == 0) $display ("%h INCFSZ  f=0x%0h, W", last_pc, debuginst[4:0]);
  1972. else        $display ("%h INCFSZ  f=0x%0h, f", last_pc, debuginst[4:0]);
  1973. end
  1974. // Bit-Oriented File Register Operations
  1975. else if (debuginst[11:8] == 4'b0100) begin
  1976. $display ("%h BCF  f=0x%0h, bit=%0d", last_pc, debuginst[4:0], piccpu_inst.b);
  1977. end
  1978. else if (debuginst[11:8] == 4'b0101) begin
  1979. $display ("%h BCF  f=0x%0h, bit=%0d", last_pc, debuginst[4:0], piccpu_inst.b);
  1980. end
  1981. else if (debuginst[11:8] == 4'b0110) begin
  1982. if (piccpu_inst.skip) $display ("%h BTFSC  f=0x%0h, bit=%0d  {Will Skip..}", last_pc, debuginst[4:0], piccpu_inst.b);
  1983. else      $display ("%h BTFSC  f=0x%0h, bit=%0d  {Will NOT Skip..}", last_pc, debuginst[4:0], piccpu_inst.b);
  1984. end
  1985. else if (debuginst[11:8] == 4'b0111) begin
  1986. if (piccpu_inst.skip) $display ("%h BTFSS  f=0x%0h, bit=%0d  {Will Skip..}", last_pc, debuginst[4:0], piccpu_inst.b);
  1987. else      $display ("%h BTFSS  f=0x%0h, bit=%0d  {Will NOT Skip..}", last_pc, debuginst[4:0], piccpu_inst.b);
  1988. end
  1989. // Literal and Control Operations
  1990. else if (debuginst[11:0] == 16'b0000_0000_0010) begin
  1991. $display ("%h OPTION", last_pc);
  1992. end
  1993. else if (debuginst[11:0] == 16'b0000_0000_0011) begin
  1994. $display ("%h SLEEP", last_pc);
  1995. end
  1996. else if (debuginst[11:0] == 16'b0000_0000_0100) begin
  1997. $display ("%h CLRWDT", last_pc);
  1998. end
  1999. else if (debuginst[11:3] == 13'b0000_0000_0) begin
  2000. $display ("%h TRIS,  f=0x%0h", last_pc, debuginst[2:0]);
  2001. end
  2002. else if (debuginst[11:8] == 4'b1000) begin
  2003. $display ("%h RETLW,  k=0x%0h", last_pc, debuginst[7:0]);
  2004. end
  2005. else if (debuginst[11:8] == 4'b1001) begin
  2006. $display ("%h CALL,  k=0x%0h", last_pc, debuginst[7:0]);
  2007. end
  2008. else if (debuginst[11:9] == 3'b101) begin
  2009. $display ("%h GOTO,  k=0x%0h", last_pc, debuginst[8:0]);
  2010. end
  2011. else if (debuginst[11:8] == 4'b1100) begin
  2012. $display ("%h MOVLW,  k=0x%0h", last_pc, debuginst[7:0]);
  2013. end
  2014. else if (debuginst[11:8] == 4'b1101) begin
  2015. $display ("%h IORLW,  k=0x%0h", last_pc, debuginst[7:0]);
  2016. end
  2017. else if (debuginst[11:8] == 4'b1110) begin
  2018. $display ("%h ANDLW,  k=0x%0h", last_pc, debuginst[7:0]);
  2019. end
  2020. else if (debuginst[11:8] == 4'b1111) begin
  2021. $display ("%h XORLW,  k=0x%0h", last_pc, debuginst[7:0]);
  2022. end
  2023. else begin
  2024. $display ("Hmmm!  instruction not recognized?! %0h", debuginst);
  2025. end
  2026.       end
  2027.    end
  2028. end
  2029. endmodule