HC165.v
/**https://docs.wokwi.com/zh-CN/parts/wokwi-74hc165
**/
`timescale 1ns / 1ps
module HC165 (input wire i_clk, // 全局系统时钟(用于串行输出寄存)input wire i_rst_n, // 异步复位(低有效)input wire PL, //串行输出input wire CP, // 移位时钟(上升沿有效)input wire [7:0] D, // 并行输入 D0~D7output wire Q7 // 串行输出
);reg [7:0] r_shift_reg;// 并行加载或串行移位always @(posedge i_clk or negedge i_rst_n) beginif (!i_rst_n)r_shift_reg <= 8'b0;else if (!PL)r_shift_reg <= D;else if (CP) // 移位操作r_shift_reg <= {r_shift_reg[6:0], 1'b0};endassign Q7 = r_shift_reg[7];endmodule
hc165_drive.v
`timescale 1ns / 1psmodule hc165_drive (input wire i_clk, // 系统时钟input wire i_rst_n, // 异步复位(低有效)input wire i_start, // 启动采集output reg [7:0] o_data, // 并转串采集到的数据output reg o_done, // 采集完成信号//接HC165output reg o_pl, // 并行加载信号(低有效)output reg o_cp, // 移位时钟信号input wire i_q7 // 串行数据输入);// 状态机状态定义localparam S_IDLE = 3'd0, // 空闲状态,等待开始信号S_WAIT = 3'd1, // 并行加载等待状态,释放 PLS_LOAD = 3'd2, // 保留状态(未使用)S_SHIFT0 = 3'd3, // 拉低 SCLK 准备移位S_SHIFT1 = 3'd4, // 拉高 SCLK,采样 QH 数据S_DONE = 3'd5; // 移位完成,输出数据reg [2:0] r_state;reg [2:0] r_bit_cnt;reg [7:0] r_shift_reg;always @(posedge i_clk or negedge i_rst_n) beginif (!i_rst_n) begino_pl <= 1'b1;o_cp <= 1'b0;o_data <= 8'd0;o_done <= 1'b0;r_bit_cnt <= 3'd0;r_shift_reg <= 8'd0;r_state <= S_IDLE;end else begincase (r_state)S_IDLE: begino_done <= 1'b0;o_cp <= 1'b0;if (i_start) begino_pl <= 1'b0; // 拉低加载r_state <= S_WAIT;endendS_WAIT: begino_pl <= 1'b1; // 拉高,准备移位r_bit_cnt <= 0;r_state <= S_SHIFT0;endS_SHIFT0: begino_cp <= 1'b0; // 先拉低时钟r_state <= S_SHIFT1;endS_SHIFT1: begino_cp <= 1'b1; // 上升沿触发移位r_shift_reg <= {r_shift_reg[6:0], i_q7};r_bit_cnt <= r_bit_cnt + 1;if (r_bit_cnt == 3'd7)r_state <= S_DONE;elser_state <= S_SHIFT0;endS_DONE: begino_cp <= 1'b0;o_data <= r_shift_reg;o_done <= 1'b1;r_state <= S_IDLE;endendcaseendendendmodule
tb.v
`timescale 1ns / 1psmodule tb;reg clk;reg rst_n;reg start;reg [7:0] d;wire [7:0] data_out;wire pl;wire cp;wire q7;wire done;// 实例化 hc165HC165 u_hc165 (.i_clk (clk),.i_rst_n (rst_n),.PL (pl),.CP (cp),.D (d),.Q7 (q7));// 实例化驱动器hc165_drive u_hc165_drive (.i_clk (clk),.i_rst_n(rst_n),.i_q7 (q7),.i_start(start),.o_pl (pl),.o_cp(cp),.o_data (data_out),.o_done (done));initial clk = 0;always #5 clk = ~clk; // 100MHzinitial beginrst_n = 0;start = 0;d = 8'b0;#20;rst_n = 1;#20;d = 8'b10101010; // 预设要采集的数据start = 1;#10;start = 0;wait (done == 1);#10;$display("Read data: %b", data_out);#20;$finish;endendmodule