[课程总结]数学电路逻辑设计实验总结

课程实验网页:课程概况 - 数字逻辑设计(2023秋季)
哈工大(深圳) (gitee.io)

各个元器件的实现

3-8译码器

module decoder_38 (
	input  wire [2:0] en,
	input  wire [2:0] data_in,
	output reg  [7:0] data_out
);

always @ (*) begin
	if (en == 3'b100) begin
	    case (data_in)
		    3'h0 : data_out = 8'hfe;
			3'h1 : data_out = 8'hfd;
			3'h2 : data_out = 8'hfb;
			3'h3 : data_out = 8'hf7;
			3'h4 : data_out = 8'hef;
			3'h5 : data_out = 8'hdf;
			3'h6 : data_out = 8'hbf;
			3'h7 : data_out = 8'h7f;
			default : data_out = 8'hff;
		endcase
	end
	else data_out = 8'hff;
end

endmodule

多路选择器

在select 分别为1 和0 下,进行不同的运算

module multiplexer (
	input  wire enable,
	input  wire select,
	input  wire [3:0] input_a, input_b,
	output reg  [3:0] led
);

always @ * begin
	if (enable == 1'b1)
		if(select == 1'b1)
			led = input_a - input_b;
		else 
			led = input_a + input_b;
	else led = 4'b1111;
	end
endmodule

8位寄存器堆(一堆八个)

[课程总结]数学电路逻辑设计实验总结_第1张图片

8个8位寄存器(复位clr为1时清0,写操作en为1时写入,其他时间保持不变)

8位寄存器如下:

module dff8 (
    input clk,
    input [7:0] d,
    input en,
    input clr,
    output reg [7:0] q 
);

always @(posedge clk or posedge clr) begin
    if(clr == 1'b1) 
        q[7:0] <= 8'b0;
    else if(en == 1'b1) 
        q[7:0] <= d[7:0];
    else q[7:0] <= q[7:0];
end
    
endmodule

8个这样的8位寄存器就是在实例化的时候,实例化八个,并用三八译码器来选择用哪个来存储,用三八译码器来选择哪个来展示。

三八译码器来选择用哪个来存储时,译码器翻译写操作rsel,连接8个8位寄存器的使能端。

以下是对八路8位信号进行选择,根据输入的rsel选择 输出(Y)的一路。

module Vrmux8in8b_b (
    input [2:0] rsel,
    input [7:0] r0,r1,r2,r3,r4,r5,r6,r7,
    output reg [7:0] Y
);

always @(*) begin
    case (rsel)
        3'h0 : Y = r0;
        3'h1 : Y = r1;
        3'h2 : Y = r2;
        3'h3 : Y = r3;
        3'h4 : Y = r4;
        3'h5 : Y = r5;
        3'h6 : Y = r6;
        3'h7 : Y = r7;
        default : Y = 8'b0;
    endcase
end
    
endmodule

流水灯(计数器设计)

基于计数器,实现时间间隔可调的的8bits循环左移流水灯

首先得有流水灯切换控制信号,控制不同的时间间隔(时间间隔由计数器控制)。灯的流动其实就是移位信号。

受按键控制下的计数器

module counter(
    input wire clk,
    input wire rst,
    input wire button
);

reg [3:0] cnt;    //计数器的数字
reg       cnt_inc;   //计数器开始计数条件

wire cnt_end = cnt_inc & (cnt==4'h9);  //cnt_end计满的标识符,可以自己调cnt等于多少


always @ (posedge clk or posedge rst) begin
    if(rst)   cnt_inc <= 1'b0;          
    else if(button) cnt_inc <= 1'b1;       //在控件按键button为1下,计数条件cnt_inc才为1
    else if(cnt_end) cnt_inc <= 1'b0;   //计满后,增长的数字cnt_inc变为0
end

always @ (posedge clk or posedge rst) begin
    if(rst)       cnt <= 4'h0;          
    else if(cnt_end) cnt <= 4'h0;       //计满后,数字清为0
    else if(cnt_inc) cnt <= cnt + 4'h1;  //计数条件cnt_inc为1时,(时钟沿到来时)数字cnt增一
end 

按键打二拍操作

signal为外界按键信号,pos_edge只持续一个时钟周期

[课程总结]数学电路逻辑设计实验总结_第2张图片

always @(posedge clk) begin
    if(rst) sig_r0 <= 1'b0;
    else  sig_r0 <= signal;
end

always @(posedge clk) begin
    if(rst) sig_r1 <= 1'b0;
    else   sig_r1 <= sig_r0;
end

assign pos_edge = ~sig_r1 & sig_r0;  //sig_r1为0,sig_r0为1时才有pos_edge为1

同一个按键启停

button为0时,与1(pos_edge=1 按键按下)异或,结果为1

button为1时,与1(pos_edge=1 按键按下)异或,结果为0

实现翻转

always @(posedge clk or posedge rst) begin
    if(rst) button <= 1'b0;
    else 
       button <= pos_edge^button;   //异或
end

灯的流转

always @(posedge clk or posedge rst) begin
    if(rst) led <= 8'b00000001;
    else if(cnt_end )   led <= {led[6:0], led[7]};
end

注意事项

  • if-else 要考虑全所有的情况(不能只盯着自己要实现的),否则会有不稳定的情况出现
  • d 是十进制  h 是十六进制
  • 常数一定带位宽和进制,变量使位宽相同后再赋值
  • button=~button这种类型的,只能在时序里出现

你可能感兴趣的:(verilog,fpga开发)