12.5单端口RAM,JS计数器,流水线乘法器,不重叠序列检测器(状态机+移位寄存器),信号发生器,交通灯

单端口RAM

`timescale 1ns/1ns



module RAM_1port(
    input clk,
    input rst,
    input enb,
    input [6:0]addr,
    input [3:0]w_data,
    output wire [3:0]r_data
);

    reg [6:0]mem[127:0];
    integer i;
    always @(posedge clk or negedge rst) begin
        if(!rst) begin
            for (i=0; i<127 ; i=i+1) begin
                mem[i] <= 'b0;
            end
        end
        else if (enb) begin
            mem[addr] <= w_data;
        end
    end
	
    assign r_data = (!enb)?mem[addr]:'b0;


endmodule

JS计数器

`timescale 1ns/1ns

module JC_counter(
   input                clk ,
   input                rst_n,
 
   output reg [3:0]     Q  
);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) Q <= 'd0;
        else Q <= {~Q[0], Q[3 : 1]};
    end
endmodule

流水线乘法器

  assign mul_1 = mul_b[0]? mul_a: 0;
  assign mul_2 = mul_b[1]? mul_a<<1: 0;
  assign mul_3 = mul_b[2]? mul_a<<2: 0;
  assign mul_4 = mul_b[3]? mul_a<<3: 0;

这步就是竖式乘法,认为是b个a相加在一起,b的最低位上的数字意味着有1个a,b[1]位上的数字意味着有2个a,b[2]意味有4个,B【3】意味有8个。所以就采用移位方式。

  assign sum_1 = {size*(1'b0),mul_r1} + {size*(1'b0),mul_r2};
  assign sum_2 = {size*(1'b0),mul_r3} + {size*(1'b0),mul_r4};

`timescale 1ns/1ns

module multi_pipe#(
	parameter size = 4
)(
	input 						clk 		,   
	input 						rst_n		,
	input	[size-1:0]			mul_a		,
	input	[size-1:0]			mul_b		,
 
 	output	reg	[size*2-1:0]	mul_out		
);
    //parameter 
    parameter N = size * 2;
    //defination
    wire [N - 1 : 0] temp [0 : 3];
    
    reg [N - 1 : 0] adder_0;
    reg [N - 1 : 0] adder_1;
    
    //output 
    genvar i;
    generate
        for(i = 0; i < 4; i = i + 1)begin : loop
            assign temp[i] = mul_b[i] ? mul_a << i : 'd0;
        end
    endgenerate
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) adder_0 <= 'd0;
        else adder_0 <= temp[0] + temp[1];
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) adder_1 <= 'd0;
        else adder_1 <= temp[2] + temp[3];
    end
    
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) mul_out <= 'd0;
        else mul_out <= adder_0 + adder_1;
    end
endmodule

这里注意temp[]的位数是N-1.即两倍的乘法位数。

变量名前的【】表示变量的位宽,每位的位宽。变量名后的【】表示数组长度,相同变量的个数,串在一起。

不重叠序列检测

状态机

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
    
    parameter ZERO=0, ONE=1, TWO=2, THREE=3, FOUR=4, FIVE=5, SIX=6, FAIL=7;
    reg [2:0] state, nstate;
    reg [2:0] cnt;
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else
            cnt <= cnt==6? 1: cnt+1; 
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            state <= ZERO;
        else
            state <= nstate;
    end
    
    always@(*) begin
        if(~rst_n)
            nstate = ZERO;
        else
            case(state)
                ZERO : nstate = data? FAIL : ONE;
                ONE  : nstate = data? TWO  : FAIL;
                TWO  : nstate = data? THREE: FAIL;
                THREE: nstate = data? FOUR : FAIL;
                FOUR : nstate = data? FAIL : FIVE;
                FIVE : nstate = data? FAIL : SIX;
                SIX  : nstate = data? FAIL : ONE;
                FAIL : nstate = cnt==6&&data==0? ONE: FAIL;
                default: nstate = ZERO;
            endcase
    end
    
    always@(*) begin
        if(~rst_n) begin
            match     = 0;
            not_match = 0;
        end
        else begin
            match     = cnt==6&&state==SIX;
            not_match = cnt==6&&state==FAIL;
        end
    end
    
endmodule

FAIL : nstate = cnt==6&&data==0? ONE: FAIL;

移位寄存器

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);
    
    reg [2:0] cnt;
    reg [5:0] data_r;
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else 
            cnt <= cnt==5? 0: cnt+1;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_r <= 6'b0; 
        else
            data_r <= {data_r[4:0], data};
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            match     <= 1'b0;
            not_match <= 1'b0;
        end
        else begin
            match     <= (cnt==5) && ({data_r[4:0], data}==6'b011100);
            not_match <= (cnt==5) && ({data_r[4:0], data}!=6'b011100);
        end
    end
    
endmodule

判断必须要这样判断,不可写为~match。

因为要match时,是要取反的是当下周期,但是由于是非阻塞,此时macth是上个周期的,但非阻塞,就会导致下个Not_match取反的就是上个周期的match而不是当下周期的,下个周期的match取反才是需要的

需要注意由于是非阻塞,所以当前进入的数据会在下一个周期里才会进入寄存器,所以在本周期中如果要输出,就需要额外再移位判断一下

信号发生器

在方波时,

// 仅在方波模式工作的计数器
always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      cnt <= 0;
    else
      cnt <= wave_choise!=0 ? 0:
             cnt        ==19? 0:
             cnt + 1;
end

如果波形选择不是0,即!=0成立,那么cnt就一直保持为0;不然就是==0成立,然后判断cnt是不是等于19,如果是的话,就复位,重新计数,不然就+1

wave <= cnt ==9 ? 20: 
        cnt ==19? 0 :
        wave;

就是cnt是只在方波模式下才工作的,先判断cnt是否==9,是的话就让wave=20;不是的话,就判断是不是等于19,是的话复位到0,不然就保持,这样实现出来的话,每个周期下,前半个周期是低电平,只有到cnt==9时,wave在下个周期设置为20,才会在后半个周期显示为高电平。

`timescale 1ns/1ns
module signal_generator(
	input clk,
	input rst_n,
	input [1:0] wave_choise,
	output reg [4:0]wave
	);

	reg [4:0]cnt;
	reg up;
	always @(posedge clk or negedge rst_n)
		if (!rst_n)
			begin 
				wave <= 0;
				cnt <= 0;
			end
		else case (wave_choise)
		2'b00:				//产生方波,保持0十个时钟,保持20十个时钟
			begin
				if (cnt == 19)
					begin	
						wave <= 0;
						cnt <= 0;
					end
				else if(cnt == 9)
					begin	
						wave <= 20;
						cnt <= cnt + 1;
					end
				else
					begin
						wave <= wave;
						cnt <= cnt + 1;
					end
			end
		2'b01:				//产生锯齿,0递增到20
			begin
				if (wave == 20)
					begin
						wave <= 0;
					end
				else 
					begin
						wave <= wave + 1;
					end
			end
		2'b10:
			begin
				if (wave == 20)
					begin
						wave <= wave - 1;
						up <= 0;
					end
				else if (wave == 0)
					begin
						wave <= wave + 1;
						up <= 1;
					end
				else if (up)
					begin
						wave <= wave + 1;
					end
				else 
					begin
						wave <= wave - 1;
					end
			end
		default:
			begin
				wave <= 1;
			end
	endcase
endmodule

交通灯

竞争与险象

相关推荐
qq_3923999011 小时前
FPGA问题
fpga开发
乌恩大侠19 小时前
PXIe-7976【K410T】
fpga开发
作精本精1 天前
Xilinx FPGA:vivado实现乒乓缓存
fpga开发
深圳信迈科技DSP+ARM+FPGA1 天前
基于X86+FPGA+AI的切割机控制、六轴机器人控制方案
人工智能·fpga开发·视觉检测
Anin蓝天(北京太速科技-陈)1 天前
116-基于5VLX110T FPGA FMC接口功能验证6U CPCI平台
图像处理·嵌入式硬件·fpga开发
作精本精2 天前
Xilinx FPGA:vivado关于真双端口的串口传输数据的实验
fpga开发
迪普微社区2 天前
双芯合璧,双FPGA赋能的软件无线电平台上线!
图像处理·fpga开发·fpga·开发板·通信·射频·雷达监测
程序员不想敲代码啊2 天前
【Emacs Verilog mode保姆级的使用指南】
fpga开发·编辑器·emacs
小达爱学习2 天前
verilog实现PID控制
fpga开发
FPGAmaster创新者2 天前
基于AGX ORIN与FPGA K7实现PCIE高速数据通信/Orin与FPGA高速数据传输/XDMA在linux系统使用教程
linux·嵌入式硬件·fpga开发