?? test.v
字號:
//task dds_test; begin $display ("Free-RISC8 1.0. This is the DDS Demo."); #1; $display ("Loading program memory with %s", "dds.rom"); $readmemh ("dds.rom", pram.mem); fork // Capture data capture_data; // Run the clock drive_clock; // Do a reset reset_pic; // Monitor the number of cycles and set an absolute maximum number of cycles. monitor_cycles (3000); // <--- this appeared about right for DDS demo to finish all bits // More specific monitors //monitor_inst; //monitor_portb; //monitor_portc; // Catch end of simulation event due to max number of cycles or pattern from PIC code. begin @(ENDSIM); // Catch the event. // Got it! $display ("End of simulation signalled. Killing simulation in a moment."); #0; // Let anything else see this event... $finish; end join endendtask// ***************************** Generic Tasks ************************** //// CYCLE monitor and end-of-simulation checker.//task monitor_cycles; input max_cycles; integer max_cycles; integer cycles; begin cycles = 0; fork // Count cycles. forever begin @(posedge clk); cycles = cycles + 1; end // Watch for max cycles. If we detect max cycles then throw our testbench ENDSIM event. // begin wait (cycles == max_cycles); $display ("MAXIMUM CYCLES EXCEEDED!"); ->ENDSIM; end join endendtask// Generic Debug Display stuff.//task monitor_rom; begin forever begin @(negedge clk); $display ("ROM Address = %h, Data = %h", pramaddr, pramdata); end endendtasktask monitor_porta; reg [7:0] last_porta; begin forever begin @(negedge clk); if (last_porta !== porta) begin $display ("porta changes to: %h", porta); last_porta = porta; end end end endtasktask monitor_portb; reg [7:0] last_portb; begin forever begin @(negedge clk); if (last_portb !== portb) begin $display ("MONITOR_PORTB: Port B changes to: %h", portb); last_portb = portb; end end endendtasktask monitor_portc; reg [7:0] last_portc; begin forever begin @(negedge clk); if (last_portc !== portc) begin $display ("MONITOR_PORTC: Port C changes to: %h", portc); last_portc = portc; end end endendtasktask monitor_w; reg [7:0] last_w; begin forever begin @(negedge clk); if (debugw !== last_w) begin $display ("W = %0h", debugw); end last_w = debugw; end endendtasktask monitor_pc; begin forever begin @(negedge clk); $display ("PC = %0h", debugpc); end endendtask// Monitor the INST register (e.g. the instruction) and display something// resembling a disassembler output. We'll use several helping tasks to// look up an appopriate mnemonic.//task monitor_inst; reg [11:0] last_pc; integer opcode; reg [8*8-1:0] mnemonic; begin fork // Always keep a copy of the LAST value of the PC. This is because // of our pipelining. The PC is really one value ahead. You really // want to see the address that corresponds to the instruction you // are looking at. // forever begin @(posedge clk); last_pc = debugpc; end begin #6; forever begin @(negedge clk); // OK. We have an instruction. Take this instruction and call some tasks // to help us display a pretty output line. We will look up a nice mnemonic, etc. // lookup_opcode (debuginst, opcode); // Look up a simpler "opcode" number instead of the actual instruction. lookup_mnemonic (opcode, mnemonic); // Look up the ASCII instruction name // Depending on the specific instruction, we want to print out different stuff. // We may need to print out the 'K' field for literal instructions, or the 'f' field // for the MOVF types of instruction, or only the address and mnemonic for // simple instructions like SLEEP or CLRW. // if (opcode == CLRW || opcode == NOP || opcode == CLRWDT || opcode == OPTION || opcode == SLEEP) begin // These are instructions with no additional arguments. Display the PC and MNEMONIC only. // $display ("MONITOR_INST: %h %s", last_pc, mnemonic); end else if (debuginst[11:10] == 2'b00) begin // These are the instructions with a register address. Display the 'd' and 'f' fields. // $display ("MONITOR_INST: %h %s %0d(0x%h), %s", last_pc, mnemonic, debuginst[4:0], debuginst[4:0], (debuginst[5]) ? "f" : "W" ); end else if (debuginst[11:10] == 2'b01) begin // These are the "Bit-Oriented" instructions with a bit reference and register address. // Display the 'b' and 'f' fields. // $display ("MONITOR_INST: %h %s bit=%d, f=%0d(0x%h)", last_pc, mnemonic, debuginst[7:5], debuginst[4:0], debuginst[4:0] ); end else if (debuginst[11] == 1'b1) begin // These are the "Literal and Control" instructions with a literal field. Display the 'k' field. // $display ("MONITOR_INST: %h %s %0d(0x%h)", last_pc, mnemonic, debuginst[7:0], debuginst[7:0] ); end else begin $display ("MONITOR_INST: --- Unhandled instruction.. %h", debuginst); end end end join endendtask// Given the actual 12-bit instruction, return the "opcode". This is just an integer number// to help us handle printing and such and does NOT correspond to any hardware encoding.//task lookup_opcode; input inst; output opcode; reg [11:0] inst; integer opcode; begin casex (inst) 12'b0000_0000_0000: opcode = NOP; 12'b0000_001X_XXXX: opcode = MOVWF; 12'b0000_0100_0000: opcode = CLRW; 12'b0000_011X_XXXX: opcode = CLRF; 12'b0000_10XX_XXXX: opcode = SUBWF; 12'b0000_11XX_XXXX: opcode = DECF; 12'b0001_00XX_XXXX: opcode = IORWF; 12'b0001_01XX_XXXX: opcode = ANDWF; 12'b0001_10XX_XXXX: opcode = XORWF; 12'b0001_11XX_XXXX: opcode = ADDWF; 12'b0010_00XX_XXXX: opcode = MOVF; 12'b0010_01XX_XXXX: opcode = COMF; 12'b0010_10XX_XXXX: opcode = INCF; 12'b0010_11XX_XXXX: opcode = DECFSZ; 12'b0011_00XX_XXXX: opcode = RRF; 12'b0011_01XX_XXXX: opcode = RLF; 12'b0011_10XX_XXXX: opcode = SWAPF; 12'b0011_11XX_XXXX: opcode = INCFSZ; // *** Bit-Oriented File Register Operations 12'b0100_XXXX_XXXX: opcode = BCF; 12'b0101_XXXX_XXXX: opcode = BSF; 12'b0110_XXXX_XXXX: opcode = BTFSC; 12'b0111_XXXX_XXXX: opcode = BTFSS; // *** Literal and Control Operations 12'b0000_0000_0010: opcode = OPTION; 12'b0000_0000_0011: opcode = SLEEP; 12'b0000_0000_0100: opcode = CLRWDT; 12'b0000_0000_0101: opcode = TRIS; 12'b0000_0000_0110: opcode = TRIS; 12'b0000_0000_0111: opcode = TRIS; 12'b1000_XXXX_XXXX: opcode = RETLW; 12'b1001_XXXX_XXXX: opcode = CALL; 12'b101X_XXXX_XXXX: opcode = GOTO; 12'b1100_XXXX_XXXX: opcode = MOVLW; 12'b1101_XXXX_XXXX: opcode = IORLW; 12'b1110_XXXX_XXXX: opcode = ANDLW; 12'b1111_XXXX_XXXX: opcode = XORLW; default: opcode = 0; endcase endendtask// Given the opcode (see task 'lookup_opcode') return the ASCII string for the instruction.//task lookup_mnemonic; input opcode; output mnemonic; integer opcode; reg [8*8-1:0] mnemonic; begin case (opcode) NOP: mnemonic = "NOP "; MOVWF: mnemonic = "MOVWF "; CLRW: mnemonic = "CLRW "; CLRF: mnemonic = "CLRF "; SUBWF: mnemonic = "SUBWF "; DECF: mnemonic = "DECF "; IORWF: mnemonic = "IORWF "; ANDWF: mnemonic = "ANDWF "; XORWF: mnemonic = "XORWF "; ADDWF: mnemonic = "ADDWF "; MOVF: mnemonic = "MOVF "; COMF: mnemonic = "COMF "; INCF: mnemonic = "INCF "; DECFSZ: mnemonic = "DECFSZ "; RRF: mnemonic = "RRF "; RLF: mnemonic = "RLF "; SWAPF: mnemonic = "SWAPF "; INCFSZ: mnemonic = "INCFSZ "; // *** Bit-Oriented File Register Operations BCF: mnemonic = "BCF "; BSF: mnemonic = "BSF "; BTFSC: mnemonic = "BTFSC "; BTFSS: mnemonic = "BTFSS "; // *** Literal and Control Operations OPTION: mnemonic = "OPTION "; SLEEP: mnemonic = "SLEEP "; CLRWDT: mnemonic = "CLRWDT "; TRIS: mnemonic = "TRIS "; RETLW: mnemonic = "RETLW "; CALL: mnemonic = "CALL "; GOTO: mnemonic = "GOTO "; MOVLW: mnemonic = "MOVLW "; IORLW: mnemonic = "IORLW "; ANDLW: mnemonic = "ANDLW "; XORLW: mnemonic = "XORLW "; default: mnemonic = "-XXXXXX-"; endcase endendtaskendmodule
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -