首页 > 其他分享 >EDA联系代码

EDA联系代码

时间:2023-03-03 22:12:24浏览次数:45  
标签:begin EDA 联系 clk res 代码 module input reg

B站大学的课程【Verilog零基础入门】 虽然写的0基础,但是并没有像其他语言那样讲解,建议不管什么先跟写,熬过两集慢慢就会理解,不会的问题也可以去搜

仿真软件为modelsim

百度云:链接: https://pan.baidu.com/s/1iD-Ryn6DVSujovU7_Tb9ew 提取码: 4t91 复制这段内容后打开百度网盘手机App,操作更方便哦)
破解方式

  1. 运行MentorKG.exe,生成LICENSE.txt,把后缀改成.dat,
  2. 将MentorKG.exe和patch_dll.bat放在安装目录win64文件夹下
  3. dos中运行patch_dll.bat
  4. LICENSE.dat文件放在安装目录win64下面
  5. 配置下环境变量重启,添加环境变量名LM_LICENSE_FILE,值为LICENSE.dat路径

软件仿真的基础使用上面教程的第一集就有,很简单

基本逻辑门

非门

注意,仿真软件基本都不支持中文,一编译或重新打开很容易中文乱码,注释建议写英文,开始可能会吃力,用翻译软件,用的多了也就会一些了。下面的中文注释方便阅读

`timescale 1ns/10ps    // 时间单位/精度
module inv(A,Y);
    input A;
    output Y;
    
    assign Y=~A;

endmodule

// testbench of inv  测试函数
module inv_tb();
reg aa;    //输入定义reg register寄存器
wire yy;   //输出定义wire wire导线
inv     inv(.A(aa), .Y(yy));

initial begin
  aa<=0;       //将0赋值给aa
  #10 aa<=1;   //等10个时间单位后
  #10 aa<=0;
  #10 aa<=1;
  #10 aa<=0;
  #10 $stop;   //仿真停止命令
end
endmodule

4位与非门

`timescale 1ns/10ps
module nand_gate(a,b,y);
input[3:0] a;    //这个和软件编程语言有些不同,[3:0]代表4位数组 例如 1101 ,左边是高位下标3的位
input[3:0] b;
output[3:0] y;
assign y=~(a&b);
endmodule

module nandgate_tb();
reg[3:0] aa,bb;
wire[3:0] yy;
nand_gate nand_gate(.a(aa),.b(bb),.y(yy));
initial begin 
    aa<=4'b0000;bb<=0;     //4'b 代表有4位 b为binary二进制
    #10  aa<=4'b0000;bb<=4'b0000;
    #10  aa<=4'b0100;bb<=4'b1000;
    #10  aa<=4'b0001;bb<=4'b0010;
    #10  aa<=4'b0100;bb<=4'b1000;
    #10  $stop;
end
endmodule

组合逻辑

二选一选择器

计组中的多路选择器

有两种实现方式
方式一

module fn_swv1(a,b,sel,y);
input a;
input b;
input sel;
output y;

assign y=sel?(a^b):(a&b);

endmodule


module fn_sw_tb();
reg a,b,sel;
wire y;
fn_swv1 fn_swv1(.a(a),.b(b),.sel(sel),.y(y));
initial begin
         a<=0;b<=0;sel<=0;
    #10  a<=1;b<=0;sel<=0;
    #10  a<=1;b<=1;sel<=0;
    #10  a<=1;b<=1;sel<=1;
    #10  a<=0;b<=1;sel<=0;
    #10  a<=0;b<=1;sel<=1;
    #10  a<=0;b<=0;sel<=1;

方法二

module fn_swv2(a,b,sel,y);
input a;
input b;
input sel;
output y;

reg y;   //输出需要定义为reg
always@(a or b or sel) begin  //输入变量不能少
    if (sel==1) begin
        y<=a^b;
    end
    else begin
        y<=a&b;
    end
end
endmodule


module fn_sw_tb2();
reg a,b,sel;
wire y;
fn_swv2 fn_swv2(.a(a),.b(b),.sel(sel),.y(y));
initial begin
         a<=0;b<=0;sel<=0;
    #10  a<=1;b<=0;sel<=0;
    #10  a<=1;b<=1;sel<=0;
    #10  a<=1;b<=1;sel<=1;
    #10  a<=0;b<=1;sel<=0;
    #10  a<=0;b<=1;sel<=1;
    #10  a<=0;b<=0;sel<=1;
    #10  a<=1;b<=0;sel<=1;
    #10 $stop;
end
endmodule

sel是多为的情况,当sel2位时就有4种情况

`timescale 1ns/10ps
module fn_swv3(a,b,sel,y);
input a;
input b;
input[1:0] sel;    //一定注意这里,容易忘
output y;

reg y;
always@(a or b or sel) begin    //看的出来和C非常的相似
    case(sel)
        2'b00:begin y<=a&b;end
        2'b01:begin y<=a|b;end
        2'b10:begin y<=a^b;end
        2'b11:begin y<=~(a^b);end
    endcase
end
endmodule


module fn_sw_tb3();
reg[3:0] param;     //四位的para参数 xxxx
wire y;
fn_swv3 fn_swv3(.a(param[0]),.b(param[1]),.sel(param[3:2]),.y(y));    //有点类似数组,不过这里是取第几位上的二进制数
initial begin
         param<=0;
    #200 $stop;   //200个单位后停止运行
end

always #10 param<=param+1;   //每过10个单位param+1

endmodule

源码转补码

`timescale 1ns/10ps

module comp_conv(a,c);
input[7:0] a;
output[7:0] c;

wire[6:0]  b;  //value bit after inversion
wire[7:0]  y;  //complement of negative number

assign b=~a[6:0];
assign y[6:0]=b+1;
assign y[7]=a[7];  //sign bit hold
assign c=a[7]?y:a;

endmodule


module comp_conv_tb();
reg[7:0] aa;
wire[7:0] cc;

comp_conv comp_conv(.a(aa),.c(cc));

initial begin      //正常我们为了验证要把所有的情况都列出,这里图个省事
    aa<=8'b00000000;
    #50 aa<=8'b00000001;
    #50 aa<=8'b00000001;
    #50 aa<=8'b10000111;
    #50 aa<=8'b10110000;
    #50 $stop;
end

endmodule

还可以改写

module comp_conv(a,c);
input[7:0] a;
output[7:0] c;

wire[7:0]  y;  //complement of negative number

assign y={a[7],~a[6:0]+1};
assign c=a[7]?y:a;      //其实还可以进一步改写
endmodule

7段数码管译码器

//       -------
//      |   a   |
//     f|       |b
//      |-------|
//      |   g   |
//     e|       |c
//       -------
//          d
//

`timescale 1ns/10ps
module seg_dec(num,ag);
input[3:0] num;
output[6:0] ag;
reg[6:0] ag;   // a,b,c,d,e,f,g
always@(num)begin
    case(num)
        4'd0: begin ag<=7'b111_1110;end
        4'd1: begin ag<=7'b011_0000;end
        4'd2: begin ag<=7'b110_1101;end
        4'd3: begin ag<=7'b111_1100;end
        4'd4: begin ag<=7'b011_0011;end
        4'd5: begin ag<=7'b101_1011;end
        4'd6: begin ag<=7'b101_1111;end
        4'd7: begin ag<=7'b111_0000;end
        4'd8: begin ag<=7'b111_1111;end
        4'd9: begin ag<=7'b111_1010;end
        default: begin ag<=7'b000_0001;end
    endcase
end
endmodule


module seg_dec_tb();
reg[3:0] n;
wire[6:0] y;

seg_dec seg_dec(.num(n),.ag(y));

initial begin
         n<=0;
    #100 $stop;
end

always #10 n<=n+1;

endmodule

时序逻辑

`timescale 1ns/10ps
module counter(clk,res,y);  //时许逻辑第一个clk第二个res,固定
input clk;
input res;
output[7:0] y;

reg[7:0] y;

wire[7:0] sum;  //
assign sum=y+1;

always@(posedge clk or negedge res) begin //clk的上升沿 res的下降沿 触发
    if(~res)begin
        y<=0;
    end
    else begin
        y<=sum;
    end
end
endmodule


module counter_tb();
reg clk,res;
wire[7:0] y;
counter counter(.clk(clk),.res(res),.y(y));

initial begin     //初始值一定要设定
    clk<=0;res<=0;
    #17 res<=1;   //17这个值是不固定的,只是用于延迟一点开始工作
    #600 $stop;
end

always #5 clk<=~clk;   //时钟的实现

endmodule

其效果是在时钟的上升沿将sum传给y
res的是重置,如果res=0了,他会将y重置为0,res=1时,则一直进行+1操作

四级伪随机码发生器

`timescale 1ns/10ps
module m_gen(clk,res,y);
input clk;
input res;
output y;

reg[3:0] d;
assign y=d[0];

always@(posedge clk or negedge res) begin
    if(~res)begin
        d<=4'b1111;   //不允许全0
    end
    else begin
        d[2:0]<=d[3:1];    //右移一位,有>>运算符,不建议用,老师为解释
        d[3]<=d[3]+d[0];   //模二加,效果类似异或,暂留个问题?
    end
end
endmodule


module m_gen_tb();
reg clk,res;
wire y;
m_gen m_gen(.clk(clk),.res(res),.y(y));

initial begin
    clk<=0;res<=0;
    #17 res<=1;   //
    #400 $stop;
end

always #5 clk<=~clk;

endmodule

秒计数器

这东西挺好玩的

我们有一个23M的时钟,我们在每一个时钟上升将con_t+1,con_t的范围时0-23999999
每次从0到23999999说明走了24000000个时钟周期,也就是1秒,那么我们标记con_t=1,每次到1说明过了1秒。此时已经实现了秒单位。计数器的范围0-9,就像红路灯倒计时一样循环,当到9的时候重置为0

`timescale 1ns/10ps
module s_counter(clk,res,s_num);

input clk;
input res;
output[3:0] s_num;

parameter freq_clk=24;   //24M

reg[24:0] con_t;
reg s_pulse;
reg[3:0] s_num;

always@(posedge clk or negedge res) begin
    if(~res)begin
        con_t<=0;
        s_pulse<=0;
        s_num<=0;
    end
    else begin
        //if(con_t==freq_clk*1000000-1)begin
        if(con_t==freq_clk*1000-1)begin  //方便我们仿真时查看结果
            con_t<=0;
        end
        else begin
            con_t<=con_t+1;
        end
    end

    if(con_t==0)begin
        s_pulse<=1;
    end
    else begin
        s_pulse<=0;
    end

    if(s_pulse==1)begin
        if(s_num==9)begin
            s_num<=0;
        end
        else begin
            s_num<=s_num+1;
        end
    end
    else begin

    end

end
endmodule

 
 module s_counter_tb();
reg clk,res;
wire[3:0] s_num;

 s_counter s_counter(.clk(clk),.res(res),.s_num(s_num));

 initial begin
    clk<=0; res<=0;
    #18 res<=1;
    #1000 $stop; 
 end

always #5 clk<=~clk;

endmodule

综合

将上面的秒计数器和7段数码管组合,我们就是实现了一个0-9反复显示的数码管


module top(clk,res,ag);
input clk j
input res;
output[6:0] ag;

wire[3:0] s_num; //只是内部链接,用wire

s_counter U1(.clk(clk),.reg(reg),.s_num(s_num));  //U1是实例化名 module在同一个目录下就能扫描到
seg_dec U2(.num(s_num),.ag(ag)); 

endmodule

秒分频

课上留下的问题

相邻16点相加输出

没学数电有点难搞,看不懂 2022年12月19日

状态机

三角波发生器

标签:begin,EDA,联系,clk,res,代码,module,input,reg
From: https://www.cnblogs.com/beifangcc/p/16989638.html

相关文章