数字验证手撕00-初步提纲(拷打无奈版
前言主包在经历了两个月秋招受到面试手撕代码狠狠的拷打之后是在是受不了了决定痛定思痛好好学习手撕以及一些被狠狠拷打的八股等。本章作为提纲总结一下都需要学啥希望能补救的及时八股也得好好看手撕代码div_4module div_4( input clk, input rst, output reg clk_div ); reg [1:0] cnt; always (posedge clk) begin if (rst) begin cnt 2d0; clk_div 1b0; end else begin if (cnt 2d3) begin cnt 2d0; clk_div ~clk_div; end else begin cnt cnt 2d1; end end end endmodulediv_5module div_5( input clk, input rst_n, output wire clk_div ); reg [2:0] cnt; reg clk_pos, clk_neg; always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 1b0; end else begin if (cnt 3d4) begin cnt 1b0; end else begin cnt cnt 3d1; end end end always (posedge clk or negedge rst_n) begin if (!rst_n) begin clk_pos 1d0; end else begin if (cnt 3d2) begin clk_pos 1d1; end else begin clk_pos 1d0; end end end always (negedge clk or negedge rst_n) begin if (!rst_n) begin clk_neg 1d0; end else begin if (cnt 3d2) begin clk_neg 1d1; end else begin clk_neg 1d0; end end end assign clk_div clk_pos | clk_neg; endmoduleseq_1011module seq_1011( input clk, input rst_n, input din, output reg dout ); reg [1:0] state; reg [1:0] next_state; parameter IDLE 2d0, S1 2d1, S10 2d2, S101 2d3; always (posedge clk or negedge rst_n) begin if (!rst_n) begin state IDLE; end else begin state next_state; end end always (*) begin next_state state; case (state) IDLE: begin if (din 1) begin next_state S1; end else begin next_state IDLE; end end S1: begin if (din 1) begin next_state S1; end else begin next_state S10; end end S10: begin if (din 1) begin next_state S101; end else begin next_state IDLE; end end S101: begin if (din 1) begin next_state S1; end else begin next_state S10; end end default: begin next_state IDLE; end endcase end always (*) begin dout 0; if (state S101 din) begin dout 1; end end endmodulesync_fifomodule sync_fifo( input wire clk, input wire rst_n, input wire wr_en, input wire [7:0] din, input wire rd_en, output reg [7:0] dout, output wire empty, output wire full ); reg [7:0] mem [0:7]; reg [2:0] wr_ptr; reg [2:0] rd_ptr; reg [3:0] count; assign full (count 3d8); assign empty (count 3d0); // Write always (posedge clk or negedge rst_n) begin if (!rst_n) begin wr_ptr 3d0; end else if (wr_en !full) begin mem[wr_ptr] din; wr_ptr wr_ptr 3d1; end end // Read always (posedge clk or negedge rst_n) begin if (!rst_n) begin rd_ptr 3d0; dout 8d0; end else if (rd_en !empty) begin dout mem[rd_ptr]; rd_ptr rd_ptr 3d1; end end // Counter always (posedge clk or negedge rst_n) begin if (!rst_n) begin count 3d0; end else begin case ({wr_en !full, rd_en !empty}) 2d2: count count 3d1; 2d1: count count - 3d1; default: count count; endcase end end endmoduleasync_fifomodule async_fifo( input wr_clk, input rd_clk, input rst_n, input wr_en, input [7:0] din, input rd_en, output reg [7:0] dout, output reg full, output reg empty ); reg [8:0] wr_bin; reg [8:0] wr_bin_next; reg [8:0] wr_gray; reg [8:0] wr_gray_next; reg [8:0] wr_gray_sync1; reg [8:0] wr_gray_sync2; reg [8:0] rd_bin; reg [8:0] rd_bin_next; reg [8:0] rd_gray; reg [8:0] rd_gray_next; reg [8:0] rd_gray_sync1; reg [8:0] rd_gray_sync2; reg [7:0] mem [0:255]; wire full_next; wire empty_next; assign wr_bin_next wr_bin ((wr_en !full) ? 1b1 : 1b0); assign wr_gray_next (wr_bin_next 1) ^ wr_bin_next; assign rd_bin_next rd_bin ((rd_en !empty) ? 1b1 : 1b0); assign rd_gray_next (rd_bin_next 1) ^ rd_bin_next; // Write domain always (posedge wr_clk or negedge rst_n) begin if (!rst_n) begin wr_bin 9d0; wr_gray 9d0; full 1b0; end else begin if (wr_en !full) begin mem[wr_bin[7:0]] din; end wr_bin wr_bin_next; wr_gray wr_gray_next; full full_next; end end // Read domain always (posedge rd_clk or negedge rst_n) begin if (!rst_n) begin rd_bin 9d0; rd_gray 9d0; dout 8d0; empty 1b0; end else begin if (rd_en !empty) begin dout mem[rd_bin[7:0]]; end rd_bin rd_bin_next; rd_gray rd_gray_next; empty empty_next; end end // Synchronize read Gray pointer into write clock domain always (posedge wr_clk or negedge rst_n) begin if (!rst_n) begin rd_gray_sync1 9d0; rd_gray_sync2 9d0; end else begin rd_gray_sync1 rd_gray; rd_gray_sync2 rd_gray_sync1; end end // Synchronize write Gray pointer into read clock domain always (posedge rd_clk or negedge rst_n) begin if (!rst_n) begin wr_gray_sync1 9d0; wr_gray_sync2 9d0; end else begin wr_gray_sync1 wr_gray; wr_gray_sync2 wr_gray_sync1; end end assign empty_next (rd_gray_next wr_gray_sync2); assign full_next (wr_gray_next {~rd_gray_sync2[8:7], rd_gray_sync2[6:0]}); endmodulecdc_handshakemodule cdc_handshake ( input wire clk_src, input wire clk_dst, input wire rst_n, input wire src_pluse, output reg dst_pluse, output reg src_busy ); reg req_src; reg req_sync1; reg req_sync2; reg req_sync2_d; reg ack_dst; reg ack_sync1; reg ack_sync2; always (posedge clk_dst or negedge rst_n)begin if(!rst_n)begin req_sync1 1d0; req_sync2 1d0; req_sync2_d 1d0; end else begin req_sync1 req_src; req_sync2 req_sync1; req_sync2_d req_sync2; end end always (posedge clk_src or negedge rst_n)begin if(!rst_n)begin ack_sync1 1d0; ack_sync2 1d0; end else begin ack_sync1 ack_dst; ack_sync2 ack_sync1; end end always (posedge clk_src or negedge rst_n)begin if(!rst_n)begin req_src 1d0; end else begin if(src_pluse !src_busy)begin req_src 1d1; end else if(ack_sync2) begin req_src 1d0; end end end always (posedge clk_dst or negedge rst_n)begin if(!rst_n)begin ack_dst 1d0; end else begin if(req_sync2)begin ack_dst 1d1; end else begin ack_dst 1d0; end end end assign dst_pluse req_sync2 ~req_sync2_d; assign src_busy req_src | ack_sync2; endmoduleround_robin_arbiter_2module round_robin_arbiter_2( input wire clk, input wire rst_n, input wire req0, input wire req1, output reg gnt0, output reg gnt1 ); //req0 last_gnt 0 //req1 last_gnt 1 reg last_gnt; always(*)begin gnt0 1b0; gnt1 1b0; case({req0,req1}) 2b00:begin gnt0 1b0; gnt1 1b0; end 2b10:begin gnt0 1b1; gnt1 1b0; end 2b01:begin gnt0 1b0; gnt1 1b1; end 2b11:begin if(last_gnt)begin gnt0 1b1; gnt1 1b0; end else begin gnt0 1b0; gnt1 1b1; end end default:begin gnt0 1b0; gnt1 1b0; end endcase end always(posedge clk or negedge rst_n)begin if(!rst_n)begin last_gnt 1b0; end else begin if(req0)begin last_gnt 1b0; end else if(req1) begin last_gnt 1b1; end end end endmoduleround_robin_arbiter_4module round_robin_arbiter_4( input wire clk, input wire rst_n, input wire [3:0] req, output reg [3:0] gnt ); reg [3:0] last_gnt; always(*)begin gnt 4b0000; case(last_gnt) 4d0:begin if(req[1]) gnt 4b0010; else if(req[2]) gnt 4b0100; else if(req[3]) gnt 4b1000; else if(req[0]) gnt 4b0001; end 4d1:begin if(req[2]) gnt 4b0100; else if(req[3]) gnt 4b1000; else if(req[0]) gnt 4b0001; else if(req[1]) gnt 4b0010; end 4d2:begin if(req[3]) gnt 4b1000; else if(req[0]) gnt 4b0001; else if(req[1]) gnt 4b0010; else if(req[2]) gnt 4b0100; end 4d3:begin if(req[0]) gnt 4b0001; else if(req[1]) gnt 4b0010; else if(req[2]) gnt 4b0100; else if(req[3]) gnt 4b1000; end default:begin gnt 4b0000; end endcase end always(posedge clk or negedge rst_n)begin if(!rst_n)begin last_gnt 4d3; end else begin if(gnt[0]) last_gnt 4d0; else if(gnt[1]) last_gnt 4d1; else if(gnt[2]) last_gnt 4d2; else if(gnt[3]) last_gnt 4d3; end end endmodulemod3module mod3( input wire clk, input wire rst_n, input wire din, output reg dout ); reg [1:0] state; reg [1:0] next_state; parameter S0 2d0, S1 2d1, S2 2d2; always(posedge clk or negedge rst_n)begin if(!rst_n)begin state S0; end else begin state next_state; end end always(*)begin next_state state; case(state) S0:begin if(din)begin next_state S1; end else begin next_state S0; end end S1:begin if(din)begin next_state S0; end else begin next_state S2; end end S2:begin if(din)begin next_state S2; end else begin next_state S1; end end default:begin next_state S0; end endcase end always(*)begin if(state S0)begin dout 1b1; end else begin dout 1b0; end end endmodule边沿检测器module edge_detector ( input wire clk, input wire rst_n, input wire din, output wire pos_edge, output wire neg_edge, output wire both_edge ); reg din_d; always (posedge clk or negedge rst_n) begin if (!rst_n) din_d 1b0; else din_d din; end // Rising edge detection assign pos_edge din ~din_d; // Falling edge detection assign neg_edge ~din din_d; // Both-edge detection assign both_edge din ^ din_d; endmodule单 bit CDC 两级同步器module cdc_sync_2ff ( input wire clk_dst, input wire rst_n, input wire async_in, output wire sync_out ); reg sync_ff1; reg sync_ff2; // Two-flop synchronizer always (posedge clk_dst or negedge rst_n) begin if (!rst_n) begin sync_ff1 1b0; sync_ff2 1b0; end else begin sync_ff1 async_in; sync_ff2 sync_ff1; end end assign sync_out sync_ff2; endmodule慢时钟域 → 快时钟域脉冲同步module pulse_sync_slow_to_fast ( input wire clk_dst, input wire rst_n, input wire pulse_src, output wire pulse_dst ); reg sync_ff1; reg sync_ff2; reg sync_ff2_d; always (posedge clk_dst or negedge rst_n) begin if (!rst_n) begin sync_ff1 1b0; sync_ff2 1b0; sync_ff2_d 1b0; end else begin sync_ff1 pulse_src; sync_ff2 sync_ff1; sync_ff2_d sync_ff2; end end // Generate one-cycle pulse assign pulse_dst sync_ff2 ~sync_ff2_d; endmodule快时钟域 → 慢时钟域Toggle 同步module pulse_sync_toggle ( input wire clk_src, input wire clk_dst, input wire rst_n, input wire pulse_src, output wire pulse_dst ); reg toggle_src; reg toggle_sync1; reg toggle_sync2; reg toggle_sync2_d; // Toggle the source bit for every source pulse always (posedge clk_src or negedge rst_n) begin if (!rst_n) toggle_src 1b0; else if (pulse_src) toggle_src ~toggle_src; end // Synchronize toggle bit into destination domain always (posedge clk_dst or negedge rst_n) begin if (!rst_n) begin toggle_sync1 1b0; toggle_sync2 1b0; toggle_sync2_d 1b0; end else begin toggle_sync1 toggle_src; toggle_sync2 toggle_sync1; toggle_sync2_d toggle_sync2; end end // Detect any toggle change assign pulse_dst toggle_sync2 ^ toggle_sync2_d; endmodule脉冲展宽module pulse_stretcher ( input wire clk, input wire rst_n, input wire pulse_in, output wire pulse_out ); reg [2:0] cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 3d0; end else begin if (pulse_in) begin cnt 3d4; end else if (cnt ! 3d0) begin cnt cnt - 1b1; end end end assign pulse_out (cnt ! 3d0); endmodule串转并 SIPOmodule sipo ( input wire clk, input wire rst_n, input wire serial_in, output reg [7:0] parallel_out, output reg data_valid ); reg [7:0] shift_reg; reg [2:0] bit_cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) begin shift_reg 8d0; parallel_out 8d0; bit_cnt 3d0; data_valid 1b0; end else begin // Default value data_valid 1b0; // Shift in one serial bit shift_reg {shift_reg[6:0], serial_in}; if (bit_cnt 3d7) begin parallel_out {shift_reg[6:0], serial_in}; bit_cnt 3d0; data_valid 1b1; end else begin bit_cnt bit_cnt 1b1; end end end endmodule并转串 PISOmodule piso ( input wire clk, input wire rst_n, input wire load, input wire [7:0] parallel_in, output wire serial_out ); reg [7:0] shift_reg; assign serial_out shift_reg[7]; always (posedge clk or negedge rst_n) begin if (!rst_n) begin shift_reg 8d0; end else begin if (load) shift_reg parallel_in; else shift_reg {shift_reg[6:0], 1b0}; end end endmodule模 N 计数器module mod_n_counter #( parameter N 10, parameter WIDTH 4 )( input wire clk, input wire rst_n, input wire en, output reg [WIDTH-1:0] cnt ); always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 0; end else if (en) begin if (cnt N - 1) cnt 0; else cnt cnt 1b1; end end endmodule加减计数器module up_down_counter ( input wire clk, input wire rst_n, input wire en, input wire up_down, output reg [7:0] cnt ); always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 8d0; end else if (en) begin if (up_down) cnt cnt 1b1; else cnt cnt - 1b1; end end endmodule饱和计数器module saturating_counter ( input wire clk, input wire rst_n, input wire en, input wire up_down, output reg [7:0] cnt ); always (posedge clk or negedge rst_n) begin if (!rst_n) begin cnt 8d0; end else if (en) begin if (up_down) begin // Saturate at maximum value if (cnt ! 8hFF) cnt cnt 1b1; end else begin // Saturate at minimum value if (cnt ! 8h00) cnt cnt - 1b1; end end end endmodule找最低位第一个 1module priority_encoder_8 ( input wire [7:0] din, output reg [2:0] pos, output reg valid ); always (*) begin pos 3d0; valid 1b1; if (din[0]) pos 3d0; else if (din[1]) pos 3d1; else if (din[2]) pos 3d2; else if (din[3]) pos 3d3; else if (din[4]) pos 3d4; else if (din[5]) pos 3d5; else if (din[6]) pos 3d6; else if (din[7]) pos 3d7; else begin pos 3d0; valid 1b0; end end endmodule提取最低位的 1module isolate_lowest_one ( input wire [7:0] din, output wire [7:0] dout ); assign dout din (~din 1b1); endmodulePWMmodule pwm ( input wire clk, input wire rst_n, input wire [7:0] duty, output wire pwm_out ); reg [7:0] cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) cnt 8d0; else cnt cnt 1b1; end assign pwm_out (cnt duty); endmodule