9.18数电学习,(数电结束)

8.半导体储存期间

RAM

Xilinx中集成的36KB,18KB 不做解释

//调用块状RAM硬件原语参照表   //
   // DATA_WIDTH_A/B | BRAM_SIZE | RAM Depth | ADDRA/B Width | WEA/B Width //
   // ===============|===========|===========|===============|=============//
   //     19-36      |  "36Kb"   |    1024   |    10-bit     |    4-bit    //
   //     10-18      |  "36Kb"   |    2048   |    11-bit     |    2-bit    //
   //     10-18      |  "18Kb"   |    1024   |    10-bit     |    2-bit    //
   //      5-9       |  "36Kb"   |    4096   |    12-bit     |    1-bit    //
   //      5-9       |  "18Kb"   |    2048   |    11-bit     |    1-bit    //
   //      3-4       |  "36Kb"   |    8192   |    13-bit     |    1-bit    //
   //      3-4       |  "18Kb"   |    4096   |    12-bit     |    1-bit    //
   //        2       |  "36Kb"   |   16384   |    14-bit     |    1-bit    //
   //        2       |  "18Kb"   |    8192   |    13-bit     |    1-bit    //
   //        1       |  "36Kb"   |   32768   |    15-bit     |    1-bit    //
   //        1       |  "18Kb"   |   16384   |    14-bit     |    1-bit    //
   //

RTL 编写ram

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/09/18 09:45:06
// Design Name: 
// Module Name: csdn_bram
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

//单口ram
module csdn_bram #(
    parameter ADDR_WITHE = 8, //地址位宽8
    parameter DATA_WITHE = 8    //位宽8
)
(
       input clk,
       input en,                    //读,写使能
       input we,                    //we = 1 为写 ,we = 0为读 
       input [ADDR_WITHE-1:0]addr,
       input [DATA_WITHE-1:0]din,
       output [DATA_WITHE-1:0]dout
);
reg[DATA_WITHE-1:0] mem [(1<<ADDR_WITHE)-1:0];
//写控制
always@(posedge clk)
if(en&we)
    mem[addr]<=din;//读入

//读控制
reg [DATA_WITHE-1:0]dout_r;
always@(posedge clk)
if(en&~we)//读请求
   dout_r<=mem[addr];//读出 (延迟一个时钟输出)

assign dout = dout_r;   
endmodule

ROM

1.Xilinx可以导入ROM文件
2.自己写的RTL代码如下

//单口rom
module csdn_bram #(
    parameter ADDR_WITHE = 8, //地址位宽8
    parameter DATA_WITHE = 10    //位宽10
)
(
       input clk,
       input en,                    //读,写使能
       input [ADDR_WITHE-1:0]addr,
       output [DATA_WITHE-1:0]dout
);
parameter MEM_DEPTH = 1<<ADDR_WITHE;
//定义内存
reg [DATA_WITHE-1:0] mem [MEM_DEPTH-1:0];

//初始化为0
integer i;
initial
    begin
        for (i=0;i<(1<<MEM_DEPTH;i=i+1)
            begin
                mem[i] <= 0;
            end
    end

//读控制
reg [DATA_WITHE-1:0]dout_r;
always@ (posedge clk)
    begin
        if(en)
            begin
                dout_r <= mem[addr];
            end
    end
assign dout = dout_r;

//或者一部组合逻辑读
/*
reg [DATA_WITHE-1:0]dout_r;
always @ (*)
	begin
		if(en)
			dout_r = mem[addr];
	end
assign dout = dout_r;
*/

endmodule

双口ram和rom需要根据情况加优先级判断中断

代码差不多这样
1.判断优先级,选择则哪路输出

always@(posedge clk)
begin
	casez (in1,in2,in3,in4)
	    4'b0001: clzres[1:0] <= 2'b11;
	    4'b001?: clzres[1:0] <= 2'b10;
	    4'b01??: clzres[1:0] <= 2'b01;
	    default: clzres[1:0] <= 2'b00;
	endcase
end

2.异步读控制

always @ (address or cs or we or oe)
begin : MEM_READ
    if (cs && !we && oe) begin
         data_out = mem[address];
    end
end

3.同步双口ram

//优先级判断
always @ (posedge clk)
begin : MEM_WRITE
  if ( cs_0 && we_0 ) begin
     mem[address_0] <= data_0;
  end 
  else if (cs_1 && we_1) begin 
     mem[address_1] <= data_1;
  end
end

仿真初始化写法
转自
FPGA 实现 bram (block RAM).

	initial begin
	
		cs = 1'b0;
		we = 1'b0;
		oe = 1'b0;
		address = 8'd0;
		data_in = 8'h00;
		#20
		@(negedge clk) begin//read		
			cs = 1'b1;
			oe = 1'b1;
		end
		
		for (i = 0; i < 256; i = i + 1) begin
			@(negedge clk)
				address = i;
		end
		
		@(negedge clk) begin//write
			we = 1'b1;
			oe = 1'b0;
		end
		
		for (i = 0; i < 256; i = i + 1) begin
			@(negedge clk) begin
				address = i;
				//此处如何给输入数据?
				data_in = data_in  + 1;
			end
		end
		
		@(negedge clk) begin//read
			we = 1'b0;
			oe = 1'b1;
		end
		
		for (i = 0; i < 256; i = i + 1) begin
			@(negedge clk)
				address = i;
		end
		
		@(negedge clk)
			cs = 1'b0;
		 //#100 $finish;
		#100 $stop;

其中:@(negedge clk) 在仿真initial中也属于时间向下走,如#20,更加任意控制数据的输入和输出,使用状态机写也类似

10 Verilog硬件描述语言实例

其他略:
状态机:
分类1:按照输出类型是否包含输入的函数
1.Moore型状态机:输出时当前状态的函数 (简单)
2.Mealy:SHUCHU 输出时当前状态和输入的函数
比较:Mealy输入状态变化,则输出立刻变化,而Moore因为输出逻辑不包含输入,所以需要等待到下一个时钟沿来临输出才能变化。

在这里插入图片描述

分类2:verilog 写法
分类:一段(时序逻辑),二段(状态变换时序逻辑,输出组合逻辑),三段

状态机的状态转移图,通常也可根据输入和内部条件画出。一般来说,状态机的设计包含下列设计步骤:
• 根据需求和设计原则,确定是 Moore 型还是 Mealy 型状态机;
• 分析状态机的所有状态,对每一状态选择合适的编码方式,进行编码;
• 根据状态转移关系和输出绘出状态转移图;
• 构建合适的状态机结构,对状态机进行硬件描述。

状态机的描述通常有三种方法,称为一段式状态机,二段式状态机和三段式状态机。状态机的描述通常包含以
下四部分:
1)利用参数定义语句 parameter 描述状态机各个状态名称,即状态编码。状态编码通常有很多方法包含自然二
进制编码, One-hot 编码,格雷编码码等;
2)用时序的 always 块描述状态触发器实现状态存储;
3)使用敏感表和 case 语句(也采用 if-else 等价语句)描述状态转换逻辑;
4)描述状态机的输出逻辑。
下面根据状态机的三种方法,来比较各种方法的优劣。
在这里插入图片描述

  • 一段式状态机是应该避免使用的,该写法仅仅适用于非常简单的状态机设计,不符合组合逻辑与时序逻辑分开的原
    则,整个结构代码也不清晰,不利用维护和修改。
    但比较直观。
  • 大的计数应该写在状态机外面,通过使能或者计数的高位判断进入下一次状态机,这样可以减少case+LUT级联的路径长度。
module detect_2(
input clk_i,
input rst_n_i,
output out_o
);
reg out_r;
//状态声明和状态编码
reg [1:0] Current_state;
reg [1:0] Next_state;
parameter [1:0] S0=2'b00;
parameter [1:0] S1=2'b01;
parameter [1:0] S2=2'b10;
parameter [1:0] S3=2'b11;
//时序逻辑:描述状态转换
always@(posedge clk_i)
begin
if(!rst_n_i)
Current_state<=0;
else
Current_state<=Next_state;
end
//组合逻辑:描述下一状态和输出
always@(*)
begin
case(Current_state)
S0 :
begin
out_r=1'b0;
Next_state= S1;
end
S1 :
begin
out_r=1'b1;
Next_state= S2;
end
S2 :
begin
out_r=1'b0;
Next_state= S3;
end
S3 :
begin
out_r=1'b1;
Next_state=Next_state;
end
endcase
end
assign out_o=out_r;
endmodule
  • 两段式状态机采用两个 always 模块实现状态机的功能,其中一个 always 采用同步时序逻辑描述状态转移,另一个
    always 采用组合逻辑来判断状态条件转移。两段式状态机是推荐的状态机设计方法。
module detect_3(
input clk_i,
input rst_n_i,
output out_o
);
reg out_r;
//状态声明和状态编码
reg [1:0] Current_state;
reg [1:0] Next_state;
parameter [1:0] S0=2'b00;
parameter [1:0] S1=2'b01;
parameter [1:0] S2=2'b10;
parameter [1:0] S3=2'b11;
//时序逻辑:描述状态转换
always@(posedge clk_i)
begin
if(!rst_n_i)
Current_state<=0;
else
Current_state<=Next_state;
end
//组合逻辑:描述下一状态
always@(*)
begin
case(Current_state)
S0:
Next_state = S1;
S1:
Next_state = S2;
S2:
Next_state = S3;
S3:
Next_state = Next_state;
default :
Next_state = S0;
endcase
end
//输出逻辑:让输出 out,经过寄存器 out_r 锁存后输出,消除毛刺
always@(*)
begin
case(Current_state)
S0,S2:
out_r<=1'b0;
S1,S3:
out_r<=1'b1;
default :
out_r<=out_r;
endcase
end assign out_o=out_r;

三段式状态机在第一个 always 模块采用同步时序逻辑方式描述状态转移,第二个 always 模块采用组合逻辑方
式描述状态转移规律,第三个 always 描述电路的输出。**通常让输出信号经过寄存器缓存之后再输出,消除电路毛刺。**这种状态机也是比较推崇的,主要是由于维护方便,组合逻辑与时序逻辑完全独立。

例题:自动售卖机
状态转换图

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/09/18 13:25:44
// Design Name: 
// Module Name: Auto_sall
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
//三段式状态机

module Auto_sall(
/*
模块:自动售货机电路
描述: 投币口每次只能投入一枚五角或一元硬币。
       投入一元五角给个饮料,投入两元(2个一元),在给出饮料的同时找回一枚五角硬币
       投币时只能一个一个投
设计分析:抽象七个变量
    - clk :时钟输入                 in
    - rst_n:系统复位信号             in
    - half_dollar: 投入五角信号       in
    - one_dollat : 投入一元硬币       in
    - half_out: 找回五角              out
    - dispense: 机器售出一瓶饮料        out
    - collect: 提示投币者取走饮料          out
*/
/*
状态分析:
实际情况买一瓶饮料投币情况
- 2个一元
- 1个1元1个5角
- 3个5角
*/
input clk,
input rst_n,
input half_dollar,
input one_dollar,
output half_out,
output dispense,
output collect
    );

//定义状态,二进制编码
parameter IDLE = 2'd0,ONE = 2'd1,HALF0 =2'd2,HALF1 = 2'd3;

//经过分析判断,电路为Moore状态机,即输入数据改变后,需要等待时钟到来数据才会变化
reg [1:0] next_state;
reg [1:0] current_state;

//时序逻辑,状态变换
always @ (posedge clk)
    begin
        if(~rst_n)  //同步复位
            begin
                current_state <=IDLE;
            end
        else
            begin
                current_state <= next_state;
            end
    end

//组合逻辑,描述下一状态
always @ (*)
    begin
        case(current_state)
                IDLE:begin
                    if(one_dollar&(~half_dollar))
                        begin
                            next_state = ONE;
                        end
                    else if(~one_dollar&half_dollar)
                        begin
                            next_state = HALF0;
                        end
                    else
                        begin
                            next_state <= IDLE;
                        end
                end
                ONE:begin
                    if((one_dollar&(~half_dollar))|(~one_dollar&half_dollar))
                        begin
                            next_state <= IDLE;
                        end
                    else
                        begin
                            next_state = ONE;
                        end
                end
                HALF0:begin
                    if(one_dollar&(~half_dollar))
                        begin
                            next_state <= IDLE;
                        end
                    else if(~one_dollar&half_dollar)
                        begin
                            next_state = HALF1;
                        end
                    else
                        begin
                            next_state = HALF0;
                        end
                end
                HALF1:begin
                    if((one_dollar&(~half_dollar))|(~one_dollar&half_dollar))
                        begin
                            next_state <= IDLE;
                        end
                    else
                        begin
                            next_state = HALF1;
                        end
                end
        endcase
    end

//组合输出逻辑,描述输出(使用锁存器),也可以在加一个寄存器输出消除毛刺
reg half_out_r;
reg dispense_r;
always @ (*)
    begin
        case(current_state)
            IDLE:begin
                half_out_r = 0;
                dispense_r = 0;
            end
            ONE:begin
                if(one_dollar&(~half_dollar))
                    begin
                        half_out_r = 1;
                        dispense_r = 1;
                    end
                else if(~one_dollar&half_dollar)
                    begin
                         half_out_r = 0;
                         dispense_r = 1;
                    end
                else
                    begin
                        half_out_r = 0;
                        dispense_r = 0;
                    end
            end
            HALF0:begin
                if(one_dollar&(~half_dollar))
                    begin
                        half_out_r = 0;
                        dispense_r = 1;
                    end
                else if(~one_dollar&half_dollar)
                    begin
                         half_out_r = 0;
                         dispense_r = 0;
                    end
                else
                    begin
                        half_out_r = 0;
                        dispense_r = 0;
                    end
            end
            HALF1:begin
            if(one_dollar&(~half_dollar))   
                begin                       
                    half_out_r = 1;         
                    dispense_r = 1;         
                end                         
            else if(~one_dollar&half_dollar)
                begin                       
                     half_out_r = 0;        
                     dispense_r = 1;        
                end                         
            else                            
                begin                       
                    half_out_r = 0;         
                    dispense_r = 0;         
                end                         
            end
        endcase
    end

assign half_out=half_out_r;
assign dispense = dispense_r;
endmodule

也可以对输出打一拍消除毛刺

仿真

module test(
);
reg clk;
reg rst_n;

parameter clk_period=50;
parameter clk_half_period=clk_period/2;
 

reg half_dollar;
reg one_dollar;

// 初始化          
initial
    begin   
      clk=1;
      rst_n = 0;
      one_dollar=0;
      half_dollar = 0;
      
      #200 rst_n = 1;
      //
        @(posedge clk) 
        
        @(posedge clk)  //1元
            begin
                one_dollar =1;
                half_dollar =0;
            end
        @(posedge clk)  //0.5元
                begin
                    one_dollar =0;
                    half_dollar =1;
                end
        //
        @(posedge clk)  //1元
            begin
                one_dollar =1;
                half_dollar =0;
            end
 
         @(posedge clk)  //1元
                begin
                    one_dollar =1;
                    half_dollar =0;
                end
        //
         @(posedge clk)  //0.5元
                    begin
                        one_dollar =0;
                        half_dollar =1;
                    end
        @(posedge clk)  //1元
                        begin
                            one_dollar =1;
                            half_dollar =0;
                        end
        //
                 @(posedge clk)  //0.5元
                   begin
                       one_dollar =0;
                       half_dollar =1;
                   end
                @(posedge clk)  //0.5元
                       begin
                           one_dollar =0;
                           half_dollar =1;
                       end
              @(posedge clk)  //0.5元
                       begin
                           one_dollar =0;
                           half_dollar =1;
                       end
              @(posedge clk)  //0元
                      begin
                          one_dollar =0;
                          half_dollar =0;
                      end 
                
    end

always                                                 
  #clk_half_period  clk=~clk;

Auto_sall A1(
.clk(clk),
.rst_n(rst_n),
.half_dollar(half_dollar),
.one_dollar(one_dollar)
    );

endmodule

结果正确

11.脉冲变换电路 略

数模与模数转换器 略

A/D种类:
1.逐次逼近性:类似不断加减砝码(这里是电压),最后确定
2.双积分型:先把模拟变量转换一个中间变量,然后在量化编码。
3.流水线型:速度快:原理跟二分法很类似,只不过残差为2倍的差值,而且起始每一级可能不同,与上一级位置有关
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值