📄 piccore.v
字号:
end end else begin intstart_reg <= 1'b0; end // 2-5-2-7. Set/clear /PD and /TO flags if (intstart_reg == 1'b0) begin if (INST_CLRWDT == 1'b1 || (INST_SLEEP == 1'b1 && (wdtreset_node == 1'b0 && intstart_reg == 1'b0))) begin // CLRWDT or (SLEEP and no interrupt trigger) // see pp.46,58 and 66 of PIC16F84 data-sheet if (INST_SLEEP == 1'b1) begin sleepflag_reg <= 1'b1; status_reg[4:3] <= 2'b10; // SLEEP: /T0,/PD = 1,0 end else begin // (INST_CLRWDT) status_reg[4:3] <= 2'b11; // CLRWDT: /T0,/PD = 1,1 end end end end // (if not stalled) // 2-5-3. Clear data-SRAM write enable (hazard-free) writeram_reg <= 1'b0; // 2-5-4. Change clkout output clkout_reg <= 1'b0; // 2-5-5. Check increment-TMR0 request if (inctmr_sync_reg == 2'b01) begin inctmrhold_reg <= 1'b1; end // 2-5-6. Goto next cycle if (reset_cond == 1'b1) begin state_reg <= Qreset; end else begin state_reg <= Q1; end end // 2-6. Illegal states (NEVER REACHED in normal execution) default: begin state_reg <= Qreset; // goto reset state end endcase end // TMR0 pre-scaler (see pp.27 of PIC16F84 data sheet) // select pre-scaler assign psck = (option_reg[5] == 1'b0) ? (clkout_reg) // option_reg(5):T0CS : (t0cki ^ option_reg[4]); // option_reg(4):T0SE // pre-scaler body reg [7:0] rateval; always @(posedge psck or negedge ponrst_n) begin if (ponrst_n == 1'b0) begin pscale_reg <= 0; ps_full_reg <= 1'b0; end else begin case (option_reg[2:0]) // select prescaler-full value by PS2-0 3'b000: begin rateval = 1; end 3'b001: begin rateval = 3; end 3'b010: begin rateval = 7; end 3'b011: begin rateval = 15; end 3'b100: begin rateval = 31; end 3'b101: begin rateval = 63; end 3'b110: begin rateval = 127; end// 3'b111: rateval = 255; default: begin rateval = 255; end endcase if (pscale_reg >= rateval) begin pscale_reg <= 0; ps_full_reg <= 1'b1; end else begin pscale_reg <= pscale_reg + 1; ps_full_reg <= 1'b0; end end end // select TMR0-increment trigger assign inctmrck = (option_reg[3] == 1'b1) ? (psck) // option_reg(3):PSA : (ps_full_reg); // ps_full_reg:output of pre-scaler// WDT timer body reg wdtfull_node; wire wdt_reset_n_node; assign wdt_reset_n_node = (ponrst_n == 1'b0 || mclr_n == 1'b0) ? 1'b0 : 1'b1; always @(posedge wdtclk or negedge wdt_reset_n_node) begin if (wdt_reset_n_node == 1'b0) begin // (async reset) wdt_reg <= 0; wdt_full_reg <= 1'b0; wdtclr_req_reg <= 2'b00; wdtfullclr_req_reg <= 2'b00; end else begin // synchronizers // WDT-clear request (CLRWDT/SLEEP instruction) wdtclr_req_reg[0] <= wdt_clr_reg; // (do not AND with sleepflag_reg, since WDT should be cleared at SLEEP instruction) wdtclr_req_reg[1] <= wdtclr_req_reg[0]; // WDT-full-clear request (after WDT reset) wdtfullclr_req_reg[0] <= wdtfull_clr_reg & ( ~sleepflag_reg); wdtfullclr_req_reg[1] <= wdtfullclr_req_reg[0]; // timer/full reg if (wdt_reg >= 255) begin wdtfull_node = 1'b1; // (intermidiate node) end else begin wdtfull_node = 1'b0; // (intermidiate node) end // wdt_reg(counter) body if (wdtclr_req_reg == 2'b01 || wdtena == 1'b0) begin wdt_reg <= 0; end else if (wdtfull_node == 1'b1) begin wdt_reg <= 0; end else begin wdt_reg <= wdt_reg + 1; end // wdt_full_reg(interrupt trigger) body if (wdtfullclr_req_reg == 2'b01 || wdtena == 1'b0) begin wdt_full_reg <= 1'b0; end else if (wdtfull_node == 1'b1) begin wdt_full_reg <= 1'b1; end end end assign wdtclr_ack = wdtclr_req_reg[1]; // WDT-clear ack signal to CPU assign wdtfull = wdt_full_reg; // WDT-full signal (interrupt trigger) to CPU// WDT controller in CPU-clock line (handshake-interface between WDT and CPU-EFSM) always @(posedge clkin) begin if (poweron_sync_reg == 1'b0 || mclr_sync_reg == 1'b0) begin wdt_clr_reg <= 1'b0; // WDT clear request register wdt_clr_reqhold_reg <= 1'b0; // will be 1 when WDT clear request comes while another clear request is still processed wdtfull_clr_reg <= 1'b0; // WDT-full clear request register end else begin // WDT-clear/hold WDT-clear request // (handshake) if (wdt_clr_reg == 1'b1) begin // still processing clear-operation if (wdtclr_ack_sync_reg == 1'b1) begin // if ack comes, go down the clear request wdt_clr_reg <= 1'b0; end end else if (wdt_clr_reqhold_reg == 1'b1 || (state_reg == Q4 && exec_op_reg == 1'b1 && intstart_reg == 1'b0 && (INST_CLRWDT == 1'b1 || INST_SLEEP == 1'b1))) begin // clear request comes if (wdtclr_ack_sync_reg == 1'b0) begin // confirm if ack is 0 wdt_clr_reg <= 1'b1; wdt_clr_reqhold_reg <= 1'b0; end else begin // (wait until ack becomes 0) wdt_clr_reqhold_reg <= 1'b1; end end // clear WDT-full (CPU reset request) // (handshake) if (wdtfull_clr_reg == 1'b1) begin // still processing clear-operation if (wdt_full_sync_reg[1] == 1'b0) begin // if ack comes, go down the clear request wdtfull_clr_reg <= 1'b0; end end else if (wdt_full_sync_reg[1] == 1'b1) begin // clear request comes // the WDT-full signal does not come so often, so hold-register is not necessary wdtfull_clr_reg <= 1'b1; end end end// Detect external interrupt requests // INT0 I/F wire i0rst_node; assign i0rst_node = intclr_reg[0]; always @(posedge int0 or posedge i0rst_node) begin if (i0rst_node == 1'b1) begin intrise_reg[0] <= 1'b0; end else begin // catch positive edge intrise_reg[0] <= 1'b1; end end always @(negedge int0 or posedge i0rst_node) begin if (i0rst_node == 1'b1) begin intdown_reg[0] <= 1'b0; end else begin // catch negative edge intdown_reg[0] <= 1'b1; end end assign rb0_int = (option_reg[6] == 1'b1) ? (intrise_reg[0]) // option_reg(6):INTEDG : (intdown_reg[0]); // INT4 I/F wire i4rst_node; assign i4rst_node = intclr_reg[1]; always @(posedge int4 or posedge i4rst_node) begin if (i4rst_node == 1'b1) begin intrise_reg[1] <= 1'b0; end else begin // catch positive edge intrise_reg[1] <= 1'b1; end end always @(negedge int4 or posedge i4rst_node) begin if (i4rst_node == 1'b1) begin intdown_reg[1] <= 1'b0; end else begin // catch negative edge intdown_reg[1] <= 1'b1; end end assign rb4_int = intrise_reg[1] | intdown_reg[1]; // INT5 I/F wire i5rst_node; assign i5rst_node = intclr_reg[2]; always @(posedge int5 or posedge i5rst_node) begin if (i5rst_node == 1'b1) begin intrise_reg[2] <= 1'b0; end else begin // catch positive edge intrise_reg[2] <= 1'b1; end end always @(negedge int5 or posedge i5rst_node) begin if (i5rst_node == 1'b1) begin intdown_reg[2] <= 1'b0; end else begin // catch negative edge intdown_reg[2] <= 1'b1; end end assign rb5_int = intrise_reg[2] | intdown_reg[2]; // INT6 I/F wire i6rst_node; assign i6rst_node = intclr_reg[3]; always @(posedge int6 or posedge i6rst_node) begin if (i6rst_node == 1'b1) begin intrise_reg[3] <= 1'b0; end else begin // catch positive edge intrise_reg[3] <= 1'b1; end end always @(negedge int6 or posedge i6rst_node) begin if (i6rst_node == 1'b1) begin intdown_reg[3] <= 1'b0; end else begin // catch negative edge intdown_reg[3] <= 1'b1; end end assign rb6_int = intrise_reg[3] | intdown_reg[3]; // INT7 I/F wire i7rst_node; assign i7rst_node = intclr_reg[4]; always @(posedge int7 or posedge i7rst_node) begin if (i7rst_node == 1'b1) begin intrise_reg[4] <= 1'b0; end else begin // catch positive edge intrise_reg[4] <= 1'b1; end end always @(negedge int7 or posedge i7rst_node) begin if (i7rst_node == 1'b1) begin intdown_reg[4] <= 1'b0; end else begin // catch negative edge intdown_reg[4] <= 1'b1; end end assign rb7_int = intrise_reg[4] | intdown_reg[4];// Decode INT triggers (do not AND with GIE(intcon_reg(7)), since these signals are also used for waking up from SLEEP) assign inte = intcon_reg[4] & rb0_int; // G0IE and raw-trigger signal assign rbint = intcon_reg[3] & (rb4_int | rb5_int | rb6_int | rb7_int); // RBIE and raw-trigger signal// Circuit's output siganals assign progadr = pc_reg; // program ROM address//> modified ver1.00c, 2002/08/07// assign ramadr = ramadr_reg; // data RAM address // map 0F0-0FF,170-17F, and 1F0-1FF into 070-07F assign ramadr = (ramadr_node[6:4] != 3'b111) ? (ramadr_node) : ({5'b00111, ramadr_node[3:0]}); // data RAM address//< assign ramdtout = aluout_reg; // data RAM write data//> modified ver1.00c, 2002/08/07// assign readram = (state_reg[1:0] = 2'b01) ? 1'b1 : 1'b0; // data RAM read enable (1 when state_reg = Q2) assign readram = ~writeram_reg;//< assign writeram = writeram_reg; // data RAM write enable assign eepadr = eeadr_reg; // EEPROM address assign eepdtout = eedata_reg; // EEPROM write data assign readeepreq = eecon1_reg[0]; // EEPROM read request assign writeeepreq = eecon1_reg[1]; // EEPROM write request assign porta_out = portaout_reg; // PORT-A output assign porta_dir = trisa_reg; // PORT-A direction assign portb_out = portbout_reg; // PORT-B output assign portb_dir = trisb_reg; // PORT-B direction assign rbpu = option_reg[7]; // RBPU: pull-up enable assign clkout = clkout_reg; // clkout (clkin/4) output assign powerdown = sleepflag_reg; // CPU clock stop indicator assign startclkin = inte | rbint | wdt_full_reg | ( ~mclr_n) | ( ~ponrst_n); // CPU clock start indicatorendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -